diff --git a/.github/ISSUE_TEMPLATE/3_customer-feedback.yml b/.github/ISSUE_TEMPLATE/3_customer-feedback.yml index 1b9fabeac3..1d2a5fd4cc 100644 --- a/.github/ISSUE_TEMPLATE/3_customer-feedback.yml +++ b/.github/ISSUE_TEMPLATE/3_customer-feedback.yml @@ -63,4 +63,10 @@ body: validations: required: true attributes: - label: Document Id \ No newline at end of file + label: Document Id + - type: input + id: platformId + validations: + required: true + attributes: + label: Platform Id diff --git a/.github/workflows/auto-publish.yml b/.github/workflows/auto-publish.yml new file mode 100644 index 0000000000..55f0e4f5f8 --- /dev/null +++ b/.github/workflows/auto-publish.yml @@ -0,0 +1,39 @@ +name: auto-publish +run-name: Automatically publish documentation +on: + schedule: + # Run at 2:00 AM UTC on Wednesday and Friday + - cron: '0 2 * * WED,FRI' +jobs: + auto-publish: + runs-on: ubuntu-latest + permissions: + contents: write + defaults: + run: + shell: bash + working-directory: ./ + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Check out main + run: | + echo "Checking out main branch" + git config user.name github-actions + git config user.email github-actions@github.com + git checkout main + - name: Check out live + run: | + echo "Checking out live branch" + git checkout live + - name: Merge from main into live + run: | + echo "Merging from main to live" + git merge main + - name: Push changes + run: | + echo "Pushing changes to live branch" + git push origin live + diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000000..47a6050709 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,6 @@ +{ + "MD025": false, + "MD033": { + "allowed_elements": ["kbd"] + } +} diff --git a/.openpublishing.build.ps1 b/.openpublishing.build.ps1 deleted file mode 100644 index aadef76202..0000000000 --- a/.openpublishing.build.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -param( - [string]$buildCorePowershellUrl = "https://opbuildstorageprod.blob.core.windows.net/opps1container/.openpublishing.buildcore.ps1", - [string]$parameters -) -# Main -$errorActionPreference = 'Stop' - -# Step-1: Download buildcore script to local -echo "download build core script to local with source url: $buildCorePowershellUrl" -$repositoryRoot = Split-Path -Parent $MyInvocation.MyCommand.Definition -$buildCorePowershellDestination = "$repositoryRoot\.openpublishing.buildcore.ps1" -Invoke-WebRequest $buildCorePowershellUrl -OutFile "$buildCorePowershellDestination" - -# Step-2: Run build core -echo "run build core script with parameters: $parameters" -& "$buildCorePowershellDestination" "$parameters" -exit $LASTEXITCODE diff --git a/.openpublishing.publish.config.json b/.openpublishing.publish.config.json index 677a8230e4..8eefcf113f 100644 --- a/.openpublishing.publish.config.json +++ b/.openpublishing.publish.config.json @@ -27,6 +27,10 @@ "excel-js-1.15", "excel-js-1.16", "excel-js-1.17", + "excel-js-1.18", + "excel-js-1.19", + "excel-js-1.20", + "excel-js-desktop-1.1", "excel-js-online", "onenote-js-1.1", "outlook-js-preview", @@ -44,12 +48,17 @@ "outlook-js-1.12", "outlook-js-1.13", "outlook-js-1.14", + "outlook-js-1.15", "powerpoint-js-preview", "powerpoint-js-1.1", "powerpoint-js-1.2", "powerpoint-js-1.3", "powerpoint-js-1.4", "powerpoint-js-1.5", + "powerpoint-js-1.6", + "powerpoint-js-1.7", + "powerpoint-js-1.8", + "powerpoint-js-1.9", "visio-js-1.1", "word-js-preview", "word-js-1.1", @@ -60,10 +69,14 @@ "word-js-1.6", "word-js-1.7", "word-js-1.8", + "word-js-1.9", "word-js-1.3-hidden-document", "word-js-1.4-hidden-document", "word-js-1.5-hidden-document", "word-js-desktop-1.1", + "word-js-desktop-1.2", + "word-js-desktop-1.3", + "word-js-desktop-1.4", "word-js-online" ], "open_to_public_contributors": true, @@ -97,6 +110,12 @@ "url": "https://github.com/Microsoft/templates.docs.msft", "branch": "main", "branch_mapping": {} + }, + { + "path_to_root": "reusable-content", + "url": "https://github.com/MicrosoftDocs/reusable-content/", + "branch": "main", + "branch_mapping": {} } ], "branch_target_mapping": {}, diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index 86884e08be..1e81523483 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -1,9 +1,17 @@ { "redirections": [ - { + { + "source_path": "docs/develop/teams-toolkit-overview.md", + "redirect_url": "/office/dev/add-ins/develop/agents-toolkit-overview" + }, + { "source_path": "docs/develop/grant-admin-consent-to-an-add-in.md", "redirect_url": "/entra/identity-platform/quickstart-configure-app-access-web-apis#more-on-api-permissions-and-admin-consent" }, + { + "source_path": "docs/publish/custom-protocol-handler.md", + "redirect_url": "/office/dev/add-ins/publish/manage-trust-options" + }, { "source_path": "docs/testing/debug-with-vs-extension.md", "redirect_url": "/office/dev/add-ins/testing/debug-add-ins-overview" @@ -54,11 +62,11 @@ }, { "source_path": "docs/reference/outlook-api-reference-latest.md", - "redirect_url": "/javascript/api/outlook?view=outlook-js-1.14" + "redirect_url": "/javascript/api/outlook?view=outlook-js-1.15" }, { "source_path": "docs/reference/powerpoint-api-reference.md", - "redirect_url": "/javascript/api/powerpoint?view=powerpoint-js-1.1" + "redirect_url": "/javascript/api/powerpoint?view=powerpoint-js-preview" }, { "source_path": "docs/reference/visio-api-reference.md", @@ -86,11 +94,11 @@ }, { "source_path": "docs/excel/excel-add-ins-get-started-vue.md", - "redirect_url": "/office/dev/add-ins/quickstarts/excel-quickstart-yo" + "redirect_url": "/office/dev/add-ins/quickstarts/excel-quickstart-jquery" }, { "source_path": "docs/quickstarts/excel-quickstart-vue.md", - "redirect_url": "/office/dev/add-ins/quickstarts/excel-quickstart-yo" + "redirect_url": "/office/dev/add-ins/quickstarts/excel-quickstart-jquery" }, { "source_path": "docs/excel/excel-add-ins-get-started-react.md", @@ -394,29 +402,38 @@ "redirect_url": "/office/dev/add-ins/develop/automatically-open-a-task-pane-with-a-document", "redirect_document_id": true }, + { + "source_path": "docs/design/design-toolkits.md", + "redirect_url": "/office/dev/add-ins/design/add-in-design-language" + }, { "source_path": "docs/tutorials/powerpoint-tutorial-customize-ui.md", - "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial" + "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial-yo" }, { "source_path": "docs/tutorials/powerpoint-tutorial-get-slide-metadata.md", - "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial" + "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial-yo" }, { "source_path": "docs/tutorials/powerpoint-tutorial-insert-image.md", - "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial" + "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial-yo" }, { "source_path": "docs/tutorials/powerpoint-tutorial-insert-text.md", - "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial" + "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial-yo" }, { "source_path": "docs/tutorials/powerpoint-tutorial-navigate-slides.md", - "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial" + "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial-yo" }, { "source_path": "docs/tutorials/powerpoint-tutorial-setup.md", - "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial" + "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial-yo" + }, + { + "source_path": "docs/tutorials/powerpoint-tutorial.md", + "redirect_url": "/office/dev/add-ins/tutorials/powerpoint-tutorial-yo", + "redirect_document_id": true }, { "source_path": "docs/tutorials/excel-tutorial-create-chart.md", @@ -470,6 +487,14 @@ "source_path": "docs/outlook/add-in-commands-for-outlook.md", "redirect_url": "/office/dev/add-ins/develop/create-addin-commands" }, + { + "source_path": "docs/outlook/troubleshoot-event-based-and-spam-reporting-add-ins.md", + "redirect_url": "/office/dev/add-ins/testing/troubleshoot-event-based-and-spam-reporting-add-ins" + }, + { + "source_path": "docs/outlook/autolaunch.md", + "redirect_url": "/office/dev/add-ins/develop/event-based-activation" + }, { "source_path": "docs/publish/centralized-deployment.md", "redirect_url": "/office/dev/add-ins/publish/publish" @@ -1277,6 +1302,14 @@ "source_path": "docs/reference/overview/project-add-ins-reference-overview.md", "redirect_url": "/office/dev/add-ins/project/overview" }, + { + "source_path": "docs/outlook/autolaunch-store-options.md", + "redirect_url": "/office/dev/add-ins/publish/autolaunch-store-options" + }, + { + "source_path": "docs/outlook/debug-autolaunch.md", + "redirect_url": "/office/dev/add-ins/testing/debug-autolaunch" + }, { "source_path": "docs/outlook/match-strings-in-an-item-as-well-known-entities.md", "redirect_url": "/office/dev/add-ins/outlook/contextual-outlook-add-ins" @@ -1289,9 +1322,53 @@ "source_path": "docs/outlook/use-regular-expressions-to-show-an-outlook-add-in.md", "redirect_url": "/office/dev/add-ins/outlook/contextual-outlook-add-ins" }, + { + "source_path": "docs/outlook/use-sso-in-event-based-activation.md", + "redirect_url": "/office/dev/add-ins/develop/use-sso-in-event-based-activation" + }, + { + "source_path": "docs/develop/extended-overrides.md", + "redirect_url": "/javascript/api/manifest/extendedoverrides" + }, { "source_path": "docs/outlook/activation-rules.md", "redirect_url": "/javascript/api/manifest/rule" + }, + { + "source_path": "docs/outlook/get-and-set-item-data-in-a-compose-form.md", + "redirect_url": "/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets" + }, + { + "source_path": "docs/outlook/item-data.md", + "redirect_url": "/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets" + }, + { + "source_path": "docs/outlook/privacy-and-security.md", + "redirect_url": "/office/dev/add-ins/concepts/privacy-and-security" + }, + { + "source_path": "docs/reference/overview/visio-javascript-reference-overview.md", + "redirect_url": "/office/dev/add-ins/visio/visio-overview" + }, + { + "source_path": "docs/visio/index.yml", + "redirect_url": "/office/dev/add-ins/visio/visio-overview" + }, + { + "source_path": "docs/outlook/add-in-requirements.md", + "redirect_url": "/office/dev/add-ins/concepts/requirements-for-running-office-add-ins" + }, + { + "source_path": "docs/outlook/read-scenario.md", + "redirect_url": "/office/dev/add-ins/outlook/outlook-add-ins-overview" + }, + { + "source_path": "docs/outlook/compose-scenario.md", + "redirect_url": "/office/dev/add-ins/outlook/outlook-add-ins-overview" + }, + { + "source_path": "docs/outlook/turn-exchange-tokens-on-off.md", + "redirect_url": "/office/dev/add-ins/develop/faq-legacy-exchange-tokens" } ] -} \ No newline at end of file +} diff --git a/Contributing.md b/Contributing.md index c1f0f43bbd..c712b6b6c3 100644 --- a/Contributing.md +++ b/Contributing.md @@ -30,7 +30,7 @@ Use GitHub to contribute to this documentation without having to clone the repo 2. Once you are on the article in GitHub, sign in to GitHub (get a free account [Join GitHub](https://github.com/join)). 3. Choose the **pencil icon** (edit the file in your fork of this project) and make your changes in the **<>Edit file** window. 4. Scroll to the bottom and enter a description. -5. Choose **Propose file change**>**Create pull request**. +5. Choose **Propose file change** > **Create pull request**. You now have successfully submitted a pull request. Pull requests are typically reviewed within 10 business days. @@ -160,7 +160,7 @@ Once your changes are successfully merged into the main repository, delete the b #### To delete a branch 1. In the Git Bash command prompt, type `git checkout main`. This ensures that you aren't in the branch to be deleted (which isn't allowed). -2. Next, at the command prompt, type `git branch -d `. This deletes the branch on your computer only if it has been successfully merged to the upstream repository. (You can override this behavior with the `–D` flag, but first be sure you want to do this.) +2. Next, at the command prompt, type `git branch -d `. This deletes the branch on your computer only if it has been successfully merged to the upstream repository. (You can override this behavior with the `-D` flag, but first be sure you want to do this.) 3. Finally, type `git push origin :` at the command prompt (a space before the colon and no space after it). This will delete the branch on your GitHub fork. Congratulations, you have successfully contributed to the project! diff --git a/docs/concepts/add-in-development-best-practices.md b/docs/concepts/add-in-development-best-practices.md index 166c206f97..0674c288e7 100644 --- a/docs/concepts/add-in-development-best-practices.md +++ b/docs/concepts/add-in-development-best-practices.md @@ -1,109 +1,116 @@ ---- +--- title: Best practices for developing Office Add-ins description: Apply the best practices when developing Office Add-ins. ms.topic: best-practice -ms.date: 07/18/2024 +ms.date: 07/28/2025 ms.localizationpriority: medium --- # Best practices for developing Office Add-ins -Effective add-ins offer unique and compelling functionality that extends Office applications in a visually appealing way. To create a great add-in, provide an engaging first-time experience for your users, design a first-class UI experience, and optimize your add-in's performance. Apply the best practices described in this article to create add-ins that help your users complete their tasks quickly and efficiently. +Great add-ins provide unique, compelling functionality that extend Office apps in visually appealing ways. To build a successful add-in, you'll need to create an engaging first-time user experience, design a polished UI, and optimize performance. Follow the best practices in this article to help your users complete tasks quickly and efficiently. [!INCLUDE [publish policies note](../includes/note-publish-policies.md)] ## Provide clear value -- Create add-ins that help users complete tasks quickly and efficiently. Focus on scenarios that make sense for Office applications. For example: - - Make core authoring tasks faster and easier, with fewer interruptions. - - Enable new scenarios within Office. - - Embed complementary services within Office applications. - - Improve the Office experience to enhance productivity. -- Make sure that the value of your add-in is clear to users right away by [creating an engaging first-run experience](#create-an-engaging-first-run-experience). -- Learn how to create an [effective AppSource listing](/partner-center/marketplace-offers/create-effective-office-store-listings) to promote your add-in. - - Make the benefits of your add-in clear in your title and description. Don't rely on your brand to communicate what your add-in does. - - Your add-in must provide sufficient value to justify users' investment. Your add-in shouldn't be a simple utility or of limited scope. - - [!INCLUDE [AppSource enterprise info](../includes/appsource-enterprise.md)] +Build add-ins that help users complete tasks quickly and efficiently. Focus on scenarios that make sense for Office apps, such as: + +- Make core authoring tasks faster and easier with fewer interruptions. +- Enable new scenarios within Office. +- Embed complementary services within Office apps. +- Improve the Office experience to enhance productivity. + +Make sure users understand your add-in's value immediately by [creating an engaging first-run experience](#create-an-engaging-first-run-experience). + +When you're ready to promote your add-in, learn how to create an [effective Microsoft Marketplace listing](/partner-center/marketplace-offers/create-effective-office-store-listings). + +- Make your add-in's benefits clear in the title and description. Don't rely only on your brand to communicate what your add-in does. +- Ensure your add-in provides sufficient value to justify users' investment. It shouldn't be just a simple utility or have limited scope. +- [!INCLUDE [Microsoft Marketplace enterprise info](../includes/appsource-enterprise.md)] ## Create an engaging first-run experience -- Engage new users with a highly usable and intuitive first experience. Note that users are still deciding whether to use or abandon an add-in after they download it from the store. +New users are still deciding whether to use or abandon your add-in after downloading it from the store. Here's how to win them over. -- Make the steps that the user needs to take to engage with your add-in clear. Use videos, placemats, paging panels, or other resources to entice users. +- **Make the next steps clear.** Use videos, placemats, paging panels, or other resources to guide users through your add-in. -- Reinforce the value proposition of your add-in on launch, rather than just asking users to sign in. +- **Lead with value, not registration.** Reinforce your add-in's value proposition when it launches rather than immediately asking users to sign in. -- Provide teaching UI to guide users and make your UI personal. +- **Provide helpful guidance.** Include teaching UI to guide users and make the experience feel personal. ![A "Do" versus "Don't" comparison on how to guide your users to use the UI. The "Do" example shows an add-in that includes a button users can click to get started. The "Don't" example shows an add-in with no introductory steps or buttons.](../images/contoso-part-catalog-do-dont.png) -- If your content add-in binds to data in the user's document, include sample data or a template to show users the data format to use. +- **Show users what to expect.** If your content add-in binds to data in the user's document, include sample data or a template to show users the expected data format. ![A "Do" versus "Don't" comparison on including an option to insert sample data in your add-in. The "Do" example shows an add-in that includes a button users can click to insert sample data. The "Don't" example shows an add-in without sample data or buttons.](../images/add-in-title.png) -- Offer [free trials](/partner-center/marketplace-offers/monetize-addins-through-microsoft-commercial-marketplace). If your add-in requires a subscription, make some functionality available without a subscription. +- **Offer free trials.** If your add-in requires a subscription, make some functionality available without one. -- Make the sign-up experience simple. Prefill information, such as email and display name, and skip email verifications. +- **Simplify sign-up.** Prefill information like email and display name, and skip email verifications when possible. -- Avoid pop-up windows. If you have to use them, guide the user to enable your pop-up window. +- **Avoid pop-ups.** If you must use them, guide users on how to enable your pop-up window. -For patterns that you can apply as you develop your first-run experience, see [UX design patterns for Office Add-ins](../design/first-run-experience-patterns.md). +For patterns you can apply when developing your first-run experience, see [UX design patterns for Office Add-ins](../design/first-run-experience-patterns.md). ## Use add-in commands -- Provide relevant UI entry points for your add-in by using add-in commands. For details, including design best practices, see [add-in commands](../design/add-in-commands.md). +Provide relevant UI entry points for your add-in by using add-in commands. These commands help users discover and access your add-in's functionality directly from the Office ribbon. For details and design best practices, see [add-in commands](../design/add-in-commands.md). ## Apply UX design principles -- Ensure that the look and feel and functionality of your add-in complements the Office experience. See [Design the UI of Office Add-ins](../design/add-in-design.md). +Follow these key principles to create add-ins that feel native to Office: -- Favor content over chrome. Avoid superfluous UI elements that don't add value to the user experience. +- **Match the Office experience.** Ensure your add-in's look, feel, and functionality complement the Office experience. See [Design the UI of Office Add-ins](../design/add-in-design.md). -- Keep users in control. Ensure that users understand important decisions, and can easily reverse actions the add-in performs. +- **Prioritize content over chrome.** Avoid unnecessary UI elements that don't add value to the user experience. -- Use branding to inspire trust and orient users. Don't use branding to overwhelm or advertise to users. +- **Keep users in control.** Make sure users understand important decisions and can easily reverse actions your add-in performs. -- Avoid scrolling. Optimize for 1366 x 768 resolution. +- **Use branding thoughtfully.** Inspire trust and help orient users, but don't overwhelm or advertise to them. -- Don't include unlicensed images. +- **Minimize scrolling.** Optimize for 1366 x 768 resolution. -- Use [clear and simple language](../design/voice-guidelines.md) in your add-in. +- **Use licensed images only.** Avoid legal and branding issues that come from unlicensed images. -- Account for accessibility - make your add-in easy for all users to interact with, and accommodate assistive technologies such as screen readers. +- **Write clearly.** Use [clear and simple language](../design/voice-guidelines.md) in your add-in. -- Design for all platforms and input methods, including mouse/keyboard and [touch](#optimize-for-touch). Ensure that your UI is responsive to different form factors. +- **Design for accessibility.** Make your add-in easy for all users to interact with and accommodate assistive technologies like screen readers. See our [accessibility guidelines](../design/accessibility-guidelines.md). + +- **Support all platforms and input methods.** Design for mouse/keyboard and [touch](#optimize-for-touch). Ensure your UI responds well to different form factors. ### Optimize for touch -- Use the [Context.touchEnabled](/javascript/api/office/office.context#office-office-context-touchenabled-member) property to detect whether the Office application that your add-in runs on is touch enabled. +Touch support is essential for modern Office add-ins. + +- **Detect touch support.** Use the [Context.touchEnabled](/javascript/api/office/office.context#office-office-context-touchenabled-member) property to detect whether the Office app your add-in runs on is touch-enabled. > [!NOTE] > This property isn't supported in Outlook. -- Ensure that all controls are appropriately sized for touch interaction. For example, buttons have adequate touch targets, and input boxes are large enough for users to enter input. +- **Size controls appropriately.** Make sure all controls work well with touch interaction. For example, buttons need adequate touch targets, and input boxes should be large enough for users to enter text easily. -- Don't rely on non-touch input methods like hover or right-click. +- **Don't rely on hover or right-click.** These input methods aren't available on touch devices. -- Ensure that your add-in works in both portrait and landscape modes. Be aware that on touch devices, part of your add-in might be hidden by the soft keyboard. +- **Support both orientations.** Ensure your add-in works in both portrait and landscape modes. Remember that on touch devices, the soft keyboard might hide part of your add-in. -- Test your add-in on a real device by using [sideloading](../testing/sideload-an-office-add-in-on-ipad.md). - -> [!NOTE] -> If you're using [Fluent UI React](../quickstarts/fluent-react-quickstart.md) for your design elements, many of these elements are built into the design system. +- **Test on real devices.** Use [sideloading](../testing/sideload-an-office-add-in-on-ipad.md) to test your add-in on actual touch devices. ## Optimize and monitor add-in performance -- Create the perception of fast UI responses. Your add-in should load in 500 ms or less. +Performance directly impacts user satisfaction. Follow these guidelines to keep your add-in fast and responsive: + +- **Aim for quick loading.** Your add-in should load in 500 ms or less to create the perception of fast UI responses. -- Ensure that all user interactions respond in under one second. +- **Respond quickly to interactions.** All user interactions should respond in under one second. -- Provide loading indicators for long-running operations. +- **Show progress for long operations.** Provide loading indicators for operations that take time. -- Use a content delivery network (CDN) to host images, resources, and common libraries. Load as much as you can from one place. +- **Use a CDN.** Host images, resources, and common libraries on a content delivery network (CDN). Load as much as possible from one place. -- Follow standard web practices to optimize your web page. In production, use only minified versions of libraries. Only load resources that you need, and optimize how resources are loaded. +- **Follow web optimization best practices.** In production, use only minified versions of libraries. Load only the resources you need and optimize how they're loaded. -- If operations take time to execute, provide feedback to users. Note the thresholds listed in the following table. For additional information, see [Resource limits and performance optimization for Office Add-ins](../concepts/resource-limits-and-performance-optimization.md). +- **Provide feedback for longer operations.** When operations take time to execute, give users feedback based on the thresholds in the following table. For more information, see [Resource limits and performance optimization for Office Add-ins](../concepts/resource-limits-and-performance-optimization.md). |Interaction class|Target|Upper bound|Human perception| |:-----|:-----|:-----|:-----| @@ -116,32 +123,35 @@ For patterns that you can apply as you develop your first-run experience, see [U |Extended|>500 ms|>10 seconds|Long enough to do something else while waiting. Might need feedback.| |Long running|>5 seconds|>1 minute|Users will certainly do something else.| -- Monitor your service health, and use telemetry to monitor user success. +- **Monitor your service.** Use telemetry to monitor service health and user success. -- Minimize data exchanges between the add-in and the Office document. For more information, see [Avoid using the context.sync method in loops](correlated-objects-pattern.md). +- **Minimize data exchanges.** Reduce data exchanges between your add-in and the Office document. For more information, see [Avoid using the context.sync method in loops](correlated-objects-pattern.md). ## Publish and market your add-in -- Create an [effective AppSource listing](/partner-center/marketplace-offers/create-effective-office-store-listings). +Ready to share your add-in with the world? Here's how to get started. - - Use succinct and descriptive add-in titles. Include no more than 128 characters. +- **Create a Partner Center account.** This process can take time, so if you plan to publish to Microsoft Marketplace, start early. See [Partner Center account](/partner-center/marketplace-offers/open-a-developer-account). - - Write short, compelling, and accurate descriptions of your add-in. Answer the question "What problem does this add-in solve?". +- **Create an effective Microsoft Marketplace listing.** Follow these tips: - - Convey the value proposition of your add-in in your title and description. Don't rely on your brand. + - Use succinct, descriptive titles (128 characters or fewer). + - Write short, compelling descriptions that answer "What problem does this add-in solve?" + - Convey your add-in's value proposition clearly in the title and description. Don't rely only on your brand. -- Create a website to help users find and use your add-in. + Learn more about [creating effective Microsoft Marketplace listings](/partner-center/marketplace-offers/create-effective-office-store-listings). -- Publish your add-in to [AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center). Be sure to follow the AppSource [prepublish checklist](/partner-center/marketplace-offers/checklist) and [submission guide](/partner-center/marketplace-offers/add-in-submission-guide). +- **Publish to Microsoft Marketplace.** Follow the Microsoft Marketplace [prepublish checklist](/partner-center/marketplace-offers/checklist) and [submission guide](/partner-center/marketplace-offers/add-in-submission-guide). Make sure to: - - Ensure that your add-in works error-free in all operating systems, browsers, and devices supported by the minimum set of APIs declared in your add-in manifest. + - Test your add-in thoroughly on all supported operating systems, browsers, and devices. + - Provide detailed testing instructions and resources for certification reviewers. - - Provide detailed testing instructions and resources for certification reviewers to verify the functionality of your add-in. +- **Create a website.** Help users discover your add-in outside of Microsoft Marketplace. -- [Promote your add-in](/partner-center/marketplace-offers/promote-your-office-store-solution) from your website. +- **Promote your add-in** from your website. See [how to promote your add-in](/partner-center/marketplace-offers/promote-your-office-store-solution). > [!IMPORTANT] -> [!INCLUDE [AppSource enterprise info](../includes/appsource-enterprise.md)] +> [!INCLUDE [Microsoft Marketplace enterprise info](../includes/appsource-enterprise.md)] ## Support older Microsoft webviews and Office versions (recommended but not required) diff --git a/docs/concepts/browsers-used-by-office-web-add-ins.md b/docs/concepts/browsers-used-by-office-web-add-ins.md index d8d6177fd7..16e6563a6e 100644 --- a/docs/concepts/browsers-used-by-office-web-add-ins.md +++ b/docs/concepts/browsers-used-by-office-web-add-ins.md @@ -1,8 +1,8 @@ ---- +--- title: Browsers and webview controls used by Office Add-ins description: Specifies how the operating system and Office version determine what webview is used by Office Add-ins. ms.topic: concept-article -ms.date: 04/24/2024 +ms.date: 10/17/2024 ms.localizationpriority: medium --- @@ -23,8 +23,8 @@ Which webview is used depends on: > > We recommend (but don't require) that you continue to support these combinations, at least in a minimal way, by providing users of your add-in a graceful failure message when your add-in is launched in one of these webviews. Keep these additional points in mind: > -> - Office on the web no longer opens in Internet Explorer or Microsoft Edge Legacy. Consequently, [AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center) doesn't test add-ins in Office on these web browsers. -> - AppSource still tests for combinations of platform and Office *desktop* versions that use Trident or EdgeHTML. However, it only issues a warning when the add-in doesn't support these webviews; the add-in isn't rejected by AppSource. +> - Office on the web no longer opens in Internet Explorer or Microsoft Edge Legacy. Consequently, [Microsoft Marketplace](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center) doesn't test add-ins in Office on these web browsers. +> - Microsoft Marketplace still tests for combinations of platform and Office *desktop* versions that use Trident or EdgeHTML. However, it only issues a warning when the add-in doesn't support these webviews; the add-in isn't rejected by Microsoft Marketplace. > - The [Script Lab tool](../overview/explore-with-script-lab.md) no longer supports Trident. > > For more information about supporting Trident or EdgeHTML, including configuring a graceful failure message on your add-in, see [Support older Microsoft webviews and Office versions](../develop/support-ie-11.md). @@ -33,7 +33,7 @@ The following sections specify which browser is used for the various platforms a ## Non-Windows platforms -For these platforms, the platform alone determines the browser that is used. +For these platforms, the platform alone determines the browser that's used. |OS|Office version|Browser| |:-----|:-----|:-----| @@ -55,9 +55,9 @@ An add-in running on Windows might use any of three different webviews: ### Perpetual versions of Office on Windows -For perpetual versions of Office on Windows, the browser that is used is determined by the Office version, whether the license is retail or volume-licensed, and whether the Edge WebView2 (Chromium-based) is installed. The version of Windows doesn't matter, but note that Office Web Add-ins aren't supported on versions earlier than Windows 7 and Office 2021 isn't supported on versions earlier than Windows 10. +For perpetual versions of Office on Windows, the browser that's used is determined by the Office version, whether the license is retail or volume-licensed, and whether the Edge WebView2 (Chromium-based) is installed. The version of Windows doesn't matter, but note that Office Add-ins aren't supported on versions earlier than Windows 7 and Office 2021 and later aren't supported on versions earlier than Windows 10. -To determine whether Office 2016 or Office 2019 is retail or volume-licensed, use the format of the Office version and build number. (For Office 2021, the distinction between volume-licensed and retail doesn't matter.) +To determine whether Office 2016 or Office 2019 is retail or volume-licensed, use the format of the Office version and build number. (For Office 2021 and later, the distinction between volume-licensed and retail doesn't matter.) - **Retail**: For both Office 2016 and 2019, the format is `YYMM (xxxxx.xxxxxx)`, ending with two blocks of five digits; for example, `2206 (Build 15330.20264)`. - **Volume-licensed**: @@ -66,6 +66,7 @@ To determine whether Office 2016 or Office 2019 is retail or volume-licensed, us | Office version | Retail vs. Volume-licensed | WebView2 installed? | Browser | |:-----|:-----|:-----|:-----| +| Office 2024 | Doesn't matter | Yes1 | WebView2 (Microsoft Edge2 Chromium-based) | | Office 2021 | Doesn't matter | Yes1 | WebView2 (Microsoft Edge2 Chromium-based) | | Office 2019 | Retail | Yes1 | WebView2 (Microsoft Edge2 Chromium-based) | | Office 2019 | Retail | No | EdgeHTML (Microsoft Edge Legacy)2, 3
If Edge isn't installed, Trident+ (Internet Explorer 11) is used. | @@ -76,30 +77,30 @@ To determine whether Office 2016 or Office 2019 is retail or volume-licensed, us 1 On Windows versions prior to Windows 11, the WebView2 control must be installed so that Office can embed it. It's installed with perpetual Office 2021 or later; but it isn't automatically installed with Microsoft Edge. If you have an earlier version of perpetual Office, use the instructions for installing the control at [Microsoft Edge WebView2 / Embed web content ... with Microsoft Edge WebView2](https://developer.microsoft.com/microsoft-edge/webview2/). -2 When you use either EdgeHTML or WebView2, the Windows Narrator (sometimes called a "screen reader") reads the `` tag in the page that opens in the task pane. In Trident+, the Narrator reads the title bar of the task pane, which comes from the add-in name that is specified in the add-in's manifest. +<sup>2</sup> When you use either EdgeHTML or WebView2, the Windows Narrator (sometimes called a "screen reader") reads the `<title>` tag in the page that opens in the task pane. In Trident+, the Narrator reads the title bar of the task pane, which comes from the add-in name that's specified in the add-in's manifest. -<sup>3</sup> If your add-in uses an add-in only manifest and includes the **\<Runtimes\>** element in the manifest or it uses the unified manifest and it includes an "extensions.runtimes.lifetime" property, then it won't use EdgeHTML. If the conditions for using WebView2 are met, then the add-in uses WebView2. Otherwise, it uses Trident+. For more information, see [Runtimes](/javascript/api/manifest/runtimes) and [Configure your Outlook add-in for event-based activation](../outlook/autolaunch.md?tabs=jsonmanifest). +<sup>3</sup> If your add-in uses an add-in only manifest and includes the `<Runtimes>` element in the manifest or it uses the unified manifest and it includes an "extensions.runtimes.lifetime" property, then it won't use EdgeHTML. If the conditions for using WebView2 are met, then the add-in uses WebView2. Otherwise, it uses Trident+. For more information, see [Runtimes](/javascript/api/manifest/runtimes) and [Activate add-ins with events](../develop/event-based-activation.md). ### Microsoft 365 subscription versions of Office on Windows -For subscription Office on Windows, the browser that is used is determined by the operating system, the Office version, and whether the WebView2 control is installed. +For subscription Office on Windows, the browser that's used is determined by the operating system, the Office version, and whether the WebView2 control is installed. |OS|Office version| WebView2 installed?|Browser| |:-----|:-----|:-----|:-----| -|Windows 11,<br>Windows 10,<br>Windows 8.1,<br>Windows Server 2022,<br>Windows Server 2019,<br>Windows Server 2016| Microsoft 365 ver. >= 16.0.13530.20424<sup>1</sup>| Yes<sup>2</sup>| WebView2 (Microsoft Edge<sup>3</sup> Chromium-based) | -|Window 11,<br>Windows 10 ver. >= 1903 | Microsoft 365 ver. >= 16.0.13530.20424<sup>1</sup>| No |EdgeHTML (Microsoft Edge Legacy)<sup>3, 4</sup>| -|Windows 11,<br>Windows 10 ver. >= 1903 | Microsoft 365 ver. >= 16.0.11629 *AND* < 16.0.13530.20424<sup>1</sup>| Doesn't matter|EdgeHTML (Microsoft Edge Legacy)<sup>3, 4</sup>| -|Windows 11,<br>Windows 10 ver. >= 1903 | Microsoft 365 ver. < 16.0.11629<sup>1</sup>| Doesn't matter|Trident+ (Internet Explorer 11)| -|Windows 10 ver. < 1903,<br>Windows 8.1| Microsoft 365 | No| Trident+ (Internet Explorer 11)| -|Windows 7 | Microsoft 365| Doesn't matter | Trident+ (Internet Explorer 11)| +|<ul><li>Windows 11</li><li>Windows 10</li><li>Windows 8.1</li><li>Windows Server 2022</li><li>Windows Server 2019</li><li>Windows Server 2016</li></ul>| Microsoft 365 ver. >= 16.0.13530.20424<sup>1</sup>| Yes<sup>2</sup>| WebView2 (Microsoft Edge<sup>3</sup> Chromium-based) | +|<ul><li>Window 11</li><li>Windows 10 ver. >= 1903</li></ul>| Microsoft 365 ver. >= 16.0.13530.20424<sup>1</sup>| No |EdgeHTML (Microsoft Edge Legacy)<sup>3, 4</sup>| +|<ul><li>Windows 11</li><li>Windows 10 ver. >= 1903</li></ul>| Microsoft 365 ver. >= 16.0.11629 *AND* < 16.0.13530.20424<sup>1</sup>| Doesn't matter|EdgeHTML (Microsoft Edge Legacy)<sup>3, 4</sup>| +|<ul><li>Windows 11</li><li>Windows 10 ver. >= 1903</li></ul>| Microsoft 365 ver. < 16.0.11629<sup>1</sup>| Doesn't matter|Trident+ (Internet Explorer 11)| +|<ul><li>Windows 10 ver. < 1903</li><li>Windows 8.1</li></ul>| Microsoft 365 | No| Trident+ (Internet Explorer 11)| +|<ul><li>Windows 7</li></ul>| Microsoft 365| Doesn't matter | Trident+ (Internet Explorer 11)| <sup>1</sup> See the [update history page](/officeupdates/update-history-office365-proplus-by-date) and how to [find your Office client version and update channel](https://support.microsoft.com/office/932788b8-a3ce-44bf-bb09-e334518b8b19) for more details. <sup>2</sup> On Windows versions prior to Windows 11, the WebView2 control must be installed so that Office can embed it. It's installed with Microsoft 365, Version 2101 or later, but it isn't automatically installed with Microsoft Edge. If you have an earlier version of Microsoft 365, use the instructions for installing the control at [Microsoft Edge WebView2 / Embed web content ... with Microsoft Edge WebView2](https://developer.microsoft.com/microsoft-edge/webview2/). On Microsoft 365 builds before 16.0.14326.xxxxx, you must also create the registry key **HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\Win32WebView2** and set its value to `dword:00000001`. -<sup>3</sup> When you use either EdgeHTML or WebView2, the Windows Narrator (sometimes called a "screen reader") reads the `<title>` tag in the page that opens in the task pane. In Trident+, the Narrator reads the title bar of the task pane, which comes from the add-in name that is specified in the add-in's manifest. +<sup>3</sup> When you use either EdgeHTML or WebView2, the Windows Narrator (sometimes called a "screen reader") reads the `<title>` tag in the page that opens in the task pane. In Trident+, the Narrator reads the title bar of the task pane, which comes from the add-in name that's specified in the add-in's manifest. -<sup>4</sup> If your add-in uses an add-in only manifest and includes the **\<Runtimes\>** element in the manifest or it uses the unified manifest and it includes an "extensions.runtimes.lifetime" property, then it won't use EdgeHTML. If the conditions for using WebView2 are met, then the add-in uses WebView2. Otherwise, it uses Trident+. For more information, see [Runtimes](/javascript/api/manifest/runtimes) and [Configure your Outlook add-in for event-based activation](../outlook/autolaunch.md?tabs=jsonmanifest). +<sup>4</sup> If your add-in uses an add-in only manifest and includes the `<Runtimes>` element in the manifest or it uses the unified manifest and it includes an "extensions.runtimes.lifetime" property, then it won't use EdgeHTML. If the conditions for using WebView2 are met, then the add-in uses WebView2. Otherwise, it uses Trident+. For more information, see [Runtimes](/javascript/api/manifest/runtimes) and [Activate add-ins with events](../develop/event-based-activation.md). ## Working with Trident+ (Internet Explorer 11) @@ -120,11 +121,11 @@ Office Add-ins don't support Service Workers when EdgeHTML is used. They're supp ### Scroll bar doesn't appear in task pane -By default, scroll bars in EdgeHTML and WebView2 are hidden until hovered over. To ensure that the scroll bar is always visible, the CSS styling that applies to the `<body>` element of the pages in the task pane should include the [-ms-overflow-style](https://reference.codeproject.com/css/-ms-overflow-style) property and it should be set to `scrollbar`. +By default, scroll bars in EdgeHTML and WebView2 are hidden until hovered over. To ensure that the scroll bar is always visible, the CSS styling that applies to the `<body>` element of the pages in the task pane should include the [-ms-overflow-style](https://devdoc.net/web/developer.mozilla.org/en-US/docs/Web/CSS/-ms-overflow-style.html) property and it should be set to `scrollbar`. ### When debugging with the Microsoft Edge DevTools, the add-in crashes or reloads -Setting breakpoints in the [Microsoft Edge DevTools](https://www.microsoft.com/p/microsoft-edge-devtools-preview/9mzbfrmz0mnj?rtc=1&activetab=pivot%3Aoverviewtab) for EdgeHTML can cause Office to think that the add-in is hung. It will automatically reload the add-in when this happens. To prevent this, add the following Registry key and value to the development computer: `[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\16.0\Wef]"AlertInterval"=dword:00000000`. +Setting breakpoints in the [Microsoft Edge DevTools](https://apps.microsoft.com/detail/9mzbfrmz0mnj) for EdgeHTML can cause Office to think that the add-in is hung. It will automatically reload the add-in when this happens. To prevent this, add the following Registry key and value to the development computer: `[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\16.0\Wef]"AlertInterval"=dword:00000000`. ### When the add-in tries to open, get "ADD-IN ERROR We can't open this add-in from the localhost" error @@ -152,7 +153,7 @@ To determine if a document is WIP-protected, follow these steps. 1. Open the file. 1. Select the **File** tab on the ribbon. 1. Select **Info**. -1. In the upper section of the **Info** page, just below the file name, a WIP-enabled document will have a briefcase icon followed by **Managed by Work (…)**. +1. In the upper section of the **Info** page, just below the file name, a WIP-enabled document will have a briefcase icon followed by **Managed by Work (...)**. > [!NOTE] > Support for WebView2 in WIP-enabled documents was added with build 16.0.16626.20132. If you're on an older build, your runtime defaults to **EdgeHTML (Microsoft Edge Legacy)**, regardless of policy. diff --git a/docs/concepts/correlated-objects-pattern.md b/docs/concepts/correlated-objects-pattern.md index 5467d0d753..f290f78703 100644 --- a/docs/concepts/correlated-objects-pattern.md +++ b/docs/concepts/correlated-objects-pattern.md @@ -2,7 +2,7 @@ title: Avoid using the context.sync method in loops description: Learn how to use the split loop and correlated objects patterns to avoid calling context.sync in a loop. ms.topic: best-practice -ms.date: 08/18/2023 +ms.date: 09/03/2025 ms.localizationpriority: medium --- @@ -10,9 +10,9 @@ ms.localizationpriority: medium # Avoid using the context.sync method in loops > [!NOTE] -> This article assumes that you're beyond the beginning stage of working with at least one of the four application-specific Office JavaScript APIs—for Excel, Word, OneNote, and Visio—that use a batch system to interact with the Office document. In particular, you should know what a call of `context.sync` does and you should know what a collection object is. If you're not at that stage, please start with [Understanding the Office JavaScript API](../develop/understanding-the-javascript-api-for-office.md) and the documentation linked to under "application-specific" in that article. +> This article assumes that you're beyond the beginning stage of working with at least one of the four application-specific Office JavaScript APIs—for Excel, Word, OneNote, and Visio—that use a batch system to interact with the Office document. In particular, you should know what a call to `context.sync` does and you should know what a collection object is. If you're not at that stage, please start with [Understanding the Office JavaScript API](../develop/understanding-the-javascript-api-for-office.md) and the documentation linked to under "application-specific" in that article. -For some programming scenarios in Office Add-ins that use one of the application-specific API models (for Excel, Word, PowerPoint, OneNote, and Visio), your code needs to read, write, or process some property from every member of a collection object. For example, an Excel add-in that needs to get the values of every cell in a particular table column or a Word add-in that needs to highlight every instance of a string in the document. You need to iterate over the members in the `items` property of the collection object; but, for performance reasons, you need to avoid calling `context.sync` in every iteration of the loop. Every call of `context.sync` is a round trip from the add-in to the Office document. Repeated round trips hurt performance, especially if the add-in is running in Office on the web because the round trips go across the internet. +Office Add-ins that use one of the [application-specific API models](../develop/application-specific-api-model.md) may have scenarios that require your code to read or write some property from every member of a collection object. For example, an Excel add-in that gets the values of every cell in a particular table column or a Word add-in that highlights every instance of a string in the document. You will need to iterate over the members in the `items` property of the collection object; but, for performance reasons, you should to avoid calling `context.sync` in every iteration of the loop. Every call of `context.sync` is a round trip from the add-in to the Office document. Repeated round trips hurt performance, especially if the add-in is running in Office on the web because the round trips go across the internet. > [!NOTE] > All examples in this article use `for` loops but the practices described apply to any loop statement that can iterate through an array, including the following: @@ -34,13 +34,13 @@ For some programming scenarios in Office Add-ins that use one of the application > - `Array.reduceRight` > - `Array.some` +> [!NOTE] +> It's generally a good practice to put have a final `context.sync` just before the closing "}" character of the application `run` function (such as `Excel.run`, `Word.run`, etc.). This is because the `run` function makes a hidden call of `context.sync` as the last thing it does if, and only if, there are queued commands that haven't yet been synchronized. The fact that this call is hidden can be confusing, so we generally recommend that you add the explicit `context.sync`. However, given that this article is about minimizing calls of `context.sync`, it is actually more confusing to add an entirely unnecessary final `context.sync`. So, in this article, we leave it out when there are no unsynchronized commands at the end of the `run`. + ## Writing to the document In the simplest case, you are only writing to members of a collection object, not reading their properties. For example, the following code highlights in yellow every instance of "the" in a Word document. -> [!NOTE] -> It's generally a good practice to put have a final `context.sync` just before the closing "}" character of the application `run` function (such as `Excel.run`, `Word.run`, etc.). This is because the `run` function makes a hidden call of `context.sync` as the last thing it does if, and only if, there are queued commands that haven't yet been synchronized. The fact that this call is hidden can be confusing, so we generally recommend that you add the explicit `context.sync`. However, given that this article is about minimizing calls of `context.sync`, it is actually more confusing to add an entirely unnecessary final `context.sync`. So, in this article, we leave it out when there are no unsynchronized commands at the end of the `run`. - ```javascript await Word.run(async function (context) { let startTime, endTime; @@ -71,15 +71,15 @@ await Word.run(async function (context) { The preceding code took 1 full second to complete in a document with 200 instances of "the" in Word on Windows. But when the `await context.sync();` line inside the loop is commented out and the same line just after the loop is uncommented, the operation took only a 1/10th of a second. In Word on the web (with Edge as the browser), it took 3 full seconds with the synchronization inside the loop and only 6/10ths of a second with the synchronization after the loop, about five times faster. In a document with 2000 instances of "the", it took (in Word on the web) 80 seconds with the synchronization inside the loop and only 4 seconds with the synchronization after the loop, about 20 times faster. > [!NOTE] -> It's worth asking whether the synchronize-inside-the-loop version would execute faster if the synchronizations ran concurrently, which could be done by simply removing the `await` keyword from the front of the `context.sync()`. This would cause the runtime to initiate the synchronization and then immediately start the next iteration of the loop without waiting for the synchronization to complete. However, this isn't as good a solution as moving the `context.sync` out of the loop entirely for these reasons. +> It's worth asking whether the synchronize-inside-the-loop version would execute faster if the synchronizations ran concurrently, which could be done by simply removing the `await` keyword from the front of the `context.sync()`. This would cause the runtime to initiate the synchronization and then immediately start the next iteration of the loop without waiting for the synchronization to complete. However, this isn't as good a solution as moving the `context.sync` out of the loop entirely for the following reasons. > > - Just as the commands in a synchronization batch job are queued, the batch jobs themselves are queued in Office, but Office supports no more than 50 batch jobs in the queue. Any more triggers errors. So, if there are more than 50 iterations in a loop, there's a chance that the queue size is exceeded. The greater the number of iterations, the greater the chance of this happening. > - "Concurrently" doesn't mean simultaneously. It would still take longer to execute multiple synchronization operations than to execute one. -> - Concurrent operations aren't guaranteed to complete in the same order in which they started. In the preceding example, it doesn't matter what order the word "the" gets highlighted, but there are scenarios where it's important that the items in the collection be processed in order. +> - Concurrent operations aren't guaranteed to complete in the same order in which they started. In the preceding example, it doesn't matter what order the word "the" gets highlighted, but there are scenarios where it's important that the items in the collection be processed in order. ## Read values from the document with the split loop pattern -Avoiding `context.sync`s inside a loop becomes more challenging when the code must *read* a property of the collection items as it processes each one. Suppose your code needs to iterate all the content controls in a Word document and log the text of the first paragraph associated with each control. Your programming instincts might lead you to loop over the controls, load the `text` property of each (first) paragraph, call `context.sync` to populate the proxy paragraph object with the text from the document, and then log it. The following is an example. +Avoiding `context.sync` inside a loop becomes more challenging when the code must *read* a property of the collection items as it processes each one. Suppose your code needs to iterate all the content controls in a Word document and log the text of the first paragraph associated with each control. Your programming instincts might lead you to loop over the controls, load the `text` property of each (first) paragraph, call `context.sync` to populate the proxy paragraph object with the text from the document, and then log it. The following is an example. ```javascript Word.run(async (context) => { @@ -87,7 +87,8 @@ Word.run(async (context) => { await context.sync(); for (let i = 0; i < contentControls.items.length; i++) { - const paragraph = contentControls.items[i].getRange('Whole').paragraphs.getFirst(); + // The sync statement in this loop will degrade performance. + const paragraph = contentControls.items[i].getRange('Whole').paragraphs.getFirst(); paragraph.load('text'); await context.sync(); console.log(paragraph.text); @@ -98,7 +99,7 @@ Word.run(async (context) => { In this scenario, to avoid having a `context.sync` in a loop, you should use a pattern we call the **split loop** pattern. Let's see a concrete example of the pattern before we get to a formal description of it. Here's how the split loop pattern can be applied to the preceding code snippet. Note the following about this code. - There are now two loops and the `context.sync` comes between them, so there's no `context.sync` inside either loop. -- The first loop iterates through the items in the collection object and loads the `text` property just as the original loop did, but the first loop cannot log the paragraph text because it no longer contains a `context.sync` to populate the `text` property of the `paragraph` proxy object. Instead, it adds the `paragraph` object to an array. +- The first loop iterates through the items in the collection object and loads the `text` property, just as the original loop did, but the first loop cannot log the paragraph text because it no longer contains a `context.sync` to populate the `text` property of the `paragraph` proxy object. Instead, it adds the `paragraph` object to an array. - The second loop iterates through the array that was created by the first loop, and logs the `text` of each `paragraph` item. This is possible because the `context.sync` that came between the two loops populated all the `text` properties. ```javascript @@ -125,14 +126,16 @@ The preceding example suggests the following procedure for turning a loop that c 1. Replace the loop with two loops. 2. Create a first loop to iterate over the collection and add each item to an array while also loading any property of the item that your code needs to read. -3. Following the first loop, call `context.sync` to populate the proxy objects with any loaded properties. +3. Follow the first loop with `context.sync` to populate the proxy objects with any loaded properties. 4. Follow the `context.sync` with a second loop to iterate over the array created in the first loop and read the loaded properties. ## Process objects in the document with the correlated objects pattern -Let's consider a more complex scenario where processing the items in the collection requires data that isn't in the items themselves. The scenario envisions a Word add-in that operates on documents created from a template with some boilerplate text. Scattered in the text are one or more instances of the following placeholder strings: "{Coordinator}", "{Deputy}", and "{Manager}". The add-in replaces each placeholder with some person's name. The UI of the add-in isn't important to this article. For example, it could have a task pane with three text boxes, each labeled with one of the placeholders. The user enters a name in each text box and then presses a **Replace** button. The handler for the button creates an array that maps the names to the placeholders, and then replaces each placeholder with the assigned name. +Let's consider a more complex scenario where processing the items in the collection requires data that isn't in the items themselves. The scenario envisions a Word add-in that operates on documents created from a template with some boilerplate text. Scattered in the text are one or more instances of the following placeholder strings: "{Coordinator}", "{Deputy}", and "{Manager}". The add-in replaces each placeholder with some person's name. While the UI of the add-in isn't important to this article, the add-in could have a task pane with three text boxes, each labeled with one of the placeholders. The user enters a name in each text box and then presses a **Replace** button. The handler for the button creates an array that maps the names to the placeholders, and then replaces each placeholder with the assigned name. -You don't need to actually produce an add-in with this UI to experiment with the code. You can use the [Script Lab tool](../overview/explore-with-script-lab.md) to prototype the important code. Use the following assignment statement to create the mapping array. +You can use the [Script Lab tool](../overview/explore-with-script-lab.md) to follow along with the code snippets shown here. In Word, you can load the "Correlated objects pattern" sample or [import this sample code from the GitHub repo](https://raw.githubusercontent.com/OfficeDev/office-js-snippets/refs/heads/prod/samples/word/90-scenarios/correlated-objects-pattern.yaml). + +The following assignment statement creates the mapping array between placeholder and assigned names. ```javascript const jobMapping = [ @@ -142,14 +145,14 @@ const jobMapping = [ ]; ``` -The following code shows how you might replace each placeholder with its assigned name if you used `context.sync` inside loops. +The following code shows how you might replace each placeholder with its assigned name if you used `context.sync` inside loops. This corresponds to the `replacePlaceholdersSlow` function in the sample. ```javascript Word.run(async (context) => { - + // The context.sync calls in the loops will degrade performance. for (let i = 0; i < jobMapping.length; i++) { let options = Word.SearchOptions.newObject(context); - options.matchWildCards = false; + options.matchWildcards = false; let searchResults = context.document.body.search(jobMapping[i].job, options); searchResults.load('items'); @@ -164,7 +167,7 @@ Word.run(async (context) => { }); ``` -In the preceding code, there's an outer and an inner loop. Each of them contains a `context.sync`. Based on the very first code snippet in this article, you probably see that the `context.sync` in the inner loop can simply be moved to after the inner loop. But that would still leave the code with a `context.sync` (two of them actually) in the outer loop. The following code shows how you can remove `context.sync` from the loops. We discuss the code later. +In the preceding code, there's an outer and an inner loop. Each of them contains a `context.sync` call. Based on the first code snippet in this article, you probably see that the `context.sync` in the inner loop can simply be moved after the inner loop. But that would still leave the code with a `context.sync` (two of them actually) in the outer loop. The following code shows how you can remove `context.sync` from the loops. It corresponds to the `replacePlaceholders` function in the sample. We discuss the code later. ```javascript Word.run(async (context) => { @@ -172,7 +175,7 @@ Word.run(async (context) => { const allSearchResults = []; for (let i = 0; i < jobMapping.length; i++) { let options = Word.SearchOptions.newObject(context); - options.matchWildCards = false; + options.matchWildcards = false; let searchResults = context.document.body.search(jobMapping[i].job, options); searchResults.load('items'); let correlatedSearchResult = { @@ -206,7 +209,7 @@ Note the code uses the split loop pattern. But the array created in the first loop does *not* contain only an Office object as the first loop did in the section [Reading values from the document with the split loop pattern](#read-values-from-the-document-with-the-split-loop-pattern). This is because some of the information needed to process the Word Range objects is not in the Range objects themselves but instead comes from the `jobMapping` array. -So, the objects in the array created in the first loop are custom objects that have two properties. The first is an array of Word Ranges that match a specific job title (that is, a placeholder string) and the second is a string that provides the name of the person assigned to the job. This makes the final loop easy to write and easy to read because all of the information needed to process a given range is contained in the same custom object that contains the range. The name that should replace _**correlatedObject**.rangesMatchingJob.items[j]_ is the other property of the same object: _**correlatedObject**.personAssignedToJob_. +So, the objects in the array created in the first loop are custom objects that have two properties. The first is an array of Word ranges that match a specific job title (that is, a placeholder string) and the second is a string that provides the name of the person assigned to the job. This makes the final loop easy to write and easy to read because all of the information needed to process a given range is contained in the same custom object that contains the range. The name that should replace _**correlatedObject**.rangesMatchingJob.items[j]_ is the other property of the same object: _**correlatedObject**.personAssignedToJob_. We call this variation of the split loop pattern the **correlated objects** pattern. The general idea is that the first loop creates an array of custom objects. Each object has a property whose value is one of the items in an Office collection object (or an array of such items). The custom object has other properties, each of which provides information needed to process the Office objects in the final loop. See the section [Other examples of these patterns](#other-examples-of-these-patterns) for a link to an example where the custom correlating object has more than two properties. @@ -222,4 +225,4 @@ One further caveat: sometimes it takes more than one loop just to create the arr ## When should you *not* use the patterns in this article? -Excel can't read more than 5 MB of data in a given call of `context.sync`. If this limit is exceeded, an error is thrown. (See the "Excel add-ins section" of [Resource limits and performance optimization for Office Add-ins](resource-limits-and-performance-optimization.md#excel-add-ins) for more information.) It's very rare that this limit is approached, but if there's a chance that this will happen with your add-in, then your code should *not* load all the data in a single loop and follow the loop with a `context.sync`. But you still should avoid having a `context.sync` in every iteration of a loop over a collection object. Instead, define subsets of the items in the collection and loop over each subset in turn, with a `context.sync` between the loops. You could structure this with an outer loop that iterates over the subsets and contains the `context.sync` in each of these outer iterations. +**Excel on the web** can't read more than **5MB** of data in a given call of `context.sync`. If this limit is exceeded, an error is thrown. (See the "Excel add-ins section" of [Resource limits and performance optimization for Office Add-ins](resource-limits-and-performance-optimization.md#excel-add-ins) for more information.) It's very rare that this limit is approached, but if there's a chance that this will happen with your add-in, then your code should *not* load all the data in a single loop and follow the loop with a `context.sync`. But you still should avoid having a `context.sync` in every iteration of a loop over a collection object. Instead, define subsets of the items in the collection and loop over each subset in turn, with a `context.sync` between the loops. You could structure this with an outer loop that iterates over the subsets and contains the `context.sync` in each of these outer iterations. diff --git a/docs/concepts/duplicate-legacy-metaos-add-ins.md b/docs/concepts/duplicate-legacy-metaos-add-ins.md index 667ad377d6..4c61dc89da 100644 --- a/docs/concepts/duplicate-legacy-metaos-add-ins.md +++ b/docs/concepts/duplicate-legacy-metaos-add-ins.md @@ -1,4 +1,4 @@ ---- +--- title: Manage both a unified manifest and an add-in only manifest version of your Office Add-in description: Learn when and how to maintain versions of your add-in for each type of manifest. ms.topic: best-practice @@ -15,21 +15,21 @@ One important improvement we're working on is the ability to create a single uni > [!TIP] > For information about converting an existing add-in to use the unified manifest, see [Convert an add-in to use the unified manifest for Microsoft 365](../develop/convert-xml-to-json-manifest.md). -After you've created a version of your add-in that uses the unified manifest, you must link the existing add-in and the app built using the unified manifest to ensure users don't see two copies of the add-in UI inside of Outlook. +After you've created a version of your add-in that uses the unified manifest, you must link the existing add-in and the app built using the unified manifest to ensure users don't see two copies of the add-in UI inside of Outlook. > [!NOTE] -> The configuration described below doesn't take effect for up to 24 hours after the new version is installed on a user's computer. During that period, the UI of both versions is visible. For example, if both versions have a custom ribbon button, both buttons appear on the ribbon. +> The configuration described below doesn't take effect for up to 24 hours after the new version is installed on a user's computer. During that period, the UI of both versions is visible. For example, if both versions have a custom ribbon button, both buttons appear on the ribbon. Use the following steps. -1. Open the extension object in the "extensions" array. -1. Create an "alternatives" array property, if there isn’t one already. -1. In the "alternatives" array, create an "alternate" object that has a "hide" property. -1. If the existing add-in is marketed through AppSource, give the "hide" object a "storeOfficeAddin" property. Otherwise, skip to step 6. -1. Give the "storeOfficeAddin" object two properties: +1. Open the extension object in the [`"extensions"`](/microsoft-365/extensibility/schema/root#extensions) array. +1. Create an [`"alternates"`](/microsoft-365/extensibility/schema/element-extensions#alternates) array property, if there isn’t one already. +1. In the `"alternates"` array, create an alternate object that has a [`"hide"`](/microsoft-365/extensibility/schema/extension-alternate-versions-array#hide) property. +1. If the existing add-in is marketed through Microsoft Marketplace, give the `"hide"` object a [`"storeOfficeAddin"`](/microsoft-365/extensibility/schema/extension-alternate-versions-array-hide#storeofficeaddin) property. Otherwise, skip to step 6. +1. Give the `"storeOfficeAddin"` object two properties: - - An "officeAddinId" with the GUID of the old add-in as its value. - - An "assetId" with the AppSource asset ID as its value. + - An `"officeAddinId"` with the GUID of the old add-in as its value. + - An `"assetId"` with the Microsoft Marketplace asset ID as its value. The following is an example: @@ -56,12 +56,11 @@ Use the following steps. > [!NOTE] > - > - The asset ID of the add-in in your unified manifest must match with an existing add-in that has been published by your seller account on Partner Center. If the asset ID of the add-in that you have linked in your unified manifest doesn't match an existing offer published by your seller account, the unified manifest submission will fail. You'll need to update the manifest to use the correct add-in asset ID and re-submit the unified manifest. + > - The asset ID of the add-in in your unified manifest must match with an existing add-in that has been published by your seller account on Partner Center. If the asset ID of the add-in that you have linked in your unified manifest doesn't match an existing offer published by your seller account, the unified manifest submission will fail. You'll need to update the manifest to use the correct add-in asset ID and re-submit the unified manifest. > - An existing add-in can only be hidden by a single unified manifest. At this time, you may not use multiple unified manifests to hide the same add-in. If you try to hide an already linked add-in using a different unified manifest, the submission will fail. You'll need to remove the linking and re-submit the unified manifest. - -1. If the old add-in isn't distributed through AppSource, then give the "hide" object a "customOfficeAddin" property. -1. Give the "customOfficeAddin" object an "officeAddinId" property with the GUID of the old add-in as its value. The following is an example. +1. If the old add-in isn't distributed through Microsoft Marketplace, then give the `"hide"` object a [`"customOfficeAddin"`](/microsoft-365/extensibility/schema/extension-alternate-versions-array-hide-custom-office-addin) property. +1. Give the `"customOfficeAddin"` object an `"officeAddinId"` property with the GUID of the old add-in as its value. The following is an example. ```json "extensions": [ @@ -83,11 +82,11 @@ Use the following steps. ] ``` -Don't remove the existing add-in from AppSource or the Microsoft 365 Admin Center, or earlier versions of Office will no longer be able to use your add-in. +Don't remove the existing add-in from Microsoft Marketplace or the Microsoft 365 Admin Center, or earlier versions of Office will no longer be able to use your add-in. ## Maintain both versions for the immediate future -Generally, add-ins that use the unified manifest can be installed only on Microsoft 365 Version 2307 (Build 16626.20132) and later. However, there are two exceptions which enable these add-ins to be installed on older versions of Microsoft 365 and on perpetual license versions of Office. +Generally, add-ins that use the unified manifest can be installed only on Microsoft 365 Version 2307 (Build 16626.20132) and later. However, there are two exceptions which enable these add-ins to be installed on older versions of Microsoft 365 and on perpetual license versions of Office. - The user's Microsoft 365 administrator deploys the add-in for all users. - The user installs the add-in on another Microsoft 365 client app that *is* version Version 2307 (Build 16626.20132) and later. This makes the add-in available on the same user's other Office clients, including older or perpetual license. @@ -97,14 +96,13 @@ If you have users on older or perpetual license versions for which these excepti There are also some scenarios where you might want to maintain both both versions of the add-in for an extended period. For example, there are two features of add-ins that aren't supported with the unified manifest because they're little used or deprecated. You may choose to maintain a version of your add-in that uses these features. The following are the features that aren't supported in the unified manifest. - [Outlook modules](../outlook/extension-module-outlook-add-ins.md) aren't supported. But you can provide a nearly identical experience using the unified manifest by [including a Teams Tab with your add-in in a single app](/microsoftteams/platform/m365-apps/combine-office-add-in-and-teams-app). -- [Outlook contextual add-ins](../outlook/contextual-outlook-add-ins.md) (also known as "activation rules") aren't supported. But you can provide similar experiences using the unified manifest and [Event-based activation](../outlook/autolaunch.md). +- [Outlook contextual add-ins](../outlook/contextual-outlook-add-ins.md) (also known as "activation rules") aren't supported. But you can provide similar experiences using the unified manifest and [Event-based activation](../develop/event-based-activation.md). -The critical requirement for making two versions available is to be sure that the two of them appear distinct in the Outlook UI. +The critical requirement for making two versions available is to be sure that the two of them appear distinct in the Outlook UI. -- Give the new version a different name from the existing add-in. +- Give the new version a different name from the existing add-in. - Create and use different icons for the new version. -- Be sure that the "id" property of the unified manifest in the new version is a different GUID from the **\<Id\>** element in the add-in only manifest of the existing add-in. +- Be sure that the [`"id"`](/microsoft-365/extensibility/schema/root#id) property of the unified manifest in the new version is a different GUID from the `<Id>` element in the add-in only manifest of the existing add-in. > [!NOTE] -> If you use the same name and icon, the old and new solutions appear indistinguishable in the Outlook UI for add-in installation. - +> If you use the same name and icon, the old and new solutions appear indistinguishable in the Outlook UI for add-in installation. diff --git a/docs/concepts/privacy-and-security.md b/docs/concepts/privacy-and-security.md index 162d7d05b3..2dffde6f04 100644 --- a/docs/concepts/privacy-and-security.md +++ b/docs/concepts/privacy-and-security.md @@ -1,7 +1,7 @@ ---- +--- title: Privacy and security for Office Add-ins description: Learn about the privacy and security aspects of the Office Add-ins platform. -ms.date: 05/16/2024 +ms.date: 07/24/2025 ms.localizationpriority: medium --- @@ -52,9 +52,9 @@ In supported web clients, Office Add-ins are hosted in an **iframe** that runs u ![Diagram of the infrastructure that supports Office Add-ins in Office on the web clients.](../images/dk2-agave-overview-03.png) -## Add-in integrity in AppSource +## Add-in integrity in Microsoft Marketplace -You can make your Office Add-ins available to the public by publishing them to AppSource. AppSource enforces the following measures to maintain the integrity of add-ins. +You can make your Office Add-ins available to the public by publishing them to Microsoft Marketplace. Microsoft Marketplace enforces the following measures to maintain the integrity of add-ins. - Requires the host server of an Office Add-in to always use Secure Sockets Layer (SSL) to communicate. @@ -64,19 +64,28 @@ You can make your Office Add-ins available to the public by publishing them to A ## Optional connected experiences -End users and IT admins can turn off [optional connected experiences in Office](/deployoffice/privacy/optional-connected-experiences) desktop and mobile clients. For Office Add-ins, the impact of disabling the **Optional connected experiences** setting is that users can no longer access add-ins or the Microsoft 365 and Copilot store through these clients. However, certain Microsoft add-ins that are considered essential or business-critical, and add-ins deployed by an organization's IT admin through [Centralized Deployment](/microsoft-365/admin/manage/centralized-deployment-of-add-ins) will still be available. Additionally, add-ins and the Microsoft 365 and Copilot store remain available in Outlook on the web, regardless of the status of the setting. - -For more about Outlook-specific behavior, see [Privacy, permissions, and security for Outlook add-ins](../outlook/privacy-and-security.md#optional-connected-experiences). +End users and IT admins can turn off [optional connected experiences in Office](/deployoffice/privacy/optional-connected-experiences) desktop and mobile clients. For Office Add-ins, the impact of disabling the **Optional connected experiences** setting is that users can no longer access add-ins or the Microsoft 365 and Copilot store through these clients. However, certain Microsoft add-ins that are considered essential or business-critical, and add-ins deployed by an organization's IT admin through [Centralized Deployment](/microsoft-365/admin/manage/centralized-deployment-of-add-ins) will still be available. In Outlook, the availability of add-ins when the **Optional connected experiences** setting is turned off varies depending on the client. For more information, see [Optional connected experiences in Outlook](#optional-connected-experiences-in-outlook). Note that if an IT admin disables the [use of connected experiences in Office](/deployoffice/privacy/manage-privacy-controls#policy-setting-for-most-connected-experiences), it has the same effect on add-ins as turning off just optional connected experiences. +### Optional connected experiences in Outlook + +The following table describes the availability of add-ins on Outlook clients when optional connected experiences is turned off. + +|Client|Behavior when optional connected experiences is turned off| +|-----|-----| +|<ul><li>Web browser</li><li>[new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627)</li></ul>|Admin-deployed add-ins remain visible and usable. While users can still access the Microsoft 365 and Copilot store and install add-ins, these add-ins can't be used until the **Optional connected experiences** setting is turned on. Additionally, sideloaded add-ins can't be used.| +|<ul><li>Windows (classic)</li></ul>|All add-ins remain visible and usable. However, the Microsoft 365 and Copilot store is inaccessible.| +|<ul><li>Mac</li></ul>|Add-ins don't appear in the ribbon and the Microsoft 365 and Copilot store is inaccessible.| +|<ul><li>Android</li><li>iOS</li></ul>|The **Get Add-ins** dialog shows only admin-deployed add-ins.| + ## Addressing end users' privacy concerns This section describes the protection offered by the Office Add-ins platform from the customer's (end user's) perspective, and provides guidelines for how to support users' expectations and how to securely handle users' personally identifiable information (PII). ### End users' perspective -Office Add-ins are built using web technologies that run in a browser control or **iframe**. Because of this, using add-ins is similar to browsing to web sites on the Internet or intranet. Add-ins can be external to an organization (if you acquire the add-in from AppSource) or internal (if you acquire the add-in from an Exchange Server add-in catalog, SharePoint app catalog, or file share on an organization's network). Add-ins have limited access to the network and most add-ins can read or write to the active document or mail item. The add-in platform applies certain constraints before a user or administrator installs or starts an add-in. But as with any extensibility model, users should be cautious before starting an unknown add-in. +Office Add-ins are built using web technologies that run in a browser control or **iframe**. Because of this, using add-ins is similar to browsing to web sites on the Internet or intranet. Add-ins can be external to an organization (if you acquire the add-in from Microsoft Marketplace) or internal (if you acquire the add-in from an Exchange Server add-in catalog, SharePoint app catalog, or file share on an organization's network). Add-ins have limited access to the network and most add-ins can read or write to the active document or mail item. The add-in platform applies certain constraints before a user or administrator installs or starts an add-in. But as with any extensibility model, users should be cautious before starting an unknown add-in. > [!NOTE] > Users may see a security prompt to trust the domain the first time an add-in is loaded. This will happen if the add-in's domain host is outside of the domain of Exchange on-premise or Office Online Server. @@ -85,7 +94,7 @@ The add-in platform addresses end users' privacy concerns in the following ways. - Data communicated with the web server that hosts a content, Outlook or task pane add-in as well as communication between the add-in and any web services it uses must be encrypted using the Secure Socket Layer (SSL) protocol. -- Before a user installs an add-in from AppSource, the user can view the privacy policy and requirements of that add-in. In addition, Outlook add-ins that interact with users' mailboxes surface the specific permissions that they require; the user can review the terms of use, requested permissions and privacy policy before installing an Outlook add-in. +- Before a user installs an add-in from Microsoft Marketplace, the user can view the privacy policy and requirements of that add-in. In addition, Outlook add-ins that interact with users' mailboxes surface the specific permissions that they require; the user can review the terms of use, requested permissions and privacy policy before installing an Outlook add-in. - When sharing a document, users also share add-ins that have been inserted in or associated with that document. If a user opens a document that contains an add-in that the user hasn't used before, the Office client application prompts the user to grant permission for the add-in to run in the document. In an organizational environment, the Office client application also prompts the user if the document comes from an external source. @@ -97,11 +106,11 @@ The add-in platform addresses end users' privacy concerns in the following ways. A user's device capabilities include their camera, geolocation, and microphone. To learn more, see [View, manage, and install add-ins for Excel, PowerPoint, and Word](https://support.microsoft.com/office/16278816-1948-4028-91e5-76dca5380f8d). -- Users can enable or disable the access to AppSource. For content and task pane add-ins, users manage access to trusted add-ins and catalogs from the **Trust Center** on the host Office client (opened from **File** > **Options** > **Trust Center** > **Trust Center Settings** > **Trusted Add-in Catalogs**). +- Users can enable or disable the access to Microsoft Marketplace. For content and task pane add-ins, users manage access to trusted add-ins and catalogs from the **Trust Center** on the host Office client (opened from **File** > **Options** > **Trust Center** > **Trust Center Settings** > **Trusted Add-in Catalogs**). In Outlook, access to manage add-ins depends on the user's Outlook client. To learn more, see [Use add-ins in Outlook](https://support.microsoft.com/office/1ee261f9-49bf-4ba6-b3e2-2ba7bcab64c8). - Administrators can also manage access to AppSource [through the admin center](/microsoft-365/admin/manage/manage-addins-in-the-admin-center). + Administrators can also manage access to Microsoft Marketplace [through the admin center](/microsoft-365/admin/manage/manage-addins-in-the-admin-center). - The design of the add-in platform provides security and performance for end users in the following ways. @@ -109,7 +118,31 @@ The add-in platform addresses end users' privacy concerns in the following ways. - Running in a web browser control allows the add-in to do almost anything a regular web page running in a browser can do but, at the same time, restricts the add-in to observe the same-origin policy for domain isolation and security zones. -Outlook add-ins provide additional security and performance features through Outlook add-in specific resource usage monitoring. For more information, see [Privacy, permissions, and security for Outlook add-ins](../outlook/privacy-and-security.md). +#### End users' perspective in Outlook + +The following points address end users' privacy concerns specific to Outlook. + +- End user's messages that are protected by Outlook's Information Rights Management (IRM) won't interact with add-ins in the following instances. + + - When the IRM-protected message is accessed from Outlook on mobile devices. + + - When the IRM-protected message contains a sensitivity label with the **Allow programmatic access** custom policy option set to `false`. + + For more information on IRM support in add-ins, see [Mail items protected by IRM](../outlook/outlook-add-ins-overview.md#mail-items-protected-by-irm). + +- Granting the **restricted** permission allows the Outlook add-in to have limited access on only the current item. Granting the **read item** permission allows the Outlook add-in to access personal identifiable information, such as sender and recipient names and email addresses, on only the current item. For more information on Outlook add-in permissions, see [Understanding Outlook add-in permissions](../outlook/understanding-outlook-add-in-permissions.md). + +- Manifest files of installed Outlook add-ins are secured in the user's email account. + +- Outlook on Windows (classic) and on Mac monitor the performance of installed Outlook add-ins, exercise governance control, and make add-ins unavailable when they exceed limits in the following areas. + + - Response time to activate + + - Number of failures to activate or reactivate + + - Memory usage + + - CPU usage ### Developer guidelines to handle PII @@ -119,9 +152,9 @@ The following lists some specific PII protection guidelines for you as a develop - Using some applications can reveal PII. Make sure that you securely store data for your users' identity, location, access times, and any other credentials so that data won't become available to other users of the add-in. -- If your add-in is available in AppSource, the AppSource requirement for HTTPS protects PII transmitted between your web server and the client computer or device. However, if you re-transmit that data to other servers, make sure you observe the same level of protection. +- If your add-in is available in Microsoft Marketplace, the requirement for HTTPS protects PII transmitted between your web server and the client computer or device. However, if you re-transmit that data to other servers, make sure you observe the same level of protection. -- If you store users' PII, make sure you reveal that fact, and provide a way for users to inspect and delete it. If you submit your add-in to AppSource, you can outline the data you collect and how it's used in the privacy statement. +- If you store users' PII, make sure you reveal that fact, and provide a way for users to inspect and delete it. If you submit your add-in to Microsoft Marketplace, you can outline the data you collect and how it's used in the privacy statement. ## Developers' permission choices and security practices @@ -129,13 +162,37 @@ Follow these general guidelines to support the security model of Office Add-ins, ### Request the necessary permissions -The add-in platform provides a permissions model that your add-in uses to declare the level of access to a user's data that it requires for its features. Each permission level corresponds to the subset of the JavaScript API for Office your add-in is allowed to use for its features. For example, the **WriteDocument** permission for content and task pane add-ins allows access to the [Document.setSelectedDataAsync](/javascript/api/office/office.document) method that lets an add-in write to the user's document, but doesn't allow access to any of the methods for reading data from the document. This permission level makes sense for add-ins that only need to write to a document, such as an add-in where the user can query for data to insert into their document. +The add-in platform provides a permissions model that your add-in uses to declare the level of access to a user's data that it requires for its features. Each permission level corresponds to the subset of the JavaScript API for Office your add-in is allowed to use for its features. For example, the **write document** permission for content and task pane add-ins allows access to the [Document.setSelectedDataAsync](/javascript/api/office/office.document) method that lets an add-in write to the user's document, but doesn't allow access to any of the methods for reading data from the document. This permission level makes sense for add-ins that only need to write to a document, such as an add-in where the user can query for data to insert into their document. + +As a best practice, you should request permissions based on the principle of *least privilege*. That is, you should request permission to access only the minimum subset of the API that your add-in requires to function correctly. For example, if your add-in needs only to read data in a user's document for its features, you should request no more than the **read document** permission. (But, keep in mind that requesting insufficient permissions will result in the add-in platform blocking your add-in's use of some APIs and will generate errors at run time.) + +You specify permissions in the manifest of your add-in, as shown in the example in this section below, and end users can see the requested permission level of an add-in before they decide to install or activate the add-in for the first time. Additionally, Outlook add-ins that request the **read/write mailbox** permission require explicit administrator privilege to install. + +To see an example of how to request permissions in the manifest, open the tab for the type of manifest your add-in uses. -As a best practice, you should request permissions based on the principle of *least privilege*. That is, you should request permission to access only the minimum subset of the API that your add-in requires to function correctly. For example, if your add-in needs only to read data in a user's document for its features, you should request no more than the **ReadDocument** permission. (But, keep in mind that requesting insufficient permissions will result in the add-in platform blocking your add-in's use of some APIs and will generate errors at run time.) +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) -You specify permissions in the manifest of your add-in, as shown in the example in this section below, and end users can see the requested permission level of an add-in before they decide to install or activate the add-in for the first time. Additionally, Outlook add-ins that request the **ReadWriteMailbox** permission require explicit administrator privilege to install. +[!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] + +The following example shows how a task pane add-in specifies the **read document** permission in its manifest. To keep permissions as the focus, other elements in the manifest aren't displayed. + +```json +"authorization": { + "permissions": { + "resourceSpecific": [ + ... + { + "name": "Document.Read.User", + "type": "Delegated" + }, + ] + } +} +``` -The following example shows how a task pane add-in specifies the **ReadDocument** permission in its manifest. To keep permissions as the focus, other elements in the manifest aren't displayed. +# [Add-in only manifest](#tab/xmlmanifest) + +The following example shows how a task pane add-in specifies the **read document** permission in its manifest. To keep permissions as the focus, other elements in the manifest aren't displayed. ```xml <?xml version="1.0" encoding="utf-8"?> @@ -144,19 +201,17 @@ The following example shows how a task pane add-in specifies the **ReadDocument* xmlns:ver="http://schemas.microsoft.com/office/appforoffice/1.0" xsi:type="TaskPaneApp"> -... <!-- To keep permissions as the focus, not displaying other elements. --> - <Permissions>ReadDocument</Permissions> -... + ... <!-- To keep permissions as the focus, not displaying other elements. --> + <Permissions>ReadDocument</Permissions> + ... </OfficeApp> ``` -For more information about permissions for task pane and content add-ins, see [Requesting permissions for API use in add-ins](../develop/requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md). - -For more information about permissions for Outlook add-ins, see the following topics. +--- -- [Privacy, permissions, and security for Outlook add-ins](../outlook/privacy-and-security.md) +For more information about permissions for task pane and content add-ins, see [Requesting permissions for API use in add-ins](../develop/requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md). -- [Understanding Outlook add-in permissions](../outlook/understanding-outlook-add-in-permissions.md) +For more information about permissions for Outlook add-ins, see [Understanding Outlook add-in permissions](../outlook/understanding-outlook-add-in-permissions.md). ### Follow the same-origin policy @@ -246,7 +301,7 @@ Developers should also take note of the following security practices. - Developers shouldn't use ActiveX controls in Office Add-ins as ActiveX controls don't support the cross-platform nature of the add-in platform. -- Content and task pane add-ins assume the same SSL settings that the browser uses by default, and allows most content to be delivered only by SSL. Outlook add-ins require all content to be delivered by SSL. Developers must specify in the **\<SourceLocation\>** element of the add-in manifest a URL that uses HTTPS, to identify the location of the HTML file for the add-in. +- Content and task pane add-ins assume the same SSL settings that the browser uses by default, and allows most content to be delivered only by SSL. Outlook add-ins require all content to be delivered by SSL. Developers must specify in the `<SourceLocation>` element of the add-in manifest a URL that uses HTTPS, to identify the location of the HTML file for the add-in. To make sure add-ins aren't delivering content by using HTTP, when testing add-ins, developers should make sure the following settings are selected in **Internet Options** in **Control Panel** and no security warnings appear in their test scenarios. @@ -260,7 +315,7 @@ Developers should also take note of the following security practices. - Developers shouldn't embed keys that they use to access APIs or services from Microsoft and others (such as Bing, Google, or Facebook) directly in the HTML pages of their add-in. Instead, they should create a custom web service or store the keys in some other form of secure web storage that they can then call to pass the key value to their add-in. -- Developers should do the following when submitting an add-in to AppSource. +- Developers should do the following when submitting an add-in to Microsoft Marketplace. - Host the add-in they are submitting on a web server that supports SSL. - Produce a statement outlining a compliant privacy policy. @@ -270,7 +325,7 @@ Other than resource usage rules, developers for Outlook add-ins should also make ## IT administrators' control -In a corporate setting, IT administrators have ultimate authority over enabling or disabling access to AppSource and any private catalogs. +In a corporate setting, IT administrators have ultimate authority over enabling or disabling access to Microsoft Marketplace and any private catalogs. The management and enforcement of Office settings is done with group policy settings. These are configurable through the [Office Deployment Tool](/deployoffice/overview-office-deployment-tool), in conjunction with the [Office Customization Tool](/deployoffice/admincenter/overview-office-customization-tool). @@ -278,12 +333,13 @@ The management and enforcement of Office settings is done with group policy sett |--------------|-------------| | Allow Unsecure web add-ins and Catalogs | Allows users to run non-secure Office Add-ins, which are Office Add-ins that have webpage or catalog locations that are not SSL-secured (https://) and are not in users' Internet zones. | | Block Web Add-ins | Allows you to prevent users from running Office Add-ins that use web technologies. | -| Block the Office Store | Allows you to prevent users from getting or running Office Add-ins that come from [AppSource](https://appsource.microsoft.com). | +| Block the Office Store | Allows you to prevent users from getting or running Office Add-ins that come from [Microsoft Marketplace](https://marketplace.microsoft.com). | + +To specify permissions to install and manage Outlook add-ins in an organization that uses Exchange Online, configure administrative and user roles in the Exchange admin center. For more information, see [Specify the administrators and users who can install and manage add-ins for Outlook in Exchange Online](/exchange/clients-and-mobile-in-exchange-online/add-ins-for-outlook/specify-who-can-install-and-manage-add-ins). ## See also - [Requesting permissions for API use in add-ins](../develop/requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md) -- [Privacy, permissions, and security for Outlook add-ins](../outlook/privacy-and-security.md) - [Understanding Outlook add-in permissions](../outlook/understanding-outlook-add-in-permissions.md) - [Limits for activation and JavaScript API for Outlook add-ins](../outlook/limits-for-activation-and-javascript-api-for-outlook-add-ins.md) - [Addressing same-origin policy limitations in Office Add-ins](../develop/addressing-same-origin-policy-limitations.md) diff --git a/docs/concepts/requirements-for-running-office-add-ins.md b/docs/concepts/requirements-for-running-office-add-ins.md index 01a1052884..29e361c8d3 100644 --- a/docs/concepts/requirements-for-running-office-add-ins.md +++ b/docs/concepts/requirements-for-running-office-add-ins.md @@ -1,7 +1,7 @@ ---- +--- title: Requirements for running Office Add-ins description: Learn about the client and server requirements that an end user needs to run Office Add-ins. -ms.date: 04/24/2024 +ms.date: 08/13/2025 ms.localizationpriority: medium --- @@ -24,12 +24,17 @@ For all types of add-ins (content, Outlook, and task pane add-ins and add-in com > [!TIP] > When you develop and debug an add-in in Visual Studio, Visual Studio deploys and runs your add-in's webpage files locally with IIS Express, and doesn't require an additional web server. -For content and task pane add-ins, in the supported Office client applications - Excel, PowerPoint, Project, or Word - you also need either an [app catalog](../publish/publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md) on SharePoint to upload the add-in's XML-formatted add-in only manifest file, or you need to deploy the add-in using [Integrated Apps](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps). +For content and task pane add-ins, in the supported Office client applications - Excel, PowerPoint, Project, or Word - you also need either an [app catalog](../publish/publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md) on SharePoint to upload the add-in's XML-formatted add-in only manifest file, or you need to deploy the add-in using the [integrated apps portal](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps). + +To test and run an Outlook add-in, the user's Outlook email account must reside on Exchange 2016 or later, which is available through Microsoft 365, Exchange Online, or through an on-premises installation. The user or administrator installs manifest files for Outlook add-ins on that server. For Exchange on-premises installations, the following requirements apply. -To test and run an Outlook add-in, the user's Outlook email account must reside on Exchange 2016 or later, which is available through Microsoft 365, Exchange Online, or through an on-premises installation. The user or administrator installs manifest files for Outlook add-ins on that server. +- The server must be Exchange 2016 or later. +- Exchange Web Services (EWS) must be enabled and must be exposed to the Internet. Many add-ins require EWS to function properly. +- The server must have a valid authentication certificate in order for the server to issue valid identity tokens. New installations of Exchange Server include a default authentication certificate. For more information, see [Digital certificates and encryption in Exchange 2016](/Exchange/architecture/client-access/certificates) and [Set-AuthConfig](/powershell/module/exchangepowershell/set-authconfig). +- To access add-ins from [Microsoft Marketplace](https://marketplace.microsoft.com/marketplace/apps?product=office), the client access servers must be able to communicate with Microsoft Marketplace. > [!NOTE] -> POP and IMAP email accounts in Outlook don't support Office Add-ins. +> POP3 and IMAP email accounts in Outlook don't support Office Add-ins. ## Client requirements: Windows desktop and tablet @@ -74,7 +79,7 @@ Specifically for Outlook running on smartphones and non-Windows tablet devices, |Outlook on the web (modern)<sup>1</sup>|<ul><li>iPad 2 or later</li><li>Android tablets</li></ul>|<ul><li>iOS 5 or later</li><li>Android 4.4 KitKat or later</li></ul>|On Microsoft 365, Exchange Online|<ul><li>Microsoft Edge</li><li>Chrome</li><li>Firefox</li><li>Safari</li></ul>| |Outlook on the web (classic)|<ul><li>iPhone 4 or later</li><li>iPad 2 or later</li><li>iPod Touch 4 or later</li></ul>|<ul><li>iOS 5 or later</li></ul>|On on-premises Exchange Server 2016 or later<sup>2</sup>|<ul><li>Safari</li></ul>| |Outlook on Android|<ul><li>Android tablets</li><li>Android smartphones</li></ul>|<ul><li>Android 4.4 KitKat or later</li></ul>|On the latest update of Microsoft 365 Apps for business or Exchange Online|Browser not applicable. Use the native app for Android.<sup>3</sup>| -|Outlook on iOS|<ul><li>iPad tablets</li><li>iPhone smartphones|<ul><li>iOS 11 or later</li></ul>|On the latest update of Microsoft 365 Apps for business or Exchange Online|Browser not applicable. Use the native app for iOS.<sup>3</sup>| +|Outlook on iOS|<ul><li>iPad tablets</li><li>iPhone smartphones|<ul><li>iOS 11 or later</li><li>iPadOS 13 or later</li></ul>|On the latest update of Microsoft 365 Apps for business or Exchange Online|Browser not applicable. Use the native app for iOS.<sup>3</sup>| > [!NOTE] > <sup>1</sup> Modern Outlook on the web on iPhone and Android smartphones is no longer required or available for testing Outlook add-ins. diff --git a/docs/concepts/resource-limits-and-performance-optimization.md b/docs/concepts/resource-limits-and-performance-optimization.md index 70eb94fe64..119b5a4239 100644 --- a/docs/concepts/resource-limits-and-performance-optimization.md +++ b/docs/concepts/resource-limits-and-performance-optimization.md @@ -1,90 +1,87 @@ ---- +--- title: Resource limits and performance optimization for Office Add-ins description: Learn about the resource limits of the Office Add-in platform, including CPU and memory. -ms.date: 02/29/2024 +ms.date: 09/03/2025 ms.localizationpriority: medium --- # Resource limits and performance optimization for Office Add-ins -To create the best experience for your users, ensure that your Office Add-in performs within specific limits for CPU core and memory usage, reliability, and, for Outlook add-ins, the response time for evaluating regular expressions. These run-time resource usage limits apply to add-ins running in Office clients on Windows and OS X, but not on mobile apps or in a browser. - -You can also optimize the performance of your add-ins on desktop and mobile devices by optimizing the use of resources in your add-in design and implementation. +Quality add-ins must performs within specific requirements for CPU core usage, memory usage, reliability, and, for Outlook add-ins, regular expression evaluation response time. These limits help ensure performance for your users and mitigate denial-of-service attacks. Be sure to test your Office Add-in on your target Office application by using a range of possible data, and measure its performance against the following run-time usage limits. ## Resource usage limits for add-ins -Run-time resource usage limits apply to all types of Office Add-ins. These limits help ensure performance for your users and mitigate denial-of-service attacks. Be sure to test your Office Add-in on your target Office application by using a range of possible data, and measure its performance against the following run-time usage limits. +> [!NOTE] +> The resource limits in this section only apply to Excel, Outlook on Mac (classic), PowerPoint, and Word. -- **CPU core usage** - A single CPU core usage threshold of 90%, observed three times in default 5-second intervals. +The following runtime resource limits apply to add-ins running in Office clients on Windows and Mac, but not on mobile apps or in a browser. - The default interval for an Office client to check CPU core usage is every 5 seconds. If the Office client detects the CPU core usage of an add-in is above the threshold value, it displays a message asking if the user wants to continue running the add-in. If the user chooses to continue, the Office client does not ask the user again during that edit session. Administrators might want to use the **AlertInterval** registry key to raise the threshold to reduce the display of this warning message if users run CPU-intensive add-ins. +- **CPU core usage** - A single CPU core usage threshold of 90%, observed three times in five-second intervals by default. + + If the Office client detects the CPU core usage of an add-in is above the threshold value, it displays a message asking if the user wants to continue running the add-in. If the user chooses to continue, the Office client does not ask the user again during that edit session. The default interval for an Office client to check CPU core usage is every five seconds. Administrators can use the **AlertInterval** registry key to raise the threshold to reduce the display of this warning message if users run CPU-intensive add-ins. - **Memory usage** - A default memory usage threshold that is dynamically determined based on the available physical memory of the device. - By default, when a Office client detects that physical memory usage on a device exceeds 80% of the available memory, the client starts monitoring the add-in's memory usage, at a document level for content and task pane add-ins, and at a mailbox level for Outlook add-ins. At a default interval of 5 seconds, the client warns the user if physical memory usage for a set of add-ins at the document or mailbox level exceeds 50%. This memory usage limit uses physical rather than virtual memory to ensure performance on devices with limited RAM, such as tablets. Administrators can override this dynamic setting with an explicit limit by using the **MemoryAlertThreshold** Windows registry key as a global setting, ir adjust the alert interval by using the **AlertInterval** key as a global setting. + By default, when a Office client detects that physical memory usage on a device exceeds 80% of the available memory, the client starts monitoring the add-in's memory usage. This is done at the document level for content and task pane add-ins and at the mailbox level for Outlook add-ins. At a default interval of five seconds, the client warns the user if physical memory usage for a set of add-ins at the document or mailbox level exceeds 50%. This memory usage limit uses physical rather than virtual memory to ensure performance on devices with limited RAM, such as tablets. Administrators can override this dynamic setting with an explicit limit by using the **MemoryAlertThreshold** Windows registry key as a global setting. They can also adjust the alert interval with the **AlertInterval** key. -- **Crash tolerance** - A default limit of four crashes for an add-in. +- **Crash tolerance** - A default limit of four crashes during the document's session. Administrators can adjust the threshold for crashes by using the **RestartManagerRetryLimit** registry key. -- **Application blocking** - Prolonged unresponsiveness threshold of 5 seconds for an add-in. +- **Application blocking** - A prolonged unresponsiveness threshold of five seconds. - This affects the user's experiences of the add-in and the Office application. When this occurs, the Office application automatically restarts all the active add-ins for a document or mailbox (where applicable), and warns the user as to which add-in became unresponsive. Add-ins can reach this threshold when they do not regularly yield processing while performing long-running tasks. There are techniques to ensure that blocking does not occur. Administrators cannot override this threshold. + This affects the user's experiences of the add-in and the Office application. When this occurs, the Office application automatically restarts all the active add-ins for a document or mailbox (where applicable), and warns the user which add-in became unresponsive. Add-ins reach this threshold when they don't regularly yield processing while performing long-running tasks. There are techniques listed later in this article to help ensure the add-in doesn't block the Office application. Administrators cannot override this threshold. -### Outlook add-ins +> [!NOTE] +> Although only Outlook on Mac (classic) monitors resource usage, if the client makes an Outlook add-in unavailable, the add-in also become unavailable in other supported Outlook clients. -If any Outlook add-in exceeds the preceding thresholds for CPU core or memory usage, or tolerance limit for crashes, the add-in becomes unavailable. The Exchange Admin Center displays the add-in status. +### Task pane and content add-ins -> [!NOTE] -> Even though only Outlook on Windows (classic) and on Mac monitor resource usage, if either of these clients makes an Outlook add-in unavailable, that add-in also becomes unavailable in Outlook on the web, on mobile devices, and in [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627). +If any content or task pane add-in exceeds the preceding thresholds on CPU core or memory usage, or tolerance limit for crashes, the corresponding Office application displays a warning for the user. At this point, the user can do one of the following: -In addition to the CPU core, memory, and reliability rules, Outlook add-ins should observe the following rules on activation. +- Restart the add-in. +- Cancel further alerts about exceeding that threshold. Ideally, the user should then delete the add-in from the document. Continued use of the add-in would risk further performance and stability issues. -- **Regular expressions response time** - A default threshold of 1,000 milliseconds for Outlook to evaluate all regular expressions in the manifest of an Outlook add-in. Exceeding the threshold causes Outlook to retry evaluation at a later time. +### Evaluation response time for regular expressions in Outlook add-ins - Using a group policy or application-specific setting in the Windows registry, administrators can adjust this default threshold value of 1,000 milliseconds in the **OutlookActivationAlertThreshold** setting. +Outlook add-ins that use regular expressions and run in Outlook on Windows (classic) or on Mac (classic) should observe the following rules on activation. -- **Regular expressions re-evaluation** - A default limit of three times for Outlook to reevaluate all the regular expressions in a manifest. If evaluation fails all three times by exceeding the applicable threshold (which is either the default of 1,000 milliseconds or a value specified by **OutlookActivationAlertThreshold**, if that setting exists in the Windows registry), Outlook makes the add-in unavailable. The Exchange Admin Center displays the add-in status, and the add-in is unavailable in Outlook on the web, on Windows (new and classic), on Mac, and on mobile devices. +- **Regular expressions response time** - A default threshold of 1,000 milliseconds for Outlook to evaluate all regular expressions in the manifest of an Outlook add-in. Exceeding the threshold causes Outlook to retry evaluation at a later time. - Using a group policy or application-specific setting in the Windows registry, administrators can adjust this number of times to retry evaluation in the **OutlookActivationManagerRetryLimit** setting. + In classic Outlook on Windows, administrators can adjust this default threshold value of 1,000 milliseconds by using a group policy or application-specific setting for the `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\Outlook\ActivationAlertThreshold` DWORD value in the Windows registry. -### Excel add-ins +- **Regular expressions re-evaluation** - A default limit of three times for Outlook to reevaluate all the regular expressions in a manifest. If evaluation fails three times, the user must switch to a different mail item then switch back to retry evaluation. -If you're building an Excel add-in, be aware of the following size limitations when interacting with the workbook. + Administrators can adjust this number of times to retry evaluation by using a group policy or application-specific setting. The location of the setting depends on the platform. -- Excel on the web has a payload size limit for requests and responses of 5MB. `RichAPI.Error` will be thrown if that limit is exceeded. -- A range is limited to five million cells for get operations. + - **Windows**: The `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\Outlook\ActivationRetryLimit` DWORD value in the Windows registry. + - **Mac**: The `ActivationRetryLimit` property list in `~/Library/Preferences`. -If you expect user input to exceed these limits, be sure to check the data before calling `context.sync()`. Split the operation into smaller pieces as needed. Be sure to call `context.sync()` for each sub-operation to avoid those operations getting batched together again. +### Excel add-ins -These limitations are typically exceeded by large ranges. Your add-in might be able to use [RangeAreas](/javascript/api/excel/excel.rangeareas) to strategically update cells within a larger range. For more information about working with `RangeAreas`, see [Work with multiple ranges simultaneously in Excel add-ins](../excel/excel-add-ins-multiple-ranges.md). For additional information about optimizing payload size in Excel, see [Payload size limit best practices](../excel/performance.md#payload-size-limit-best-practices). +Excel add-ins have important data transfer limits when interacting with the workbook. -### Task pane and content add-ins +- Excel on the web has a payload size limit for requests and responses of **5MB**. `RichAPI.Error` will be thrown if that limit is exceeded. +- A range is limited to **5,000,000** cells for read operations. -If any content or task pane add-in exceeds the preceding thresholds on CPU core or memory usage, or tolerance limit for crashes, the corresponding Office application displays a warning for the user. At this point, the user can do one of the following: +If you expect user input will exceed these limits, check the data before calling `context.sync()`. Split the operation into smaller pieces as needed. Call `context.sync()` for each sub-operation to avoid those operations getting batched together again. -- Restart the add-in. -- Cancel further alerts about exceeding that threshold. Ideally, the user should then delete the add-in from the document; continuing the add-in would risk further performance and stability issues. +These limits are typically exceeded by large ranges. Your add-in might be able to use [RangeAreas](/javascript/api/excel/excel.rangeareas) to strategically update cells within a larger range. For more information about working with `RangeAreas`, see [Work with multiple ranges simultaneously in Excel add-ins](../excel/excel-add-ins-multiple-ranges.md). For additional information about optimizing payload size in Excel, see [Payload size limit best practices](../excel/performance.md#payload-size-limit-best-practices). ## Verify resource usage issues in the Telemetry Log -Office provides a Telemetry Log that maintains a record of certain events (loading, opening, closing, and errors) of Office solutions running on the local computer, including resource usage issues in an Office Add-in. If you have the Telemetry Log set up, you can use Excel to open the Telemetry Log in the following default location on your local drive. +Office provides a Telemetry Log that maintains a record of certain events (loading, opening, closing, and errors) for Office solutions running on the local computer. This includes resource usage issues in an Office Add-in. If you have the Telemetry Log set up, you can use Excel to open the Telemetry Log in the following default location on your local drive. `%Users%\<Current user>\AppData\Local\Microsoft\Office\16.0\Telemetry` -For each event that the Telemetry Log tracks for an add-in, there is a date/time of the occurrence, event ID, severity, and short descriptive title for the event, the friendly name and unique ID of the add-in, and the application that logged the event. You can refresh the Telemetry Log to see the current tracked events. The following table shows examples of Outlook add-ins that were tracked in the Telemetry log. - -|Date/Time|Event ID|Severity|Title|File|ID|Application| -|:-----|:-----|:-----|:-----|:-----|:-----|:-----| -|10/8/2022 5:57:10 PM|7|*Not applicable*|add-in manifest downloaded successfully|Who's Who|69cc567c-6737-4c49-88dd-123334943a22|Outlook| -|10/8/2022 5:57:01 PM|7|*Not applicable*|add-in manifest downloaded successfully|LinkedIn|333bf46d-7dad-4f2b-8cf4-c19ddc78b723|Outlook| +For each event that the Telemetry Log tracks for an add-in, there is a date/time of the occurrence, event ID, severity, and short descriptive title for the event, the friendly name and unique ID of the add-in, and the application that logged the event. Refresh the Telemetry Log to see the current tracked events. -The following table lists the events that the Telemetry Log tracks for Office Add-ins in general. +The following table lists the events that the Telemetry Log tracks for Office Add-ins. |Event ID|Title|Severity|Description| |:-----|:-----|:-----|:-----| |7|Add-in manifest downloaded successfully|*Not applicable*|The manifest of the Office Add-in was successfully loaded and read by the Office application.| -|8|Add-in manifest did not download|Critical|The Office application was unable to load the manifest file for the Office Add-in from the SharePoint catalog, corporate catalog, or AppSource.| +|8|Add-in manifest did not download|Critical|The Office application was unable to load the manifest file for the Office Add-in from the SharePoint catalog, corporate catalog, or Microsoft Marketplace.| |9|Add-in markup could not be parsed|Critical|The Office application loaded the Office Add-in manifest, but could not read the HTML markup of the app.| |10|Add-in used too much CPU|Critical|The Office Add-in used more than 90% of the CPU resources over a finite period of time.| |15|Add-in disabled due to string search time-out|*Not applicable*|Outlook add-ins search the subject line and message of an e-mail to determine whether they should be displayed by using a regular expression. The Outlook add-in listed in the **File** column was disabled by Outlook because it timed out repeatedly while trying to match a regular expression.| @@ -96,13 +93,13 @@ For more information, see [Deploying Telemetry Dashboard](/previous-versions/off ## Design and implementation techniques -While the resources limits on CPU and memory usage, crash tolerance, and UI responsiveness apply to Office Add-ins running only in Office desktop clients, optimizing the usage of these resources and battery should be a priority if you want your add-in to perform satisfactorily on all supporting clients and devices. Optimization is particularly important if your add-in carries out long-running operations or handles large data sets. The following list suggests some techniques to break up CPU-intensive or data-intensive operations into smaller chunks so that your add-in can avoid excessive resource consumption and the Office application can remain responsive. +While the resources limits on CPU and memory usage, crash tolerance, and UI responsiveness apply to Office Add-ins running only in Office desktop clients, optimization should be a priority if you want your add-in to perform satisfactorily on all supporting clients and devices. Optimization is particularly important if your add-in carries out long-running operations or handles large data sets. The following list suggests some techniques to break up CPU-intensive or data-intensive operations into smaller chunks so that your add-in avoids excessive resource consumption and keeps the Office application responsive. -- In a scenario where your add-in needs to read a large volume of data from an unbounded dataset, you can apply paging when reading the data from a table, or reduce the size of data in each shorter read operation, rather than attempting to complete the read in one single operation. You can do this through the [setTimeout](https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) method of the global object to limit the duration of input and output. It also handles the data in defined chunks instead of randomly unbounded data. Another option is to use [async](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) to handle your Promises. +- If your add-in needs to read a large volume of data from an unbounded dataset, you can apply paging when reading the data from a table, or reduce the size of data in each shorter read operation, rather than attempting to complete the read in one single operation. You can do this through the [setTimeout](https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) method of the global object to limit the duration of input and output. It also handles the data in defined chunks instead of randomly unbounded data. Another option is to use [async](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) to handle your Promises. -- If your add-in uses a CPU-intensive algorithm to process a large volume of data, you can use web workers to perform the long-running task in the background while running a separate script in the foreground, such as displaying progress in the user interface. Web workers do not block user activities and allow the HTML page to remain responsive. For an example of web workers, see [The Basics of Web Workers](https://www.html5rocks.com/tutorials/workers/basics/). See [Web Workers](https://developer.mozilla.org/docs/Web/API/Web_Workers_API) for more information about the Web Workers API. +- If your add-in uses a CPU-intensive algorithm to process a large volume of data, you can use [web workers](https://developer.mozilla.org/docs/Web/API/Web_Workers_API) to perform the long-running task in the background while running a separate script in the foreground, such as displaying progress in the user interface. Web workers don't block user activities and allow the HTML page to remain responsive. For an example of web workers, see [The Basics of Web Workers](https://www.html5rocks.com/tutorials/workers/basics/). -- If your add-in uses a CPU-intensive algorithm but you can divide the data input or output into smaller sets, consider creating a web service, passing the data to the web service to off-load the CPU, and wait for an asynchronous callback. +- If your add-in uses a CPU-intensive algorithm but you can divide the data input or output into smaller sets, consider creating a web service, passing the data to the web service to off-load the CPU, and waiting for an asynchronous callback. - Test your add-in against the highest volume of data you expect, and restrict your add-in to process up to that limit. @@ -145,7 +142,7 @@ Excel.run(async (context) => { }); ``` -Note that needing to untrack objects only becomes important when you're dealing with thousands of them. Most add-ins will not need to manage proxy object tracking. +Note that needing to untrack objects only becomes important when you're dealing with thousands of them. Most add-ins don't need to manage proxy object tracking. ## See also diff --git a/docs/design/accessibility-guidelines.md b/docs/design/accessibility-guidelines.md index cfe9aa2710..b94a0818b6 100644 --- a/docs/design/accessibility-guidelines.md +++ b/docs/design/accessibility-guidelines.md @@ -1,20 +1,26 @@ --- title: Accessibility guidelines for Office Add-ins description: Learn how to make your Office Add-in accessible to all users. -ms.date: 05/18/2023 +ms.date: 12/3/2024 ms.topic: best-practice ms.localizationpriority: medium --- # Accessibility guidelines -As you design and develop your Office Add-ins, you'll want to ensure that all potential users and customers are able to use your add-in successfully. Apply the following guidelines to ensure that your solution is accessible to all audiences. +As you design and develop your Office Add-ins, you'll want to ensure that all potential users and customers are able to use your add-in successfully. Engineering and implementing inclusive experiences provide better usability and customer satisfaction, as well as a larger market for your solutions. We recommend you become familiar with the Web Content Accessibility Guidelines (WCAG), international web standards that define what's needed for your add-in to be accessible. + +- [Explore the WCAG standards and resources](/compliance/regulatory/offering-wcag-2-1) +- [Explore the WCAG tutorials](https://www.w3.org/WAI/tutorials/) + +Apply the following guidelines to ensure that your solution is accessible to all audiences. ## Design for multiple input methods -- Ensure that users can perform operations by using only the keyboard. Users should be able to move to all actionable elements on the page by using a combination of the Tab and arrow keys. +- Ensure that users can perform operations by using only the keyboard. Users should be able to move to all actionable elements on the page by using a combination of the <kbd>Tab</kbd> and arrow keys. - On a mobile device, when users operate a control by touch, the device should provide useful audio feedback. - Provide helpful labels for all interactive controls. +- [Explore more design and UI resources.](/windows/apps/design/accessibility/accessibility) ## Make your add-in easy to use @@ -28,6 +34,7 @@ As you design and develop your Office Add-ins, you'll want to ensure that all po - Avoid unexpected color changes. - Provide meaningful and timely information to describe UI elements, titles and headings, inputs, and errors. Ensure that names of controls adequately describe the intent of the control. +- Verify you UI elements render correctly in the Windows high-contrast themes. - Follow [standard guidelines](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html) for color contrast. ## Account for assistive technologies @@ -38,8 +45,16 @@ As you design and develop your Office Add-ins, you'll want to ensure that all po - Provide a way for users to turn on captions or audio description with audio sources. - Provide alternatives to sound as a means to alert users, such as visual cues or vibrations. +## Test your add-in + +- Always use accessibility verification and testing tools like [Accessibility Insights](https://accessibilityinsights.io/) on your add-in to catch and resolve issues before you ship. +- Verify the screen reading experience using [Windows Narrator](https://support.microsoft.com/windows/e4397a0d-ef4f-b386-d8ae-c172f109bdb1), [JAWS](https://support.freedomscientific.com/Downloads/JAWS), or [NVDA](https://www.nvaccess.org/download/). +- Periodically run the tools to keep up with changes to the international accessibility guidelines. For more information, see [Accessibility testing](/windows/apps/design/accessibility/accessibility-testing). + ## See also -- [Web Content Accessibility Guidelines (WCAG) 2.0](https://www.w3.org/TR/wcag2ict/#REF-WCAG20) -- [Guidance on Applying WCAG 2.0 to Non-Web Information and Communications Technologies (WCAG2ICT)](https://www.w3.org/TR/wcag2ict/) -- [European Standard on accessibility requirements for Information and Communication Technologies (ICT)](https://www.etsi.org/deliver/etsi_en/301500_301599/301549/01.00.00_20/en_301549v010000c.pdf) +- [Accessibility in the Store](/windows/apps/design/accessibility/accessibility-in-the-store) +- [Web Content Accessibility Guidelines (WCAG) 2.2](https://www.w3.org/TR/WCAG22/) +- [Developing for Web Accessibility](https://www.w3.org/WAI/tips/developing/) +- [Accessibility Fundamentals Learning Path](/training/paths/accessibility-fundamental/) +- [European Accessibility Act (EAA)](https://www.deque.com/blog/european-accessibility-act-eaa-top-20-key-questions-answered/) diff --git a/docs/design/add-in-color.md b/docs/design/add-in-color.md index 9b2c9ca496..82e26532dd 100644 --- a/docs/design/add-in-color.md +++ b/docs/design/add-in-color.md @@ -1,7 +1,7 @@ --- title: Color guidelines for Office Add-ins description: Learn how to use colors in the UI of an Office Add-in. -ms.date: 06/18/2024 +ms.date: 10/28/2025 ms.topic: best-practice ms.localizationpriority: medium --- @@ -12,8 +12,10 @@ Color is often used to emphasize brand and reinforce visual hierarchy. It helps ![The color scheme for Office, Excel, Word, and PowerPoint. Major colors for Office are black and white, and minor colors are light gray, dark gray, and orange. The dominant color for Excel is green, Word is blue, and PowerPoint is orange.](../images/office-addins-color-schemes.png) +## Use UI component libraries [Fluent UI React](../quickstarts/fluent-react-quickstart.md) and [Fabric Core](fabric-core.md) include a set of default theme colors. When these libraries are applied to the components or layouts of an Office Add-in, the same goals apply. Color should communicate hierarchy, purposefully guiding customers to action without interfering with content. Theme colors from Fluent UI React or Fabric Core can introduce a new accent color to the overall interface. These accent colors can conflict with Office app branding and the hierarchy. Consider ways to avoid conflicts and interference. Use neutral accents or overwrite theme colors to match Office app branding or your own brand colors. +## Develop with theming APIs In Office applications, customers personalize their interfaces by applying an [Office UI theme](https://support.microsoft.com/office/365-63e65e1c-08d4-4dea-820e-335f54672310). Customers choose between four UI themes to vary styling of backgrounds and buttons in Excel, Outlook, PowerPoint, Word, and other apps in the Office suite. To make your add-ins feel like a natural part of Office and respond to personalization, use our [Theming APIs](/javascript/api/office/office.officetheme). For example, task pane background colors switch to a dark gray in some themes. With the Theming APIs, follow suit and adjust foreground text to ensure [accessibility](../design/accessibility-guidelines.md). > [!TIP] @@ -21,12 +23,19 @@ In Office applications, customers personalize their interfaces by applying an [O > - To ensure that your add-in applies the correct color combinations in its UI, test it with all four Office themes, including the **Use system setting** option. > - For guidance on how to dynamically match the design of your PowerPoint add-in with the current document or Office theme, see [Use document themes in your PowerPoint add-ins](../powerpoint/use-document-themes-in-your-powerpoint-add-ins.md). -Apply the following general guidelines for color. +## Apply best practices - Use color sparingly to communicate hierarchy and reinforce brand. - Overuse of a single accent color applied to both interactive and non-interactive elements can lead to confusion. For example, avoid using the same color for selected and unselected items in a navigation menu. - Avoid unnecessary conflicts with Office branded app colors. - Use your own brand colors to build association with your service or company. -- Ensure that all text is accessible. Be sure that there is a 4.5:1 contrast ratio between foreground text and background. +- Ensure that all text is [accessible](accessibility-guidelines.md). Be sure that there is a 4.5:1 contrast ratio between foreground text and background. - Be aware of color blindness. Use more than just color to indicate interactivity and hierarchy. - To learn more about designing add-in command icons with the Office icon color palette, see [icon guidelines](../design/add-in-icons.md). + +## See also + +- [Office Add-in design language](add-in-design-language.md) +- [Accessibility guidelines](accessibility-guidelines.md) +- [Branding patterns](branding-patterns.md) +- [Fluent UI React in Office Add-ins](../quickstarts/fluent-react-quickstart.md) diff --git a/docs/design/add-in-commands.md b/docs/design/add-in-commands.md index 948484cf16..54bf73fca6 100644 --- a/docs/design/add-in-commands.md +++ b/docs/design/add-in-commands.md @@ -1,7 +1,7 @@ ---- +--- title: Basic concepts for add-in commands description: Learn how to add custom ribbon buttons and menu items to Excel, Outlook, PowerPoint, and Word as part of an Office Add-in. -ms.date: 08/10/2024 +ms.date: 09/30/2025 ms.topic: overview ms.localizationpriority: high --- @@ -12,7 +12,7 @@ Add-in commands are UI elements that extend the Office UI and start actions in y > [!NOTE] > -> - SharePoint catalogs don't support add-in commands. You can deploy add-in commands via [Integrated Apps](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps) or [AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center), or use [sideloading](../testing/test-debug-non-local-server.md) to deploy your add-in command for testing. +> - SharePoint catalogs don't support add-in commands. You can deploy add-in commands via the [integrated apps portal](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps) or [Microsoft Marketplace](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center), or use [sideloading](../testing/test-debug-non-local-server.md) to deploy your add-in command for testing. > - Content add-ins don't currently support add-in commands. ## Types of add-in commands @@ -21,40 +21,73 @@ There are two types of add-in commands, based on the kind of action that the com - **Task pane commands**: The button or menu item opens the add-in's [task pane](task-pane-add-ins.md). You add this kind of add-in command with markup in the manifest. The "code behind" the command is provided by Office. - **Function commands**: The button or menu item runs any arbitrary JavaScript. The code almost always calls APIs in the Office JavaScript Library, but it doesn't have to. This type of add-in typically displays no UI other than the button or menu item itself. Note the following about function commands: - - The function that is triggered can call the [displayDialogAsync](/javascript/api/office/office.ui?view=common-js&preserve-view=true#office-office-ui-displaydialogasync-member(1)) method to show a dialog, which is a good way to display an error, show progress, or prompt for input from the user. If the add-in is configured to use a [shared runtime](../testing/runtimes.md#shared-runtime), the function can also call the [showAsTaskpane](/javascript/api/office/office.addin#office-office-addin-showastaskpane-member(1)) method. + - The runtime in which the function command runs is a full [browser-based runtime](../testing/runtimes.md#browser-runtime). It can render HTML and call out to the Internet to send or get data. + - The runtime closes when either the function completes or 5 minutes have passed, whichever is earlier. + - The function that is triggered can call the [displayDialogAsync](/javascript/api/office/office.ui?view=common-js&preserve-view=true#office-office-ui-displaydialogasync-member(1)) method to show a dialog. This is a good way to display an error, show progress, or prompt the user for input. -## Location of add-in commands + > [!NOTE] + > Because of the 5-minute timeout, the dialog should be designed so that users complete their interaction and close it within 5 minutes. Your add-in should use a task pane for longer interactions. -When a user installs an add-in, the location of its commands depends on the application, platform, and context. Add-in commands are found on the ribbon, in a default or custom tab, or on an action bar (only applies to certain Outlook platforms). They appear in the UI as a button or an item in a drop-down menu. + - If the add-in is configured to use a [shared runtime](../testing/runtimes.md#shared-runtime), the function can also call the [showAsTaskpane](/javascript/api/office/office.addin#office-office-addin-showastaskpane-member(1)) method. -For add-in commands that appear on the ribbon, if you're using the simplified ribbon layout, the add-in name is removed from the app bar. Only the add-in command button on the ribbon remains. + > [!TIP] + > Function commands aren't the only way to run arbitrary JavaScript in an add-in. An add-in can also include: + > + > - Custom handlers for certain events, such as a user opening an new message pane in Outlook. + > - Custom [Copilot agents](agent-and-add-in-overview.md) that take actions in response to natural language requests from the add-in's users. + +## Location of add-in commands + +When a user installs an add-in, the add-in's commands are found on the ribbon, in a built-in Office tab or a custom tab that is specified in the manifest. (You can also put add-in commands on a [custom contextual tab](#contextual-tabs) that your add-in code defines at runtime.) They appear in the UI as a button or an item in a dropdown menu. As the ribbon or action bar gets more crowded, add-in commands are displayed in the overflow menu. Commands for the same add-in are usually grouped together. +In Office on the web, if you're using the single-line or simplified ribbon layout, the add-in name isn't shown on the ribbon. Only the add-in's command icon is shown. + ### Excel, PowerPoint, and Word -The default tab depends on the application and context. For Excel, PowerPoint, and Word, the default tab is **Home**. +The following shows an example of add-in commands in a custom group on the **Data** tab of the Excel ribbon. ![Sample add-in commands highlighted in the Excel ribbon.](../images/add-in-commands-1.png) ### Outlook -For Outlook, the default location of an add-in command is based on the platform and current Outlook mode. For guidance, see [Use add-ins in Outlook](https://support.microsoft.com/office/1ee261f9-49bf-4ba6-b3e2-2ba7bcab64c8). +For Outlook, when you want an add-in command on a built-in ribbon tab, rather than creating your own, the command will appear on the default tab based on the platform and current Outlook mode. For guidance, see [Use add-ins in Outlook](https://support.microsoft.com/office/1ee261f9-49bf-4ba6-b3e2-2ba7bcab64c8). -### Drop-down menu +### Dropdown menu -A drop-down menu add-in command defines a static list of items. The menu can be any mix of items that execute a function or that open a task pane. Submenus aren't supported. +A dropdown menu add-in command defines a static list of items. The menu can be any mix of items that execute a function or that open a task pane. Submenus aren't supported. ![A button that drops down a menu on the Outlook ribbon.](../images/commands-menu-button-1.png) +### Grouped add-in commands on the ribbon + +Multiple add-in commands can be grouped together on the ribbon. A group must contain at least one add-in command in the form of a button or a dropdown menu. In Office on Windows and on Mac, the label and icon of a button or dropdown menu are usually shown for add-in commands in a group. However, the icon size and label visibility may vary due to the following factors that constrain space. + +- The number of add-in commands in the group. +- The size of the Office client window. + +If the client window is maximized and there are more than three controls in a group, the label of each control is shown, but the size of its icon may vary (some are shown as 16 x 16 pixels while others are shown as 32 x 32 pixels). + +When there are two or more add-in commands in a group and space becomes limited, the following adjustments are made to how the add-in commands are displayed. These changes are applied to the groups of add-in commands from right to left across the ribbon in the following sequence. + +1. Small icons (16 x 16 pixels) and labels are shown for each add-in command in a group. +1. Only small icons are shown. +1. The group is displayed as a dropdown menu instead of showing individual add-in commands on the ribbon. A scroll slider icon also appears on the ribbon, so that you can scroll through the ribbon. + +In Office on the web, the icon size and label visibility of controls in groups don't change as the browser window is resized. The scroll slider icon is simply shown on the ribbon. + ## Command capabilities The following command capabilities are currently supported. ### Extension points -- Ribbon tabs - Extend built-in tabs or create a new custom tab. An add-in can have just one custom tab. +- Ribbon tabs - Extend built-in tabs or create a new custom core tab. An add-in can have just one custom core tab. (You can also put add-in commands on a [custom contextual tab](#contextual-tabs).) + + > [!NOTE] + > For Outlook, custom tabs are only supported in classic Outlook on Windows. In Outlook on the web, on Mac, and in the new Outlook on Windows, you can put custom groups of controls on one of the built-in ribbon tabs instead. - Context menus - Extend selected context menus. ### Control types @@ -62,14 +95,14 @@ The following command capabilities are currently supported. - Simple buttons - trigger specific actions. - Menus - simple menu dropdown with buttons that trigger actions. -### Default Enabled or Disabled Status +### Default availability state -You can specify whether the command is enabled or disabled when your add-in launches, and programmatically change the setting. +You can specify whether the command is available when your add-in launches, and programmatically change the setting. > [!NOTE] -> This feature isn't supported in all Office applications or scenarios. For more information, see [Enable and Disable Add-in Commands](disable-add-in-commands.md). +> This feature isn't supported in all Office applications or scenarios. For more information, see [Change the availability of add-in commands](disable-add-in-commands.md). -### Position on the ribbon (preview) +### Position on the ribbon You can specify where a custom tab appears on the Office application's ribbon, such as "just to the right of the Home tab". @@ -85,7 +118,7 @@ You can insert the built-in Office ribbon buttons into your custom command group ### Contextual tabs -You can specify that a tab is only visible on the ribbon in certain contexts, such as when a chart is selected in Excel. +You can specify a custom contextual tab; that is, a tab that is only visible on the ribbon in certain contexts, such as when a chart is selected in Excel. > [!NOTE] > This feature isn't supported in all Office applications or scenarios. For more information, see [Create custom contextual tabs in Office Add-ins](contextual-tabs.md). @@ -95,8 +128,8 @@ You can specify that a tab is only visible on the ribbon in certain contexts, su Add-in commands are currently supported on the following platforms, except for limitations specified in the subsections of [Command capabilities](#command-capabilities) earlier. - Office on the web -- Office on Windows (build 16.0.6769+, connected to a Microsoft 365 subscription) -- Office on Mac (build 15.33+, connected to a Microsoft 365 subscription) +- Office on Windows (Version 1604 (Build 6769.2000) or later, connected to a Microsoft 365 subscription) +- Office on Mac (Version 15.33 (17040900) or later, connected to a Microsoft 365 subscription) - Perpetual Office 2019 or later on Windows or on Mac > [!NOTE] @@ -112,22 +145,36 @@ Apply the following best practices when you develop add-in commands. - Use commands to represent a specific action with a clear and specific outcome for users. Don't combine multiple actions in a single button. - Provide granular actions that make common tasks within your add-in more efficient to perform. Minimize the number of steps an action takes to complete. -- For the placement of your commands in the Office app ribbon: - - Place commands on an existing tab (Insert, Review, and so on) if the functionality provided fits there. For example, if your add-in enables users to insert media, add a group to the Insert tab. Note that not all tabs are available across all Office versions. For more information, see [Office Add-ins manifest](../develop/add-in-manifests.md). - - Place commands on the Home tab if the functionality doesn't fit on another tab, and you have fewer than six top-level commands. You can also add commands to the Home tab if your add-in needs to work across Office versions (such as Office on the web or desktop) and a tab is not available in all versions (for example, the Design tab doesn't exist in Office on the web). - - Place commands on a custom tab if you have more than six top-level commands. - - Name your group to match the name of your add-in. If you have multiple groups, name each group based on the functionality that the commands in that group provide. - - Don't add unnecessary buttons to increase the real estate of your add-in. - - Don't position a custom tab to the left of the Home tab, or give it focus by default when the document opens, unless your add-in is the primary way users will interact with the document. Giving excessive prominence to your add-in inconveniences and annoys users and administrators. - - If your add-in is the primary way users interact with the document and you have a custom ribbon tab, consider integrating into the tab the buttons for the Office functions that users will frequently need. - - If the functionality provided with a custom tab should only be available in certain contexts, use [custom contextual tabs](contextual-tabs.md). If you use custom contextual tabs, make sure to implement a [fallback experience for when your add-in runs on platforms that don't support custom contextual tabs](contextual-tabs.md#implement-an-alternate-ui-experience-when-custom-contextual-tabs-arent-supported). - - > [!NOTE] - > Add-ins that take up too much space might not pass [AppSource validation](/legal/marketplace/certification-policies). - - For all icons, follow the [icon design guidelines](add-in-icons.md). - Provide a version of your add-in that works on Office applications or platforms (such as iPad) that don't support commands. A single add-in manifest can be used for these versions. +### Best practices for add-in commands on the ribbon + +The following table outlines the recommended limits for objects on an Office app ribbon. + +| Object | Recommended limit | Usability rationale | +| ------ | ----------------- | ------------------- | +| Tabs | Seven visible tabs at a time | Prevents overwhelming users with too many options and helps them remember where commands are located. We recommend using contextual tabs to reduce clutter. | +| Groups per tab | Six groups | Helps users scan and locate commands quickly. | +| Commands per group | Seven commands | Decreases decision fatigue from too many options. | +| Total commands on the ribbon | 70 visible commands | Helps users locate actions efficiently. If your add-in has more than 70 commands, we recommend implementing galleries, dropdown menus, or dialogs for overflow. | + +In addition to the recommended object limits, keep the following in mind when configuring add-in commands on the ribbon. + +- Place commands on an existing tab, such as the Insert and Review tabs, if the functionality provided fits there. For example, if your add-in enables users to insert media, add a group to the Insert tab. Note that not all tabs are available across all Office versions. For more information, see [Office Add-ins manifest](../develop/add-in-manifests.md). +- Place commands on the Home tab if the functionality doesn't fit on another tab, and you have fewer than six top-level commands. You can also add commands to the Home tab if your add-in needs to work across Office versions (such as Office on the web or desktop) and a tab isn't available in all versions. +- Place commands on a custom tab if you have more than six top-level commands. +- Name your group to match the name of your add-in. If you have multiple groups, name each group based on the functionality that the commands in that group provide. +- Make sure that groups collapse gracefully when the size of the Office app window changes. While the ribbon offers dynamic resizing (see [Grouped add-in commands on the ribbon](#grouped-add-in-commands-on-the-ribbon)), you must also define group combinations for your add-in. +- Don't add unnecessary buttons to increase the real estate of your add-in. +- Don't position a custom tab to the left of the Home tab, or give it focus by default when the document opens, unless your add-in is the primary way users will interact with the document. Giving excessive prominence to your add-in inconveniences and annoys users and administrators. +- If your add-in is the primary way users interact with the document and you have a custom ribbon tab, consider integrating into the tab the buttons for the Office functions that users will frequently need. +- If the functionality provided with a custom tab should only be available in certain contexts, use [custom contextual tabs](contextual-tabs.md). If you use custom contextual tabs, make sure to implement a [fallback experience for when your add-in runs on platforms that don't support custom contextual tabs](contextual-tabs.md#implement-an-alternate-ui-experience-when-custom-contextual-tabs-arent-supported). +- Implement a dialog to provide users with advanced options. This prevents your add-in from overloading the ribbon with rarely used commands. To learn how to implement a dialog, see [Use the Office dialog API in Office Add-ins](../develop/dialog-api-in-office-add-ins.md). + +> [!NOTE] +> Add-ins that take up too much space might not pass [Microsoft Marketplace validation](/legal/marketplace/certification-policies). + ## Next steps The best way to get started using add-in commands is to take a look at the [Office Add-in commands samples](https://github.com/OfficeDev/Office-Add-in-Commands-Samples/) on GitHub. diff --git a/docs/design/add-in-design-language.md b/docs/design/add-in-design-language.md index 16a85bce67..139f710e39 100644 --- a/docs/design/add-in-design-language.md +++ b/docs/design/add-in-design-language.md @@ -1,7 +1,7 @@ --- title: Office Add-in design language description: Learn how to make your Office Add-in visually compatible with Office. -ms.date: 08/18/2023 +ms.date: 02/11/2025 ms.topic: overview ms.localizationpriority: medium --- @@ -23,3 +23,23 @@ The Office design language is a clean and simple visual system that ensures cons Many Office Add-ins are associated with a preexisting brand. You can retain a strong brand and its visual or component language in your add-in. Look for opportunities to retain your own visual language while integrating with Office. Consider ways to swap out Office colors, typography, icons, or other stylistic elements with elements of your own brand. Consider ways to follow common add-in layouts or UX design patterns while inserting controls and components that are familiar to your customers. Inserting a heavily branded HTML-based UI inside of Office can create dissonance for customers. Find a balance that fits seamlessly in Office but also clearly aligns with your service or parent brand. When an add-in doesn't fit with Office, it's often because stylistic elements conflict. For example, typography is too large and off grid, colors are contrasting or particularly loud, or animations are superfluous and behave differently than Office. The appearance and behavior of controls or components veer too far from Office standards. + +## Review guidelines for visual elements + +Learn about each visual element that makes up an Office Add-in, including guidelines and recommended practices. + +- [Color guidelines for Office Add-ins](add-in-color.md) +- [Icon guidelines for Office Add-ins](add-in-icons.md) +- [Layout guidelines for Office Add-ins](add-in-layout.md) +- [Using motion in Office Add-ins](using-motion-office-addins.md) +- [Typography guidelines for Office Add-ins](add-in-typography.md) + +## Design toolkits for download + +To help you get started, we've created toolkits for use with either the [Sketch](https://www.sketch.com/) application for Mac or the [Adobe XD](https://www.adobe.com/products/xd/features.html) application for Windows or Mac. The following downloads include all of our available patterns, along with brief descriptions and layout recommendations. + +- [Fluent UI Design Sketch Toolkit](https://aka.ms/fabric-sketch-toolkit) +- [Fluent UI Design Adobe XD Toolkit](https://aka.ms/fabric-toolkit) +- [Add-in Sketch Toolkit](https://aka.ms/addins_sketch_toolkit) +- [Add-in Adobe XD Toolkit](https://aka.ms/addins_toolkit) +- [Segoe UI and Fabric MDL2 icon font](https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/fabric-website/files/segoeui_fabricmdl2_icon_fonts.zip) diff --git a/docs/design/add-in-icons-fresh.md b/docs/design/add-in-icons-fresh.md index 91ca3314b9..b8a7236be6 100644 --- a/docs/design/add-in-icons-fresh.md +++ b/docs/design/add-in-icons-fresh.md @@ -1,7 +1,7 @@ ---- +--- title: Fresh style icon guidelines for Office Add-ins description: Guidelines for using Fresh style icons in Office Add-ins. -ms.date: 08/18/2023 +ms.date: 08/25/2025 ms.topic: best-practice ms.localizationpriority: medium --- @@ -42,7 +42,7 @@ Office desktop icons are bitmap images. Different sizes will render depending on - 80 px (Required) > [!IMPORTANT] -> For an image that is your add-in's representative icon, see [Create effective listings in AppSource and within Office](/partner-center/marketplace-offers/create-effective-office-store-listings#create-an-icon-for-your-add-in) for size and other requirements. +> For an image that is your add-in's representative icon, see [Create effective listings in Microsoft Marketplace and within Office](/partner-center/marketplace-offers/create-effective-office-store-listings#create-an-icon-for-your-add-in) for size and other requirements. Make sure to redraw your icons for each size rather than shrink them to fit. @@ -85,7 +85,7 @@ All modifiers should have a 1 px transparent cutout between each element, includ ## Icon colors > [!NOTE] -> These color guidelines are for ribbon icons used in [Add-in commands](add-in-commands.md). These icons are not rendered with Fluent UI and the color palette is different from the palette described at [Microsoft UI Fabric | Colors | Shared](https://fluentfabric.azurewebsites.net/#/color/shared). +> These color guidelines are for ribbon icons used in [Add-in commands](add-in-commands.md). These icons aren't rendered with Fluent UI. Office icons have a limited color palette. Use the colors listed in the following table to guarantee seamless integration with the Office UI. Apply the following guidelines to the use of color. @@ -128,6 +128,12 @@ Office icons are designed to render well in high contrast modes. Foreground elem ## See also +### Unified manifest reference + +- [`"extensions.ribbons"` array](/microsoft-365/extensibility/schema/extension-ribbons-array) + +### Add-in only manifest reference + - [Icon manifest element](/javascript/api/manifest/icon) - [IconUrl manifest element](/javascript/api/manifest/iconurl) - [HighResolutionIconUrl manifest element](/javascript/api/manifest/highresolutioniconurl) diff --git a/docs/design/add-in-icons-monoline.md b/docs/design/add-in-icons-monoline.md index 0133b5788a..586ed85f6a 100644 --- a/docs/design/add-in-icons-monoline.md +++ b/docs/design/add-in-icons-monoline.md @@ -1,7 +1,7 @@ ---- +--- title: Monoline style icon guidelines for Office Add-ins description: Guidelines for using Monoline style icons in Office Add-ins. -ms.date: 08/18/2023 +ms.date: 02/12/2025 ms.topic: best-practice ms.localizationpriority: medium --- @@ -57,7 +57,7 @@ We recommend that you produce each icon in all these sizes to support high DPI d **16 px, 20 px, 24 px, 32 px, 40 px, 48 px, 64 px, 80 px, 96 px** > [!IMPORTANT] -> For an image that is your add-in's representative icon, see [Create effective listings in AppSource and within Office](/partner-center/marketplace-offers/create-effective-office-store-listings#create-an-icon-for-your-add-in) for size and other requirements. +> For an image that is your add-in's representative icon, see [Create effective listings in Microsoft Marketplace and within Office](/partner-center/marketplace-offers/create-effective-office-store-listings#create-an-icon-for-your-add-in) for size and other requirements. ### Layout @@ -205,6 +205,12 @@ The final icons should be saved as .png image files. Use PNG format with a trans ## See also +### Unified manifest reference + +- ["extensions.ribbons" array](/microsoft-365/extensibility/schema/extension-ribbons-array) + +### Add-in only manifest reference + - [Icon manifest element](/javascript/api/manifest/icon) - [IconUrl manifest element](/javascript/api/manifest/iconurl) - [HighResolutionIconUrl manifest element](/javascript/api/manifest/highresolutioniconurl) diff --git a/docs/design/add-in-icons.md b/docs/design/add-in-icons.md index c1f47fdb56..af103752dc 100644 --- a/docs/design/add-in-icons.md +++ b/docs/design/add-in-icons.md @@ -1,7 +1,7 @@ --- title: Icon guidelines for Office Add-ins description: Get an overview of how to design icons and the Fresh and Monoline design styles for add-in commands. -ms.date: 08/18/2023 +ms.date: 11/03/2025 ms.topic: overview ms.localizationpriority: medium --- @@ -10,6 +10,9 @@ ms.localizationpriority: medium Icons are the visual representation of a behavior or concept. They are often used to add meaning to controls and commands. Visuals, either realistic or symbolic, enable the user to navigate the UI the same way signs help users navigate their environment. They should be simple, clear, and contain only the necessary details to enable customers to quickly parse what action will occur when they choose a control. +> [!NOTE] +> This article about designing icons for ribbon buttons. For guidance about icons that represent the add-in in the app acquisition and managment UIs of Microsoft 365 applications, see [Design icons for add-in acquisisiton and management](microsoft-365-extension-management-icons.md). + Office app ribbon interfaces have a standard visual style. This ensures consistency and familiarity across Office apps. The guidelines will help you design a set of PNG assets for your solution that fit in as a natural part of Office. Many HTML containers contain controls with iconography. Use Fabric Core’s custom font to render Office styled icons in your add-in. The icon font provided by [Fabric Core](fabric-core.md) contains many glyphs for common Office metaphors that you can scale, color, and style to suit your needs. If you have an existing visual language with your own set of icons, feel free to use it in your HTML canvases. Building continuity with your own brand with a standard set of icons is an important part of any design language. Be careful to avoid creating confusion for customers by conflicting with Office metaphors. diff --git a/docs/design/agent-and-add-in-overview.md b/docs/design/agent-and-add-in-overview.md new file mode 100644 index 0000000000..90d11be18a --- /dev/null +++ b/docs/design/agent-and-add-in-overview.md @@ -0,0 +1,259 @@ +--- +title: Combine Copilot Agents with Office Add-ins (preview) +description: Get an overview of why and how to combine a Copilot agent with an Office Add-in. +ms.date: 10/17/2025 +ms.topic: overview +ms.localizationpriority: medium +--- + +# Combine Copilot Agents with Office Add-ins (preview) + +> [!NOTE] +> This article assumes you're familiar with Copilot declarative agents. If you're not, start with the following: +> +> - [Declarative agents for Microsoft 365 Copilot overview](/microsoft-365-copilot/extensibility/overview-declarative-agent). +> - [Agents are apps for Microsoft 365](/microsoft-365-copilot/extensibility/agents-are-apps). + +Including a Microsoft 365 Copilot agent in an Office Add-in provides two benefits: + +- Copilot becomes a natural language interface for the add-in's functionality. +- The agent can pass parameters to the JavaScript it invokes, which isn't possible when a [function command](add-in-commands.md#types-of-add-in-commands) is invoked from a button or menu item. + +You can also think of an Office Add-in as a skill in a Copilot agent. Because Office Add-ins use the [Office JavaScript Library](../develop/understanding-the-javascript-api-for-office.md) to perform read and write operations on Office documents, these operations become actions in the Copilot agent. + +## Scenarios + +The following are some selected ways in which adding a Copilot agent enhances the value of an add-in to users. + +- **Learning how to use the add-in**: When a user needs to perform multiple steps or tasks with the add-in to achieve a goal, the chat interface of Copilot can ease the process of getting started with the add-in. For example, consider a legal firm that needs to have a list of questions that must be answered about each lease that it prepares. Creating this list of questions can be time-consuming and labor-intensive. But a Copilot agent that uses the Office JavaScript Library can be prompted to produce a first draft list of questions and insert them into a Word document. + +- **Content analysis**: An agent can be used to analyze the content of a document or spreadsheet and take action depending on what it finds. The following are examples. + + - An agent analyzes a Request for Proposal and then fetches the answers to questions in the RFP from a backend system. The user simply prompts the agent to "Fill in the answers you know to the questions." + - An agent analyzes a document, or a table in a spreadsheet, for content that implies certain actions must be taken, either in the document itself or elsewhere in the customer's business systems. The user might say "Review the document for any items I missed on the audit list." + +- **Trusted insertion of data**: If you prompt a typical AI engine with a question, it will combine information it finds and compose an answer; a process that can introduce inaccuracies. But a Copilot agent based on an add-in can insert data *unchanged* from a trusted source. Some examples: + + - Consider an add-in that enables the insertion of legal research into Word where it can then be edited. A user prompts the agent: "In what circumstances can a lease of residential space in Indiana be broken unilaterally by the lessor?" The add-in then fetches content, unchanged, from precedents and statutes. + - Consider an add-in that manages the inventory of a digital assets. In the Copilot agent chat, a user prompts: "Insert a table of our color photos with the name of each, the number of times it was downloaded, and it's size in megabytes, sorted in order from most downloaded." The add-in then fetches this data, unchanged, from the system of record and inserts the table into an Excel spreadsheet. + +## The relation of Copilot agents to the Add-in framework + +A Copilot agent is a natural language interface for an add-in. + +An add-in can be configured to be *only* a skill in a Copilot agent. It doesn't have to include a task pane, custom ribbon buttons, or custom menus; but it can have any of these in addition to being a Copilot skill. The best approach depends on the user scenarios that the add-in should enable. + +- If the add-in should provide simple, fast actions that don't need parameters passed to them, include custom ribbon buttons or menus, called [add-in commands](add-in-commands.md), in the add-in. +- If the add-in needs a dashboard experience, needs the user to configure settings, needs to display metadata about the content of the Office document, or needs a page-like experience for any other reason, include a task pane in the add-in. +- If the add-in needs to provide complex actions that require parameters passed at runtime or needs a natural language interface, include a Copilot agent. + +> [!NOTE] +> +> - Currently, only Excel, PowerPoint, and Word add-ins can be configured as a skill in Copilot. We're working to support Outlook. +> - Copilot agents aren't currently supported in Office on Mac. +> - An add-in must use the [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md) to be configured as a skill in Copilot. +> - A [content add-in](content-add-ins.md) cannot be a skill in Copilot. + +## Major tasks + +There are two major tasks to configuring an add-in as a Copilot skill, and they are analogous to the two tasks for configuring [function commands](add-in-commands.md#types-of-add-in-commands) for an add-in. + +- Create JavaScript functions that implement the agent's actions. +- Use JSON to specify for Office and the JavaScript runtimes the names of these functions. + +## JSON configuration + +Configuration of an add-in to be a Copilot skill requires three JSON-formatted files that are described in the following subsections. + +### Unified manifest for Microsoft 365 + +There are two parts of the manifest that you configure. First, create an action object that identifies the JavaScript function that is invoked by the action. The following is an example (with some extraneous markup omitted). Note the following about this code. + +- The "page" property specifies the URL of the web page that contains an embedded script tag that, in turn, specifies the URL of the JavaScript file where the function is defined. That same file contains an invocation of the [Office.actions.associate](/javascript/api/office/office.actions#office-office-actions-associate-member(1)) method to map the function to an action ID. +- The [`"actions.id"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item#id) property in the manifest is the same action ID that is passed to the call of `associate`. +- The [`"actions.type"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item#type) property is set to "executeDataFunction", which is the type that can accept parameters and can be invoked by Copilot. + +```json +"extensions": [ + + ... + + "runtimes": [ + { + "id": "CommandsRuntime", + "type": "general", + "code": { + "page": "https://localhost:3000/commands.html" + }, + "lifetime": "short", + "actions": [ + { + "id": "fillcolor", + "type": "executeDataFunction", + } + ] + } + ] +] +``` + +Second, create a declarative agent object that identifies the file containing the detailed configuration of the agent. The following is an example. + +```json +"copilotAgents": { + "declarativeAgents": [ + { + "id": "ContosoCopilotAgent", + "file": "declarativeAgent.json" + } + ] +} +``` + +The reference documentation for the manifest JSON is at [Microsoft 365 app manifest schema reference](/microsoft-365/extensibility/schema/). + +### Declarative agent configuration + +The agent configuration file includes instructions for the agent and specifies one or more API plug-in configuration files that will contain the detailed configuration of the agent's actions. The following is an example. Note the following about this JSON. + +- The conversation starter appears in the chat canvas of Copilot. +- The `"actions.id"` property in this file is the collective ID of all the functions in the file specified in `"actions.file"`. It doesn't have to match the `"actions.id"` in the manifest. + +```json +{ + "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.5/schema.json", + "version": "v1.5", + "name": "Excel Add-in + Agent", + "description": "Agent for working with Excel cells.", + "instructions": "You are an agent for working with an add-in. You can work with any cells, not just a well-formatted table.", + "conversation_starters": [ + { + "title": "Change cell color", + "text": "I want to change the color of cell B2 to orange" + } + ], + "actions": [ + { + "id": "localExcelPlugin", + "file": "Excel-API-local-plugin.json" + } + ] +} +``` + +[!INCLUDE [Validation warning about missing 'auth' property](../includes/auth-property-warning-note.md)] + +The reference documentation for declarative agents is at [Declarative agent schema 1.5 for Microsoft 365 Copilot](/microsoft-365-copilot/extensibility/declarative-agent-manifest-1.5). + +### Copilot API plug-in configuration + +The API plug-in configuration file specifies the "functions" of the plug-in in the sense of agent actions, not JavaScript functions, including the instructions for the action. It also configures the JavaScript runtime for Copilot. The following is an example. About this JSON, note the following: + +- The `"functions.name"` must match the `"extensions.runtimes.actions.id"` property in the add-in manifest. +- The `"reasoning.description"` and `"reasoning.instructions"` refer to a JavaScript function, not a REST API. +- The `"responding.instructions"` property only provides *guidance* to Copilot about how to respond. It doesn't put any limits or structural requirements on the response. +- The `"runtimes.run_for_functions"` array must include either the same string as `"functions.name"` or a wildcard string that matches it. +- The `"runtimes.spec.local_endpoint"` property specifies that the JavaScript function that is associated with the "fillcolor" string is available in an Office Add-in, rather than in some REST endpoint. +-The `"runtimes.spec.allowed_host"` property specifies that the agent should only be visible in Excel. + +```json +{ + "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.3/schema.json", + "schema_version": "v2.3", + "name_for_human": "Excel Add-in + Agent", + "description_for_human": "Add-in Actions in Agents", + "namespace": "addinfunction", + "functions": [ + { + "name": "fillcolor", + "description": "fillcolor changes a single cell location to a specific color.", + "parameters": { + "type": "object", + "properties": { + "cell": { + "type": "string", + "description": "A cell location in the format of A1, B2, etc.", + "default" : "B2" + }, + "color": { + "type": "string", + "description": "A color in hex format, e.g., #30d5c8", + "default" : "#30d5c8" + } + }, + "required": ["cell", "color"] + }, + "returns": { + "type": "string", + "description": "A string indicating the result of the action." + }, + "states": { + "reasoning": { + "description": "`fillcolor` changes the color of a single cell based on the grid location and a color value.", + "instructions": "The user will ask for a color that isn't in the hex format needed in most cases, make sure to convert to the closest approximation in the right format." + }, + "responding": { + "description": "`fillcolor` changes the color of a single cell based on the grid location and a color value.", + "instructions": "If there is no error present, tell the user the cell location and color that was set." + } + } + } + ], + "runtimes": [ + { + "type": "LocalPlugin", + "spec": { + "local_endpoint": "Microsoft.Office.Addin", + "allowed_host": ["workbook"] + }, + "run_for_functions": ["fillcolor"] + } + ] +} +``` + +The reference documentation for API plug-ins is at [API plugin manifest schema 2.3 for Microsoft 365 Copilot](/microsoft-365-copilot/extensibility/api-plugin-manifest-2.3). + +## Create the JavaScript functions + +The JavaScript functions that will be invoked by the Copilot agent are created exactly as [function commands](../develop/create-addin-commands-unified-manifest.md#add-a-function-command) are created. The following is an example. Note the following about this code. + +- Unlike a function command, a function associated with a Copilot action can take parameters. +- The first parameter of the `associate` method must match both the `"extensions.runtimes.actions.id"` property in the add-in manifest and the `"functions.name"` property in the API plug-in's JSON. + +```javascript +async function fillColor(cell, color) { + await Excel.run(async (context) => { + context.workbook.worksheets.getActiveWorksheet().getRange(cell).format.fill.color = color; + await context.sync(); + }) +} + +Office.onReady((info) => { + Office.actions.associate("fillcolor", async (message) => { + const {cell, color} = JSON.parse(message); + await fillColor(cell, color); + return "Cell color changed."; + }); +}); +``` + +After your functions are created, create a UI-less HTML file that contains a `<script>` tag that loads the JavaScript file with the functions. The URL of this HTML file must match the value of the [`"extensions.runtimes.code.page"`](/microsoft-365/extensibility/schema/extension-runtime-code#page) property in the manifest. See [Unified manifest for Microsoft 365](#unified-manifest-for-microsoft-365) earlier in this article. + +## Troubleshooting combined agents and add-ins + +The following are some common problems and suggested solutions. + +- The agent action fails with a message indicating that the action wasn't found in the add-in. The following are some possible causes. + + - The `"functions.name"` property value in the plug-in's JSON doesn't *exactly match* any `"extensions.runtimes.actions.id"` property in the add-in manifest. + - There is a matching `"actions.id"` in the manifest, but the sibling `"actions.type"` value for the same action object isn't "executeDataFunction". + +- The agent action fails with a message indicating the action handler registration wasn't found. The following is a possible cause. + + - The add-in's JavaScript doesn't have a call of `Office.actions.associate` with the first parameter *exactly matching* the `"functions.name"` property value in the plug-in's JSON. + +## Next steps + +- [Build your first add-in as a Copilot skill](../quickstarts/agent-and-add-in-quickstart.md) +- [Add a Copilot agent to an add-in](../develop/agent-and-add-in.md) \ No newline at end of file diff --git a/docs/design/authentication-patterns.md b/docs/design/authentication-patterns.md index d8482bc8f3..0198684c4f 100644 --- a/docs/design/authentication-patterns.md +++ b/docs/design/authentication-patterns.md @@ -1,6 +1,6 @@ --- title: Authentication design guidelines for Office Add-ins -ms.date: 08/14/2023 +ms.date: 06/24/2025 ms.topic: best-practice description: Learn how to visually design a sign-on or sign-up page in an Office Add-in. @@ -32,7 +32,7 @@ Add-ins may require users to sign-in or sign-up in order to access features and ![The Identity Provider Choices dialog in an Office application.](../images/add-in-auth-choices-dialog.png) -1. Identity Provider Sign-in - The identity provider will have their own UI. Microsoft Azure Active Directory allows customization of sign-in and access panel pages for consistent look and feel with your service. [Learn More](/azure/active-directory/fundamentals/customize-branding). +1. Identity Provider Sign-in - The identity provider will have their own UI. Microsoft Entra ID allows customization of sign-in and access panel pages for consistent look and feel with your service. For more information, see [Configure your company branding](/entra/fundamentals/how-to-customize-branding). ![The Identity Provider Sign-in dialog in an Office application.](../images/add-in-auth-identity-sign-in.png) diff --git a/docs/design/branding-patterns.md b/docs/design/branding-patterns.md index 08036409e4..6a3e86b489 100755 --- a/docs/design/branding-patterns.md +++ b/docs/design/branding-patterns.md @@ -1,17 +1,19 @@ --- title: Branding patterns design guidelines for Office Add-ins description: Learn how to brand your Office Add-in while staying compatible with the visual design of Office. -ms.date: 05/18/2023 +ms.date: 10/29/2025 ms.topic: best-practice ms.localizationpriority: medium --- # Branding patterns -These patterns provide brand visibility and context to your add-in users. +Implement recommended design patterns in your add-in to promote brand visibility while maintaining seamless integration with Office applications. ## Best practices +The following table outlines design best practices to enhance your add-in's brand recognition. + |Do |Don't| |:---- |:----| | Use familiar UI components with applied branding accents like typography and color. | Don't invent new UI components that contradict established Office UI. | @@ -20,16 +22,26 @@ These patterns provide brand visibility and context to your add-in users. | Make your solution recognizable and connect your screens together with consistent visual elements. | Don't hide your solution with unrecognizable and inconsistently applied visual elements. | | Build connection with a parent service or business to ensure that customers know and trust your solution. | Don't make customers learn a new brand concept if there's a useful and understandable relationship that can be leveraged to build trust and value. | -Apply the following patterns and components as applicable to allow users to embrace the full utility of your add-in. +## Design patterns and components + +Apply the following patterns and components to allow users to embrace the full utility of your add-in. -## Brand Bar +### Brand Bar The brand bar is a space in the footer to include your brand name and logo. It also serves as a link to your brand's website and an optional access location. ![Brand bar displayed in an add-in task pane of an Office desktop application.](../images/add-in-brand-bar.png) -## Splash Screen +### Splash Screen Use this screen to display your branding while the add-in is loading or transitioning between UI states. ![Brand splash screen displayed in an add-in task pane of an Office desktop application.](../images/add-in-splash-screen.png) + +## See also + +- [Office Add-in design language](add-in-design-language.md) +- [Color guidelines for Office Add-ins](add-in-color.md) +- [First-run experience patterns](first-run-experience-patterns.md) +- [Accessibility guidelines](accessibility-guidelines.md) +- [Best practices for developing Office Add-ins](../concepts/add-in-development-best-practices.md) \ No newline at end of file diff --git a/docs/design/built-in-button-integration.md b/docs/design/built-in-button-integration.md index a1f6f658fd..c487390bfd 100644 --- a/docs/design/built-in-button-integration.md +++ b/docs/design/built-in-button-integration.md @@ -1,7 +1,7 @@ ---- +--- title: Integrate built-in Office buttons into custom control groups and tabs description: Learn how to include built-in Office buttons in your custom command groups and tabs on the Office ribbon. -ms.date: 06/26/2024 +ms.date: 06/10/2025 ms.topic: how-to ms.localizationpriority: medium --- @@ -17,17 +17,98 @@ You can insert built-in Office buttons into your custom control groups on the Of > [!IMPORTANT] > The add-in feature described in this article is only available in **PowerPoint** on the web, on Windows, and on Mac. +Open the tab for the type of manifest your add-in uses for the details of the manifest markup. + +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) + +[!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] + ## Insert a built-in control group into a custom tab -To insert a built-in Office control group into a tab, add an [OfficeGroup](/javascript/api/manifest/customtab#officegroup) element as a child element in the parent **\<CustomTab\>** element. The `id` attribute of the of the **\<OfficeGroup\>** element is set to the ID of the built-in group. See [Find the IDs of controls and control groups](#find-the-ids-of-controls-and-control-groups). +To insert a built-in Office control group into a custom tab, add a group object with a [`"builtInGroupId"`](/microsoft-365/extensibility/schema/extension-ribbons-array-tabs-item#builtintabid) property *instead of an [`"id"`](/microsoft-365/extensibility/schema/extension-ribbons-array-tabs-item#id) property* to the [`"groups"`](/microsoft-365/extensibility/schema/extension-ribbons-array-tabs-item#groups) array of your custom tab object. Set to the ID of the built-in group. See [Find the IDs of controls and control groups](#find-the-ids-of-controls-and-control-groups). *The built-in group object should have no other properties.* + +The following example adds the Office Paragraph control group to a custom tab. + +```json +"extensions": [ + ... + { + ... + "ribbons": [ + ... + { + ... + "tabs": [ + { + "id": "MyTab", + ... + "groups": [ + ... // Optionally, other groups in the tab. + { + "builtInGroupId": "Paragraph" + }, + ... // Optionally, other groups in the tab. + ] + } + ] + } + ] + } +] +``` + +## Insert a built-in control into a custom group + +To insert a built-in Office control into a custom group, add a control object with a `"builtInControlId"` property *instead of an `"id"` property* to the [`"controls"`](/microsoft-365/extensibility/schema/extension-ribbons-custom-tab-groups-item#controls) array of your custom group object. Set to the ID of the built-in control. See [Find the IDs of controls and control groups](#find-the-ids-of-controls-and-control-groups). *The built-in control object should have no other properties.* + +The following example adds the Office Superscript control to a custom group. + +```json +"extensions": [ + ... + { + ... + "ribbons": [ + ... + { + ... + "tabs": [ + { + ... + "groups": [ + { + "id": "MyGroup", + ... + "controls": [ + ... // Optionally, other controls in the group. + { + "builtInControlId": "Superscript" + }, + ... // Optionally, other controls in the group. + ] + } + ] + } + ] + } + ] + } +] +``` + +# [Add-in only manifest](#tab/xmlmanifest) + +## Insert a built-in control group into a custom tab + +To insert a built-in Office control group into a tab, add an [OfficeGroup](/javascript/api/manifest/customtab#officegroup) element as a child element in the parent `<CustomTab>` element. The `id` attribute of the of the `<OfficeGroup>` element is set to the ID of the built-in group. See [Find the IDs of controls and control groups](#find-the-ids-of-controls-and-control-groups). The following markup example adds the Office Paragraph control group to a custom tab and positions it to appear just after a custom group. ```xml -<ExtensionPoint xsi:type="ContosoRibbonTab"> +<ExtensionPoint xsi:type="PrimaryCommandSurface"> <CustomTab id="Contoso.TabCustom1"> <Group id="Contoso.myCustomTab.group1"> - <!-- additional markup omitted --> + <!-- Additional markup omitted. --> </Group> <OfficeGroup id="Paragraph" /> <Label resid="customTabLabel1" /> @@ -37,12 +118,12 @@ The following markup example adds the Office Paragraph control group to a custom ## Insert a built-in control into a custom group -To insert a built-in Office control into a custom group, add an [OfficeControl](/javascript/api/manifest/group#officecontrol) element as a child element in the parent **\<Group\>** element. The `id` attribute of the **\<OfficeControl\>** element is set to the ID of the built-in control. See [Find the IDs of controls and control groups](#find-the-ids-of-controls-and-control-groups). +To insert a built-in Office control into a custom group, add an [OfficeControl](/javascript/api/manifest/group#officecontrol) element as a child element in the parent `<Group>` element. The `id` attribute of the `<OfficeControl>` element is set to the ID of the built-in control. See [Find the IDs of controls and control groups](#find-the-ids-of-controls-and-control-groups). The following markup example adds the Office Superscript control to a custom group and positions it to appear just after a custom button. ```xml -<ExtensionPoint xsi:type="ContosoRibbonTab"> +<ExtensionPoint xsi:type="PrimaryCommandSurface"> <CustomTab id="Contoso.TabCustom2"> <Group id="Contoso.TabCustom2.group1"> <Label resid="residCustomTabGroupLabel"/> @@ -62,6 +143,8 @@ The following markup example adds the Office Superscript control to a custom gro </ExtensionPoint> ``` +--- + > [!NOTE] > Users can customize the ribbon in the Office application. Any user customizations will override your manifest settings. For example, a user can remove a button from any group and remove any group from a tab. @@ -71,4 +154,4 @@ The IDs for supported controls and control groups are in files in the repo [Offi ## Behavior on unsupported platforms -If your add-in is installed on a platform that doesn't support [requirement set AddinCommands 1.3](/javascript/api/requirement-sets/common/add-in-commands-requirement-sets), then the markup described in this article is ignored and the built-in Office controls/groups won't appear in your custom groups/tabs. To prevent your add-in from being installed on platforms that don't support the markup, add a reference to the requirement set in the **\<Requirements\>** section of the manifest. For instructions, see [Specify which Office versions and platforms can host your add-in](../develop/specify-office-hosts-and-api-requirements.md#specify-which-office-versions-and-platforms-can-host-your-add-in). Alternatively, design your add-in to have an experience when **AddinCommands 1.3** isn't supported, as described in [Design for alternate experiences](../develop/specify-office-hosts-and-api-requirements.md#design-for-alternate-experiences). For example, if your add-in contains instructions that assume the built-in buttons are in your custom groups, you could design a version that assumes that the built-in buttons are only in their usual places. +If your add-in is installed on a platform that doesn't support [requirement set AddinCommands 1.3](/javascript/api/requirement-sets/common/add-in-commands-requirement-sets), then the markup described in this article is ignored and the built-in Office controls/groups won't appear in your custom groups/tabs. To prevent your add-in from being installed on platforms that don't support the markup, you must specify **AddinCommands 1.3** in the manifest as a requirement for installation. For instructions, see [Specify which Office versions and platforms can host your add-in](../develop/specify-office-hosts-and-api-requirements.md#specify-which-office-versions-and-platforms-can-host-your-add-in). Alternatively, design your add-in to have an experience when **AddinCommands 1.3** isn't supported, as described in [Design for alternate experiences](../develop/specify-office-hosts-and-api-requirements.md#design-for-alternate-experiences). For example, if your add-in contains instructions that assume the built-in buttons are in your custom groups, you could design a version that assumes that the built-in buttons are only in their usual places. diff --git a/docs/design/content-add-ins.md b/docs/design/content-add-ins.md index 14ba92245d..d57df631f8 100644 --- a/docs/design/content-add-ins.md +++ b/docs/design/content-add-ins.md @@ -1,14 +1,14 @@ --- title: Content Office Add-ins description: Content add-ins are surfaces that can be embedded directly into Excel or PowerPoint documents that give users access to interface controls that run code to modify documents or display data from a data source. -ms.date: 06/27/2024 +ms.date: 09/11/2025 ms.topic: overview ms.localizationpriority: medium --- # Content Office Add-ins -Content add-ins are surfaces that can be embedded directly into Excel or PowerPoint documents. Content add-ins give users access to interface controls that run code to modify documents or display data from a data source. Use content add-ins when you want to embed functionality directly into the document. +Content add-ins are surfaces that can be embedded directly into Excel or PowerPoint documents. Content add-ins give users access to interface controls that run code to modify documents or display data from a data source. Use content add-ins when you want to embed functionality directly into the document. *Figure 1. Typical layout for content add-ins* @@ -41,19 +41,55 @@ For Mac, the personality menu measures 26x26 pixels, but floats 8 pixels in from ## Implementation -There are minor differences in the manifests between content add-ins and add-ins that use task panes. +There are minor differences in the manifests between content add-ins and add-ins that use task panes. Open the tab for the type of manifest you're using. + +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) + +> [!NOTE] +> The unified manifest is available in Excel, PowerPoint, and Word as a developer preview. For Outlook, it's generally available and can be used in production add-ins. + +Configure the manifest with the following steps. + +1. Add a [`"contentRuntimes"`](/microsoft-365/extensibility/schema/element-extensions#contentruntimes) child array to the extension object in the [`"extensions"`](/microsoft-365/extensibility/schema/root#extensions) array. +1. Remove the [`"runtimes"`](/microsoft-365/extensibility/schema/element-extensions#runtimes) property if it is present. The `"runtimes"` array is for task pane or mail add-ins. These cannot be combined with a content add-in. +1. Add an anonymous content runtime object in the `"contentRuntimes"` array. +1. Set the [`"id"`](/microsoft-365/extensibility/schema/extension-content-runtime-array#id) property of the object to a descriptive name. +1. Set the [`"code.page"`](/microsoft-365/extensibility/schema/extension-runtime-code#page) object to the full URL of the custom content that you want to embed in the document. +1. Optionally, set the [`"requestedWidth"`](/microsoft-365/extensibility/schema/extension-content-runtime-array#requestedwidth) and [`"requestedHeight"`](/microsoft-365/extensibility/schema/extension-content-runtime-array#requestedheight) properties to a size between 32 and 1000 pixels. If these properties aren't used, the Office application determines the size. +1. Optionally, set the [`"disableSnapshot"`](/microsoft-365/extensibility/schema/extension-content-runtime-array#disablesnapshot) property to `true` to prevent Office from saving a snapshot of the content component with the document. + +The following is an example of a `"contentRuntimes"` property. + +```json +"contentRuntimes": [ + { + "id": "ContentRuntime", + "code": { + "page": "https://localhost:3000/content.html" + }, + "requestedWidth": 100, + "requestedHeight": 100, + "disableSnapshot": true, + } +] +``` + +# [Add-in only manifest](#tab/xmlmanifest) - For the **\<[OfficeApp](/javascript/api/manifest/officeapp)\>** element, set the `xsi:type` attribute to `"ContentApp"`. - In the **\<[DefaultSettings](/javascript/api/manifest/defaultsettings)\>** element, add the **\<[RequestedHeight](/javascript/api/manifest/requestedheight)\>** and **\<[RequestedWidth](/javascript/api/manifest/requestedwidth)\>** elements. -For a sample that implements a content add-in, see [Excel Content Add-in Humongous Insurance](https://github.com/OfficeDev/Excel-Content-Add-in-Humongous-Insurance) on GitHub. +--- + +For a sample that implements a content add-in, see [Excel content add-in: Humongous Insurance](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-content-add-in) on GitHub. To create your own content add-in, see the [Excel content add-in quick start](../quickstarts/excel-quickstart-content.md) and [PowerPoint content add-in quick start](../quickstarts/powerpoint-quickstart-content.md). ## Support considerations - Check to see if your Office Add-in will work on a [specific Office application or platform](/javascript/api/requirement-sets). -- Some content add-ins may require the user to "trust" the add-in to read and write to Excel or PowerPoint. You can declare what [level of permissions](../develop/requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md) you want your user to have in the add-in's manifest. +- Some content add-ins may require the user to "trust" the add-in to read and write to Excel or PowerPoint. You can declare what [level of permissions](../develop/requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md) you want your user to have in the add-in's manifest. +- In Office on the web, the **Show as saved image** option isn't supported. Even if the **Show as saved image** option was enabled from a desktop client, the content add-in remains interactive on the web client. ## See also diff --git a/docs/design/contextual-tabs.md b/docs/design/contextual-tabs.md index ba89d20276..767f0b0702 100644 --- a/docs/design/contextual-tabs.md +++ b/docs/design/contextual-tabs.md @@ -1,7 +1,7 @@ ---- +--- title: Create custom contextual tabs in Office Add-ins description: Learn how to add custom contextual tabs to your Office Add-in. -ms.date: 08/21/2024 +ms.date: 06/30/2025 ms.topic: how-to ms.localizationpriority: medium --- @@ -11,24 +11,23 @@ ms.localizationpriority: medium A contextual tab is a hidden tab control in the Office ribbon that's displayed in the tab row when a specified event occurs in the Office document. For example, the **Table Design** tab that appears on the Excel ribbon when a table is selected. You include custom contextual tabs in your Office Add-in and specify when they're visible or hidden, by creating event handlers that change the visibility. (However, custom contextual tabs don't respond to focus changes.) > [!NOTE] -> This article assumes that you're familiar with the following documentation. Please review it if you haven't worked with Add-in Commands (custom menu items and ribbon buttons) recently. -> -> - [Basic concepts for Add-in Commands](add-in-commands.md) +> This article assumes that you're familiar with [Basic concepts for add-in commands](add-in-commands.md). Please review it if you haven't worked with add-in commands (custom menu items and ribbon buttons) recently. -> [!IMPORTANT] -> Custom contextual tabs are currently only supported on Excel and only on these platforms and builds. -> -> - Excel on the web -> - Excel on Windows: Version 2102 (Build 13801.20294) or later. -> - Excel on Mac: Version 16.53.806.0 or later. +## Prerequisites -> [!NOTE] -> Custom contextual tabs work only on platforms that support the following requirement sets. For more about requirement sets and how to work with them, see [Specify Office applications and API requirements](../develop/specify-office-hosts-and-api-requirements.md). -> -> - [RibbonApi 1.2](/javascript/api/requirement-sets/common/ribbon-api-requirement-sets) -> - [SharedRuntime 1.1](/javascript/api/requirement-sets/common/shared-runtime-requirement-sets) -> -> You can use the runtime checks in your code to test whether the user's host and platform combination supports these requirement sets as described in [Runtime checks for method and requirement set support](../develop/specify-office-hosts-and-api-requirements.md#runtime-checks-for-method-and-requirement-set-support). (The technique of specifying the requirement sets in the manifest, which is also described in that article, does not currently work for RibbonApi 1.2.) Alternatively, you can [implement an alternate UI experience when custom contextual tabs are not supported](#implement-an-alternate-ui-experience-when-custom-contextual-tabs-arent-supported). +Custom contextual tabs are currently only supported on **Excel** and only on the following platforms and builds. + +- Excel on the web +- Excel on Windows: Version 2102 (Build 13801.20294) and later. +- Excel on Mac: Version 16.53 (21080600) and later. + +Additionally, custom contextual tabs only work on platforms that support the following requirement sets. For more about requirement sets and how to work with them, see [Specify Office applications and API requirements](../develop/specify-office-hosts-and-api-requirements.md). + +- [RibbonApi 1.2](/javascript/api/requirement-sets/common/ribbon-api-requirement-sets) +- [SharedRuntime 1.1](/javascript/api/requirement-sets/common/shared-runtime-requirement-sets) + +> [!TIP] +> Use the runtime checks in your code to test whether the user's host and platform combination supports these requirement sets as described in [Check for API availability at runtime](../develop/specify-api-requirements-runtime.md). (The technique of specifying the requirement sets in the manifest, which is also described in that article, doesn't currently work for RibbonApi 1.2.) Alternatively, you can [implement an alternate UI experience when custom contextual tabs aren't supported](#implement-an-alternate-ui-experience-when-custom-contextual-tabs-arent-supported). ## Behavior of custom contextual tabs @@ -40,32 +39,117 @@ The user experience for custom contextual tabs follows the pattern of built-in O - If more than one add-in has a contextual tab that's visible in a specific context, then they appear in the order in which the add-ins were launched. - Custom *contextual* tabs, unlike custom core tabs, aren't added permanently to the Office application's ribbon. They're present only in Office documents on which your add-in is running. -> [!WARNING] -> Currently, the use of custom contextual tabs may prevent the user from undoing their previous Excel actions. This is a known issue (see [this GitHub thread](https://github.com/OfficeDev/office-js/issues/4814)) and under active investigation. - ## Major steps for including a contextual tab in an add-in The following are the major steps for including a custom contextual tab in an add-in. -1. Configure the add-in to use a shared runtime. -1. Define the tab and the groups and controls that appear on it. -1. Register the contextual tab with Office. -1. Specify the circumstances when the tab will be visible. +1. [Configure the add-in to use a shared runtime](#configure-the-add-in-to-use-a-shared-runtime). +1. [Specify the icons for your contextual tab](#specify-the-icons-for-your-contextual-tab). +1. [Define the groups and controls that appear on the tab](#define-the-groups-and-controls-that-appear-on-the-tab). +1. [Register the contextual tab with Office](#register-the-contextual-tab-with-office-with-requestcreatecontrols). +1. [Specify the circumstances when the tab will be visible](#specify-the-contexts-when-the-tab-will-be-visible-with-requestupdate). ## Configure the add-in to use a shared runtime Adding custom contextual tabs requires your add-in to use the [shared runtime](../testing/runtimes.md#shared-runtime). For more information, see [Configure an add-in to use a shared runtime](../develop/configure-your-add-in-to-use-a-shared-runtime.md). -## Define the groups and controls that appear on the tab +## Specify the icons for your contextual tab -Unlike custom core tabs, which are defined with XML in the manifest, custom contextual tabs are defined at runtime with a JSON blob. Your code parses the blob into a JavaScript object, and then passes the object to the [Office.ribbon.requestCreateControls](/javascript/api/office/office.ribbon?view=common-js&preserve-view=true#office-office-ribbon-requestcreatecontrols-member(1)) method. Custom contextual tabs are only present in documents on which your add-in is currently running. This is different from custom core tabs which are added to the Office application ribbon when the add-in is installed and remain present when another document is opened. Also, the `requestCreateControls` method may be run only once in a session of your add-in. If it's called again, an error is thrown. +Before you can customize your contextual tab, you must first specify any icons that will appear on it in your add-in's manifest. Each icon must have at least three sizes: 16x16 px, 32x32 px, and 80x80 px. Select the tab for the type of manifest your add-in uses. -> [!NOTE] -> The structure of the JSON blob's properties and subproperties (and the key names) is roughly parallel to the structure of the [CustomTab](/javascript/api/manifest/customtab) element and its descendant elements in the manifest XML. +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) + +In the [`"extensions.ribbons.tabs.groups.icons"`](/microsoft-365/extensibility/schema/extension-ribbons-custom-tab-groups-item#icons) array, specify the icons for the group of contextual tab controls that will be displayed on the host's ribbon. For icons that will be used by the tab's buttons and menus, specify these in the `"icons"` property of the [`"extensions.ribbons.tabs.groups.controls"`](/microsoft-365/extensibility/schema/extension-ribbons-custom-tab-groups-item#controls) object. + +Because the contextual tab will only be shown when a certain event occurs, you must also set the [`"extensions.ribbons.tabs.groups.controls.overriddenByRibbonApi"`](/microsoft-365/extensibility/schema/extension-common-custom-group-controls-item#overriddenbyribbonapi) property to `true`. + +The following is an example. + +```json +"ribbons": [ + { + ... + "tabs": [ + "groups": [ + { + "id": "ContosoGroup", + ... + "icons": [ + { + "size": 16, + "url": "https://cdn.contoso.com/addins/datainsertion/Images/Group16x16.png" + }, + { + "size": 32, + "url": "https://cdn.contoso.com/addins/datainsertion/Images/Group32x32.png" + }, + { + "size": 80, + "url": "https://cdn.contoso.com/addins/datainsertion/Images/Group80x80.png" + } + ], + "controls": [ + { + "id": "WriteDataButton", + ... + "icons": [ + { + "size": 16, + "url": "https://cdn.contoso.com/addins/datainsertion/Images/WriteDataButton16x16.png" + }, + { + "size": 32, + "url": "https://cdn.contoso.com/addins/datainsertion/Images/WriteDataButton16x16.png" + }, + { + "size": 80, + "url": "https://cdn.contoso.com/addins/datainsertion/Images/WriteDataButton16x16.png" + } + ], + ... + "overriddenByRibbonApi": true + }, + ... + ] + } + ] + ] + } +], +``` + +# [Add-in only manifest](#tab/xmlmanifest) + +Use the [Image](/javascript/api/manifest/image) element in the [Resources](/javascript/api/manifest/resources) section of your add-in's manifest to specify the icons for your contextual tab. + +The following is an example. + +```xml +<Resources> + <bt:Images> + <bt:Image id="contextual-tab-icon-16" DefaultValue="https://cdn.contoso.com/addins/datainsertion/Images/Group16x16.png"/> + <bt:Image id="contextual-tab-icon-32" DefaultValue="https://cdn.contoso.com/addins/datainsertion/Images/Group32x32.png"/> + <bt:Image id="contextual-tab-icon-80" DefaultValue="https://cdn.contoso.com/addins/datainsertion/Images/Group80x80.png"/> + <bt:Image id="contextual-button-icon-16" DefaultValue="https://cdn.contoso.com/addins/datainsertion/Images/WriteDataButton16x16.png"/> + <bt:Image id="contextual-button-icon-32" DefaultValue="https://cdn.contoso.com/addins/datainsertion/Images/WriteDataButton32x32.png"/> + <bt:Image id="contextual-button-icon-80" DefaultValue="https://cdn.contoso.com/addins/datainsertion/Images/WriteDataButton80x80.png"/> + </bt:Images> + ... +</Resources> +``` + +--- + +> [!IMPORTANT] +> When you move your add-in from development to staging or production, remember to update the URLs in your manifest as needed (such as changing the domain from `localhost` to `contoso.com`). + +## Define the groups and controls that appear on the tab + +Unlike custom core tabs, which are defined in the manifest, custom contextual tabs are defined at runtime with a JSON blob. Your code parses the blob into a JavaScript object, and then passes the object to the [Office.ribbon.requestCreateControls](/javascript/api/office/office.ribbon?view=common-js&preserve-view=true#office-office-ribbon-requestcreatecontrols-member(1)) method. Custom contextual tabs are only present in documents on which your add-in is currently running. This is different from custom core tabs which are added to the Office application ribbon when the add-in is installed and remain present when another document is opened. Also, the `requestCreateControls` method may be run only once in a session of your add-in. If it's called again, an error is thrown. We'll construct an example of a contextual tabs JSON blob step-by-step. The full schema for the contextual tab JSON is at [dynamic-ribbon.schema.json](https://developer.microsoft.com/json-schemas/office-js/dynamic-ribbon.schema.json). If you're working in Visual Studio Code, you can use this file to get IntelliSense and to validate your JSON. For more information, see [Editing JSON with Visual Studio Code - JSON schemas and settings](https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings). -1. Begin by creating a JSON string with two array properties named `actions` and `tabs`. The `actions` array is a specification of all the functions that can be executed by controls on the contextual tab. The `tabs` array defines one or more contextual tabs, *up to a maximum of 20*. +1. Begin by creating a JSON string with two array properties named `actions` and `tabs`. The `actions` array is a specification of all the functions that can be executed by controls on the contextual tab. The `tabs` array defines one or more contextual tabs. ```json '{ @@ -81,8 +165,8 @@ We'll construct an example of a contextual tabs JSON blob step-by-step. The full 1. This simple example of a contextual tab will have only a single button and, thus, only a single action. Add the following as the only member of the `actions` array. About this markup, note: - The `id` and `type` properties are mandatory. - - The value of `type` can be either "ExecuteFunction" or "ShowTaskpane". - - The `functionName` property is only used when the value of `type` is `ExecuteFunction`. It's the name of a function defined in the FunctionFile. For more information about the FunctionFile, see [Basic concepts for Add-in Commands](add-in-commands.md). + - The value of `type` can be either `"ExecuteFunction"` or `"ShowTaskpane"`. + - The `functionName` property is only used when the value of `type` is `ExecuteFunction`. It's the name of a function defined in the FunctionFile. For more information about the FunctionFile, see [Basic concepts for add-in commands](add-in-commands.md). - In a later step, you'll map this action to a button on the contextual tab. ```json @@ -97,7 +181,7 @@ We'll construct an example of a contextual tabs JSON blob step-by-step. The full - The `id` property is required. Use a brief, descriptive ID that is unique among all contextual tabs in your add-in. - The `label` property is required. It's a user-friendly string to serve as the label of the contextual tab. - - The `groups` property is required. It defines the groups of controls that will appear on the tab. It must have at least one member *and no more than 20*. (There are also limits on the number of controls that you can have on a custom contextual tab and that will also constrain how many groups that you have. See the next step for more information.) + - The `groups` property is required. It defines the groups of controls that will appear on the tab. It must have at least one member. > [!NOTE] > The tab object can also have an optional `visible` property that specifies whether the tab is visible immediately when the add-in starts up. Since contextual tabs are normally hidden until a user event triggers their visibility (such as the user selecting an entity of some type in the document), the `visible` property defaults to `false` when not present. In a later section, we show how to set the property to `true` in response to an event. @@ -120,9 +204,6 @@ We'll construct an example of a contextual tabs JSON blob step-by-step. The full - The `icon` property's value is an array of objects that specify the icons that the group will have on the ribbon depending on the size of the ribbon and the Office application window. - The `controls` property's value is an array of objects that specify the buttons and menus in the group. There must be at least one. - > [!IMPORTANT] - > *The total number of controls on the whole tab can be no more than 20.* For example, you could have 3 groups with 6 controls each, and a fourth group with 2 controls, but you can't have 4 groups with 6 controls each. - ```json { "id": "CustomGroup111", @@ -136,16 +217,20 @@ We'll construct an example of a contextual tabs JSON blob step-by-step. The full } ``` -1. Every group must have an icon of at least two sizes, 32x32 px and 80x80 px. Optionally, you can also have icons of sizes 16x16 px, 20x20 px, 24x24 px, 40x40 px, 48x48 px, and 64x64 px. Office decides which icon to use based on the size of the ribbon and Office application window. Add the following objects to the icon array. (If the window and ribbon sizes are large enough for at least one of the *controls* on the group to appear, then no group icon at all appears. For an example, watch the **Styles** group on the Word ribbon as you shrink and expand the Word window.) About this markup, note: +1. Every group must have an icon of at least three sizes: 16x16 px, 32x32 px, and 80x80 px. Optionally, you can also have icons of sizes 20x20 px, 24x24 px, 40x40 px, 48x48 px, and 64x64 px. Office decides which icon to use based on the size of the ribbon and Office application window. Add the following objects to the icon array. (If the window and ribbon sizes are large enough for at least one of the *controls* on the group to appear, then no group icon at all appears. For an example, watch the **Styles** group on the Word ribbon as you shrink and expand the Word window.) About this markup, note: - Both the properties are required. - The `size` property unit of measure is pixels. Icons are always square, so the number is both the height and the width. - - The `sourceLocation` property specifies the full URL to the icon. + - The `sourceLocation` property specifies the full URL to the icon. Its value must match the URL specified in the `<Image>` element of the `<Resources>` section of your manifest (see [Specify the icons for your contextual tab](#specify-the-icons-for-your-contextual-tab)). > [!IMPORTANT] - > Just as you typically must change the URLs in the add-in's manifest when you move from development to production (such as changing the domain from localhost to contoso.com), you must also change the URLs in your contextual tabs JSON. + > Just as you typically must change the URLs in the add-in's manifest when you move from development to production, you must also change the URLs in your contextual tabs JSON. ```json + { + "size": 16, + "sourceLocation": "https://cdn.contoso.com/addins/datainsertion/Images/Group16x16.png" + }, { "size": 32, "sourceLocation": "https://cdn.contoso.com/addins/datainsertion/Images/Group32x32.png" @@ -159,7 +244,7 @@ We'll construct an example of a contextual tabs JSON blob step-by-step. The full 1. In our simple ongoing example, the group has only a single button. Add the following object as the only member of the `controls` array. About this markup, note: - All the properties, except `enabled`, are required. - - `type` specifies the type of control. The values can be "Button", "Menu", or "MobileButton". + - `type` specifies the type of control. The values can be `"Button"`, `"Menu"`, or `"MobileButton"`. - `id` can be up to 125 characters. - `actionId` must be the ID of an action defined in the `actions` array. (See step 1 of this section.) - `label` is a user-friendly string to serve as the label of the button. @@ -179,6 +264,10 @@ We'll construct an example of a contextual tabs JSON blob step-by-step. The full "description": "Use this button to insert data into the document." }, "icon": [ + { + "size": 16, + "sourceLocation": "https://cdn.contoso.com/addins/datainsertion/Images/WriteDataButton16x16.png" + }, { "size": 32, "sourceLocation": "https://cdn.contoso.com/addins/datainsertion/Images/WriteDataButton32x32.png" @@ -211,6 +300,10 @@ The following is the complete example of the JSON blob. "id": "CustomGroup111", "label": "Insertion", "icon": [ + { + "size": 16, + "sourceLocation": "https://cdn.contoso.com/addins/datainsertion/Images/Group16x16.png" + }, { "size": 32, "sourceLocation": "https://cdn.contoso.com/addins/datainsertion/Images/Group32x32.png" @@ -232,6 +325,10 @@ The following is the complete example of the JSON blob. "description": "Use this button to insert data into the document." }, "icon": [ + { + "size": 16, + "sourceLocation": "https://cdn.contoso.com/addins/datainsertion/Images/WriteDataButton16x16.png" + }, { "size": 32, "sourceLocation": "https://cdn.contoso.com/addins/datainsertion/Images/WriteDataButton32x32.png" @@ -322,7 +419,7 @@ const showDataTab = async () => { ### Toggle tab visibility and the enabled status of a button at the same time -The `requestUpdate` method is also used to toggle the enabled or disabled status of a custom button on either a custom contextual tab or a custom core tab. For details about this, see [Enable and Disable Add-in Commands](disable-add-in-commands.md). There may be scenarios in which you want to change both the visibility of a tab and the enabled status of a button at the same time. You do this with a single call of `requestUpdate`. The following is an example in which a button on a core tab is enabled at the same time as a contextual tab is made visible. +The `requestUpdate` method is also used to toggle the enabled or disabled status of a custom button on either a custom contextual tab or a custom core tab. For details about this, see [Change the availability of add-in commands](disable-add-in-commands.md). There may be scenarios in which you want to change both the visibility of a tab and the enabled status of a button at the same time. You do this with a single call of `requestUpdate`. The following is an example in which a button on a core tab is enabled at the same time as a contextual tab is made visible. ```javascript function myContextChanges() { @@ -379,7 +476,7 @@ function myContextChanges() { ## Open a task pane from contextual tabs -To open your task pane from a button on a custom contextual tab, create an action in the JSON with a `type` of `ShowTaskpane`. Then define a button with the `actionId` property set to the `id` of the action. This opens the default task pane specified by the **\<Runtime\>** element in your manifest. +To open your task pane from a button on a custom contextual tab, create an action in the JSON with a `type` of `ShowTaskpane`. Then define a button with the `actionId` property set to the `id` of the action. This opens the default task pane specified in your manifest. ```json `{ @@ -529,9 +626,101 @@ Some combinations of platform, Office application, and Office build don't suppor #### Use noncontextual tabs or controls -There's a manifest element, [OverriddenByRibbonApi](/javascript/api/manifest/overriddenbyribbonapi), that's designed to create a fallback experience in an add-in that implements custom contextual tabs when the add-in is running on an application or platform that doesn't support custom contextual tabs. +The add-in's manifest provides a way to create a fallback experience in an add-in that implements custom contextual tabs when the add-in is running on an application or platform that doesn't support custom contextual tabs. The strategy is to define a custom core tab (that is, *noncontextual* custom tab) in the manifest that duplicates the ribbon customizations of the custom contextual tabs in your add-in. Then you use special manifest markup to enable the custom core tab to be visible all the time on platform and version combinations that don't support custom contextual tabs. The process depends on which type of manifest your add-in uses. + +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) + +[!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] -The simplest strategy for using this element is to define a custom core tab (that is, *noncontextual* custom tab) in the manifest that duplicates the ribbon customizations of the custom contextual tabs in your add-in. But you add `<OverriddenByRibbonApi>true</OverriddenByRibbonApi>` as the first child element of the duplicate [Group](/javascript/api/manifest/group), [Control](/javascript/api/manifest/control), and menu **\<Item\>** elements on the custom core tabs. The effect of doing so is the following: +Begin by defining a custom core tab (that is, *noncontextual* custom tab) in the manifest that duplicates the ribbon customizations of the custom contextual tabs in your add-in. Then, mark any control groups, or individual controls, or menu items that shouldn't be visible on platforms that support contextual tabs. You mark a group, control, or menu item object by adding an `"overriddenByRibbonApi"` property to it and setting its value to `true`. The effect of doing so is the following: + +- If the add-in runs on an application and platform that support custom contextual tabs, then the marked custom groups, controls, and menu items won't appear on the ribbon. Instead, the custom contextual tab will be created when the add-in calls the `requestCreateControls` method. +- If the add-in runs on an application or platform that *doesn't* support `requestCreateControls`, then the groups, controls, and menu items do appear on the custom core tab. + +The following is an example. Note that "Contoso.MyButton1" will appear on the custom core tab only when custom contextual tabs aren't supported. However, the parent group (with "ContosoButton2") and the custom core tab will appear regardless of whether custom contextual tabs are supported. + +```json +"extensions": [ + ... + { + ... + "ribbons": [ + ... + { + ... + "tabs": [ + { + "id": "MyTab", + "groups": [ + { + ... + "controls": [ + { + "id": "Contoso.MyButton1", + ... + "overriddenByRibbonApi": true + }, + { + "id": "Contoso.MyButton2", + ... + } + ] + } + ] + } + ] + } + ] + } +] +``` + +The following is another example. Note that "MyControlGroup" will appear on the custom core tab only when custom contextual tabs aren't supported. However, the parent custom core tab (with unmarked groups) will appear regardless of whether custom contextual tabs are supported. + +```json +"extensions": [ + ... + { + ... + "ribbons": [ + ... + { + ... + "tabs": [ + { + "id": "MyTab", + "groups": [ + { + "id": "MyControlGroup", + "overriddenByRibbonApi": true + ... + "controls": [ + { + "id": "Contoso.MyButton1", + ... + } + ] + }, + ... other groups configured here + ] + } + ] + } + ] + } +] +``` + +When a parent menu control is marked with `"overriddenByRibbonApi": true`, then it isn't visible, and all of its child markup is ignored when custom contextual tabs aren't supported. So, it doesn't matter if any of those child menu items have the `"overriddenByRibbonApi"` property or what its value is. The implication of this is that if a menu item must be visible in all contexts, then not only should it not be marked with `"overriddenByRibbonApi": true`, but *its ancestor menu control must also not be marked this way*. A similar point applies to ribbon controls. If a control must be visible in all contexts, then not only should it not be marked with `"overriddenByRibbonApi": true`, but its parent group must also not be marked this way. + +> [!IMPORTANT] +> Don't mark *all* of the child items of a menu with `"overriddenByRibbonApi": true`. This is pointless if the parent element is marked with `"overriddenByRibbonApi": true` for reasons given in the preceding paragraph. Moreover, if you leave out the `"overriddenByRibbonApi"` property on the parent menu control (or set it to `false`), then the parent will appear regardless of whether custom contextual tabs are supported, but it will be empty when they are supported. So, if all the child elements shouldn't appear when custom contextual tabs are supported, mark the *parent* menu control with `"overriddenByRibbonApi": true`. +> +> A parallel point applies to groups and controls, don't mark all of the controls in a group with `"overriddenByRibbonApi": true`. This is pointless if the parent group is marked with `"overriddenByRibbonApi": true`. Moreover, if you leave out the `"overriddenByRibbonApi"` property on the parent group (or set it to `false`), then the group will appear regardless of whether custom contextual tabs are supported, but it will have no controls in it when they are supported. So, if all the controls shouldn't appear when custom contextual tabs are supported, mark the parent group with `"overriddenByRibbonApi": true`. + +# [Add-in only manifest](#tab/xmlmanifest) + +Begin by defining a custom core tab (that is, *noncontextual* custom tab) in the manifest that duplicates the ribbon customizations of the custom contextual tabs in your add-in. But add an [OverriddenByRibbonApi](/javascript/api/manifest/overriddenbyribbonapi) element as the first child element of the duplicate [Group](/javascript/api/manifest/group), [Control](/javascript/api/manifest/control), and menu `<Item>` elements on the custom core tabs. The effect of doing so is the following: - If the add-in runs on an application and platform that support custom contextual tabs, then the custom core groups and controls won't appear on the ribbon. Instead, the custom contextual tab will be created when the add-in calls the `requestCreateControls` method. - If the add-in runs on an application or platform that *doesn't* support `requestCreateControls`, then the elements do appear on the custom core tab. @@ -562,14 +751,16 @@ The following is an example. Note that "MyButton" will appear on the custom core For more examples, see [OverriddenByRibbonApi](/javascript/api/manifest/overriddenbyribbonapi). -When a parent group, or menu is marked with `<OverriddenByRibbonApi>true</OverriddenByRibbonApi>`, then it isn't visible, and all of its child markup is ignored when custom contextual tabs aren't supported. So, it doesn't matter if any of those child elements have the **\<OverriddenByRibbonApi\>** element or what its value is. The implication of this is that if a menu item or control must be visible in all contexts, then not only should it not be marked with `<OverriddenByRibbonApi>true</OverriddenByRibbonApi>`, but *its ancestor menu and group must also not be marked this way*. +When a parent group, or menu is marked with `<OverriddenByRibbonApi>true</OverriddenByRibbonApi>`, then it isn't visible, and all of its child markup is ignored when custom contextual tabs aren't supported. So, it doesn't matter if any of those child elements have the `<OverriddenByRibbonApi>` element or what its value is. The implication of this is that if a menu item or control must be visible in all contexts, then not only should it not be marked with `<OverriddenByRibbonApi>true</OverriddenByRibbonApi>`, but *its ancestor menu and group must also not be marked this way*. > [!IMPORTANT] -> Don't mark *all* of the child elements of a group or menu with `<OverriddenByRibbonApi>true</OverriddenByRibbonApi>`. This is pointless if the parent element is marked with `<OverriddenByRibbonApi>true</OverriddenByRibbonApi>` for reasons given in the preceding paragraph. Moreover, if you leave out the **\<OverriddenByRibbonApi\>** on the parent (or set it to `false`), then the parent will appear regardless of whether custom contextual tabs are supported, but it will be empty when they are supported. So, if all the child elements shouldn't appear when custom contextual tabs are supported, mark the parent with `<OverriddenByRibbonApi>true</OverriddenByRibbonApi>`. +> Don't mark *all* of the child elements of a group or menu with `<OverriddenByRibbonApi>true</OverriddenByRibbonApi>`. This is pointless if the parent element is marked with `<OverriddenByRibbonApi>true</OverriddenByRibbonApi>` for reasons given in the preceding paragraph. Moreover, if you leave out the `<OverriddenByRibbonApi>` on the parent (or set it to `false`), then the parent will appear regardless of whether custom contextual tabs are supported, but it will be empty when they are supported. So, if all the child elements shouldn't appear when custom contextual tabs are supported, mark the parent with `<OverriddenByRibbonApi>true</OverriddenByRibbonApi>`. + +--- #### Use APIs that show or hide a task pane in specified contexts -As an alternative to **\<OverriddenByRibbonApi\>**, your add-in can define a task pane with UI controls that duplicate the functionality of the controls on a custom contextual tab. Then use the [Office.addin.showAsTaskpane](/javascript/api/office/office.addin?view=common-js&preserve-view=true#office-office-addin-showastaskpane-member(1)) and [Office.addin.hide](/javascript/api/office/office.addin?view=common-js&preserve-view=true#office-office-addin-hide-member(1)) methods to show the task pane when the contextual tab would have been shown if it was supported. For details on how to use these methods, see [Show or hide the task pane of your Office Add-in](../develop/show-hide-add-in.md). +As an alternative to using the manifest, your add-in can define a task pane with UI controls that duplicate the functionality of the controls on a custom contextual tab. Then use the [Office.addin.showAsTaskpane](/javascript/api/office/office.addin?view=common-js&preserve-view=true#office-office-addin-showastaskpane-member(1)) and [Office.addin.hide](/javascript/api/office/office.addin?view=common-js&preserve-view=true#office-office-addin-hide-member(1)) methods to show the task pane when the contextual tab would have been shown if it was supported. For details on how to use these methods, see [Show or hide the task pane of your Office Add-in](../develop/show-hide-add-in.md). ### Handle the HostRestartNeeded error diff --git a/docs/design/custom-tab-placement.md b/docs/design/custom-tab-placement.md index f89df6f357..3f299e6758 100644 --- a/docs/design/custom-tab-placement.md +++ b/docs/design/custom-tab-placement.md @@ -1,7 +1,7 @@ ---- +--- title: Position a custom tab on the ribbon description: Learn how to control where a custom tab appears on the Office ribbon and whether it has focus by default. -ms.date: 08/18/2023 +ms.date: 02/12/2025 ms-topic: how-to ms.localizationpriority: medium --- @@ -19,9 +19,46 @@ You can specify where you want your add-in's custom tab to appear on the Office > - The add-in feature and markup described in this article is *only available in PowerPoint on the web*. > - The markup described in this article only works on platforms that support requirement set **AddinCommands 1.3**. See [Behavior on unsupported platforms](#behavior-on-unsupported-platforms) below. -Specify where you want a custom tab to appear by identifying which built-in Office tab you want it to be next to and specifying whether it should be on the left or right side of the built-in tab. Make these specifications by including either an [InsertBefore](/javascript/api/manifest/customtab#insertbefore) (left) or an [InsertAfter](/javascript/api/manifest/customtab#insertafter) (right) element in the [CustomTab](/javascript/api/manifest/customtab) element of your add-in's manifest. (You cannot have both elements.) +By default, a custom tab is added to the end of the ribbon. However, you can specify where you want a custom tab to appear by identifying which built-in Office tab you want it to be next to and specifying whether it should be on the left or right side of the built-in tab. Open the tab for the type of manifest your add-in uses for the details of the manifest markup. + +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) + +[!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] -In the following example, the custom tab is configured to appear *just after* the **Review** tab. Note that the value of the **\<InsertAfter\>** element is the ID of the built-in Office tab. +To position your custom tab, include a [`"position"`](/microsoft-365/extensibility/schema/extension-ribbons-array-tabs-item-position) property in the [`"extensions.ribbons.tabs"`](/microsoft-365/extensibility/schema/extension-ribbons-array#tabs) object. Set the `"position.builtInTabId"` property to the ID of the built-in tab that you want your custom tab to be next to. (See [Find the IDs of built-in Office ribbon tabs](../develop/built-in-ui-ids.md).) Set the `"position.align"` property to either `"before"` (left) or `"after"` (right). + +In the following example, the custom tab is configured to appear *just after* the **Review** tab. + +```json +"extensions": [ + ... + { + ... + "ribbons": [ + ... + { + ... + "tabs": [ + { + "id": "MyTab", + ... + "position": { + "builtInTabId": "TabReview", + "align": "after" + } + } + ] + } + ] + } +] +``` + +# [Add-in only manifest](#tab/xmlmanifest) + +To position your custom tab, include either an [InsertBefore](/javascript/api/manifest/customtab#insertbefore) (left) or an [InsertAfter](/javascript/api/manifest/customtab#insertafter) (right) element in the [CustomTab](/javascript/api/manifest/customtab) element of your add-in's manifest. (You cannot have both elements.) + +In the following example, the custom tab is configured to appear *just after* the **Review** tab. Note that the value of the `<InsertAfter>` element is the ID of the built-in Office tab. See [Find the IDs of built-in Office ribbon tabs](../develop/built-in-ui-ids.md). ```xml <ExtensionPoint xsi:type="ContosoRibbonTab"> @@ -35,21 +72,21 @@ In the following example, the custom tab is configured to appear *just after* th </ExtensionPoint> ``` -Keep the following points in mind. +--- + +## How user actions can affect custom tab positioning -- The **\<InsertBefore\>** and **\<InsertAfter\>** elements are optional. If you use neither, then your custom tab will appear as the rightmost tab on the ribbon. -- The **\<InsertBefore\>** and **\<InsertAfter\>** elements are mutually exclusive. You can't use both. - If the user installs more than one add-in whose custom tab is configured for the same place, say after the **Review** tab, then the tab for the most recently installed add-in will be located in that place. The tabs of the previously installed add-ins will be moved over one place. For example, the user installs add-ins A, B, and C in that order and all are configured to insert a tab after the **Review** tab, then the tabs will appear in this order: **Review**, **AddinCTab**, **AddinBTab**, **AddinATab**. - Users can customize the ribbon in the Office application. For example, a user can move or hide your add-in's tab. You cannot prevent this or detect that it has happened. -- If a user moves one of the built-in tabs, then Office interprets the **\<InsertBefore\>** and **\<InsertAfter\>** elements in terms of *the default location of the built-in tab*. For example, if the user moves the **Review** tab to the right end of the ribbon, Office will interpret the markup in the previous example as meaning "put the custom tab just to the right of *where the **Review** tab would be by default*." +- If a user moves one of the built-in tabs, then Office interprets the positioning markup in the manifest in terms of *the default location of the built-in tab*. For example, if the user moves the **Review** tab to the right end of the ribbon, Office will interpret the markup in the previous example as meaning "put the custom tab just to the right of *where the **Review** tab would be by default*." ## Specify which tab has focus when the document opens -Office always gives default focus to the tab that's immediately to the right of the **File** tab. By default this is the **Home** tab. If you configure your custom tab to be before the **Home** tab, with `<InsertBefore>TabHome</InsertBefore>`, then your custom tab will have focus when the document opens. +Office always gives default focus to the tab that's immediately to the right of the **File** tab. By default this is the **Home** tab. If you configure your custom tab to be before the **Home** tab, then your custom tab will have focus when the document opens. > [!IMPORTANT] > Giving excessive prominence to your add-in inconveniences and annoys users and administrators. Don't position a custom tab before the **Home** tab unless your add-in is the primary way users will interact with the document. ## Behavior on unsupported platforms -If your add-in is installed on a platform that doesn't support [requirement set AddinCommands 1.3](/javascript/api/requirement-sets/common/add-in-commands-requirement-sets), then the markup described in this article is ignored and your custom tab will appear as the rightmost tab on the ribbon. To prevent your add-in from being installed on platforms that don't support the markup, add a reference to the requirement set in the **\<Requirements\>** section of the manifest. For instructions, see [Specify which Office versions and platforms can host your add-in](../develop/specify-office-hosts-and-api-requirements.md#specify-which-office-versions-and-platforms-can-host-your-add-in). Alternatively, design your add-in to have an alternate experience when **AddinCommands 1.3** isn't supported, as described in [Design for alternate experiences](../develop/specify-office-hosts-and-api-requirements.md#design-for-alternate-experiences). For example, if your add-in contains instructions that assume the custom tab is where you want it, you could have an alternate version that assumes the tab is the rightmost. +If your add-in is installed on a platform that doesn't support [requirement set AddinCommands 1.3](/javascript/api/requirement-sets/common/add-in-commands-requirement-sets), then the markup described in this article is ignored and your custom tab will appear as the rightmost tab on the ribbon. To prevent your add-in from being installed on platforms that don't support the markup, you must specify **AddinCommands 1.3** in the manifest as a requirement for installation. For instructions, see [Specify which Office versions and platforms can host your add-in](../develop/specify-office-hosts-and-api-requirements.md#specify-which-office-versions-and-platforms-can-host-your-add-in). Alternatively, design your add-in to have an alternate experience when **AddinCommands 1.3** isn't supported, as described in [Design for alternate experiences](../develop/specify-office-hosts-and-api-requirements.md#design-for-alternate-experiences). For example, if your add-in contains instructions that assume the custom tab is where you want it, you could have an alternate version that assumes the tab is the rightmost. diff --git a/docs/design/data-visualization-guidelines.md b/docs/design/data-visualization-guidelines.md index a79ed3de77..857ecd656b 100644 --- a/docs/design/data-visualization-guidelines.md +++ b/docs/design/data-visualization-guidelines.md @@ -1,7 +1,7 @@ --- title: Data visualization style guidelines for Office Add-ins description: Get some good practices for how to visualize data in an Office Add-in. -ms.date: 06/27/2023 +ms.date: 10/29/2025 ms.topic: best-practice ms.localizationpriority: medium --- diff --git a/docs/design/design-toolkits.md b/docs/design/design-toolkits.md deleted file mode 100644 index 7d042b07bc..0000000000 --- a/docs/design/design-toolkits.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Design toolkits for Office Add-ins -description: Get links to some tools to help design the UI of an Office Add-in. -ms.date: 06/23/2023 -ms.localizationpriority: medium ---- - -# Design toolkits - -To help you get started, we've created toolkits for use with either the [Sketch](https://www.sketch.com/) application for Mac or the [Adobe XD](https://www.adobe.com/products/xd/features.html) application for Windows or Mac. The following downloads include all of our available patterns, along with brief descriptions and layout recommendations. - -## Downloads - -* [Fluent UI Design Sketch Toolkit](https://aka.ms/fabric-sketch-toolkit) -* [Fluent UI Design Adobe XD Toolkit](https://aka.ms/fabric-toolkit) -* [Add-in Sketch Toolkit](https://aka.ms/addins_sketch_toolkit) -* [Add-in Adobe XD Toolkit](https://aka.ms/addins_toolkit) -* [Segoe UI and Fabric MDL2 icon font](https://static2.sharepointonline.com/files/fabric/fabric-website/files/segoeui_fabricmdl2_icon_fonts.zip) diff --git a/docs/design/disable-add-in-commands.md b/docs/design/disable-add-in-commands.md index 60008ce1a9..7dcec67d55 100644 --- a/docs/design/disable-add-in-commands.md +++ b/docs/design/disable-add-in-commands.md @@ -1,39 +1,99 @@ ---- +--- title: Enable and Disable Add-in Commands description: Learn how to change the enabled or disabled status of custom ribbon buttons and menu items in your Office Web Add-in. -ms.date: 08/05/2024 +ms.date: 03/11/2025 ms.topic: how-to ms.localizationpriority: medium --- -# Enable and Disable Add-in Commands +# Change the availability of add-in commands + +When some functionality in your add-in should only be available in certain contexts, you can programmatically configure your custom add-in commands to only be available in these contexts. For example, a function that changes the header of a table should only be available when the cursor is in a table. + +> [!NOTE] +> +> - This article assumes that you're familiar with the [basic concepts for add-in commands](add-in-commands.md). Please review it if you haven't worked with add-in commands (custom menu items and ribbon buttons) recently. + +## Supported capabilities + +You can programmatically change the availability of an add-in command for the following capabilities. + +- Ribbon buttons, menus, and tabs. +- Context menu items. + +## Office application and requirement set support + +The following table outlines the Office applications that support configuring the availability of add-in commands. It also lists the requirement sets needed to use the API. + +| Add-in command capability | Requirement set | Supported Office applications | +| ---- | ---- | ---- | +| Ribbon buttons, menus, and tabs | [RibbonApi 1.1](/javascript/api/requirement-sets/common/ribbon-api-requirement-sets) | <ul><li>Excel</li><li>PowerPoint</li><li>Word</li></ul> | +| Context menu items | [ContextMenuApi 1.1](/javascript/api/requirement-sets/common/context-menu-api-requirement-sets) | <ul><li>Excel</li><li>PowerPoint</li><li>Word</li></ul> | + +> [!TIP] +> To learn how to test for platform support with requirement sets, see [Office versions and requirement sets](../develop/office-versions-and-requirement-sets.md). + +## Configure a shared runtime + +To change the availability of a ribbon or context menu control or item, the manifest of your add-in must first be configured to use a [shared runtime](../testing/runtimes.md#shared-runtime). For guidance on how to set up a shared runtime, see [Configure your Office Add-in to use a shared runtime](../develop/configure-your-add-in-to-use-a-shared-runtime.md). -When some functionality in your add-in should only be available in certain contexts, you can programmatically enable or disable your custom Add-in Commands. For example, a function that changes the header of a table should only be enabled when the cursor is in a table. +## Programmatically change the availability of an add-in command -You can also specify whether the command is enabled or disabled when the Office client application opens. +# [Ribbon](#tab/ribbon) + +### Deactivate ribbon controls at launch > [!NOTE] -> This article assumes that you're familiar with the [basic concepts for Add-in Commands](add-in-commands.md). Please review it if you haven't worked with Add-in Commands (custom menu items and ribbon buttons) recently. +> Only the controls on the ribbon can be deactivated when the Office application starts. You can't deactivate custom controls added to a context menu at launch. + +By default, a custom button or menu item on the ribbon is available for use when the Office application launches. To deactivate it when Office starts, you must specify this in the manifest. The process depends on which type of manifest your add-in uses. -## Office application and platform support +- [Unified manifest for Microsoft 365](#unified-manifest-for-microsoft-365) +- [Add-in only manifest](#add-in-only-manifest) -The APIs described in this article are available in **Excel**, **PowerPoint**, and **Word** as part of the [RibbonApi 1.1](/javascript/api/requirement-sets/common/ribbon-api-requirement-sets) requirement set. To learn how to test for platform support with requirement sets, see [Office versions and requirement sets](../develop/office-versions-and-requirement-sets.md). +#### Unified manifest for Microsoft 365 -## Shared runtime required +[!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] -The APIs and manifest markup described in this article require that the add-in's manifest specify that it should use a [shared runtime](../testing/runtimes.md#shared-runtime). To do this, take the following steps. +Just add an [`"enabled"`](/microsoft-365/extensibility/schema/extension-common-custom-group-controls-item#enabled) property with the value `false` to the control or menu item object. The following shows the basic structure. -1. In the [Runtimes](/javascript/api/manifest/runtimes) element in the manifest, add the following child element: `<Runtime resid="Contoso.SharedRuntime.Url" lifetime="long" />`. (If there isn't already a **\<Runtimes\>** element in the manifest, create it as the first child under the **\<Host\>** element in the **\<VersionOverrides\>** section.) -1. In the [Resources.Urls](/javascript/api/manifest/resources) section of the manifest, add the following child element: `<bt:Url id="Contoso.SharedRuntime.Url" DefaultValue="https://{mydomain}/%7Bpath-to-start-page%7D" />`, where `{MyDomain}` is the domain of the add-in and `{path-to-start-page}` is the path for the start page of the add-in; for example: `<bt:Url id="Contoso.SharedRuntime.Url" DefaultValue="https://localhost:3000/index.html" />`. -1. Depending on whether your add-in contains a task pane, a function file, or an Excel custom function, you must do one or more of the following three steps. +```json +"extensions": [ + ... + { + ... + "ribbons": [ + ... + { + ... + "tabs": [ + { + "id": "MyTab", + "groups": [ + { + ... + "controls": [ + { + "id": "Contoso.MyButton1", + ... + "enabled": false + } + ] + } + ] + } + ] + } + ] + } +] +``` - - If the add-in contains a task pane, set the `resid` attribute of the [Action](/javascript/api/manifest/action).[SourceLocation](/javascript/api/manifest/sourcelocation) element to exactly the same string as you used for the `resid` of the **\<Runtime\>** element in step 1; for example, `Contoso.SharedRuntime.Url`. The element should look like this: `<SourceLocation resid="Contoso.SharedRuntime.Url"/>`. - - If the add-in contains an Excel custom function, set the `resid` attribute of the [Page](/javascript/api/manifest/page).[SourceLocation](/javascript/api/manifest/sourcelocation) element exactly the same string as you used for the `resid` of the **\<Runtime\>** element in step 1; for example, `Contoso.SharedRuntime.Url`. The element should look like this: `<SourceLocation resid="Contoso.SharedRuntime.Url"/>`. - - If the add-in contains a function file, set the `resid` attribute of the [FunctionFile](/javascript/api/manifest/functionfile) element to exactly the same string as you used for the `resid` of the **\<Runtime\>** element in step 1; for example, `Contoso.SharedRuntime.Url`. The element should look like this: `<FunctionFile resid="Contoso.SharedRuntime.Url"/>`. +#### Add-in only manifest -## Set the default state to disabled +Just add an [Enabled](/javascript/api/manifest/enabled) element immediately *below* (not inside) the [Action](/javascript/api/manifest/action) element of the control item. Then, set its value to `false`. -By default, any Add-in Command is enabled when the Office application launches. If you want a custom button or menu item to be disabled when the Office application launches, you specify this in the manifest. Just add an [Enabled](/javascript/api/manifest/enabled) element (with the value `false`) immediately *below* (not inside) the [Action](/javascript/api/manifest/action) element in the declaration of the control. The following shows the basic structure. +The following shows the basic structure of a manifest that configures the `<Enabled>` element. ```xml <OfficeApp ...> @@ -57,27 +117,29 @@ By default, any Add-in Command is enabled when the Office application launches. </OfficeApp> ``` -## Change the state programmatically +### Change the availability of a ribbon control -The essential steps to changing the enabled status of an Add-in Command are: +To update the availability of a button or menu item on the ribbon, perform the following steps. -1. Create a [RibbonUpdaterData](/javascript/api/office/office.ribbonupdaterdata) object that (1) specifies the command, and its parent group and tab, by their IDs as declared in the manifest; and (2) specifies the enabled or disabled state of the command. +1. Create a [RibbonUpdaterData](/javascript/api/office/office.ribbonupdaterdata) object that specifies the following: + - The IDs of the command, including its parent group and tab. The IDs must match those declared in the manifest. + - The availability status of the command. 1. Pass the **RibbonUpdaterData** object to the [Office.ribbon.requestUpdate()](/javascript/api/office/office.ribbon?view=common-js&preserve-view=true#office-office-ribbon-requestupdate-member(1)) method. The following is a simple example. Note that "MyButton", "OfficeAddinTab1", and "CustomGroup111" are copied from the manifest. ```javascript function enableButton() { - Office.ribbon.requestUpdate({ + const ribbonUpdaterData = { tabs: [ { - id: "OfficeAppTab1", + id: "OfficeAppTab1", groups: [ { id: "CustomGroup111", controls: [ { - id: "MyButton", + id: "MyButton", enabled: true } ] @@ -85,96 +147,141 @@ function enableButton() { ] } ] - }); + }; + + Office.ribbon.requestUpdate(ribbonUpdaterData); } ``` -We also provide several interfaces (types) to make it easier to construct the **RibbonUpdateData** object. The following is the equivalent example in TypeScript and it makes use of these types. +There are several interfaces (types) to make it easier to construct the **RibbonUpdateData** object. + +- [Office.Control](/javascript/api/office/office.control) +- [Office.Group](/javascript/api/office/office.group) +- [Office.Tab](/javascript/api/office/office.tab) + +The following is the equivalent example in TypeScript and it makes use of these types. ```typescript const enableButton = async () => { - const button: Control = {id: "MyButton", enabled: true}; - const parentGroup: Group = {id: "CustomGroup111", controls: [button]}; - const parentTab: Tab = {id: "OfficeAddinTab1", groups: [parentGroup]}; - const ribbonUpdater: RibbonUpdaterData = { tabs: [parentTab]}; + const button: Control = { id: "MyButton", enabled: true }; + const parentGroup: Group = { id: "CustomGroup111", controls: [button] }; + const parentTab: Tab = { id: "OfficeAddinTab1", groups: [parentGroup] }; + const ribbonUpdater: RibbonUpdaterData = { tabs: [parentTab] }; Office.ribbon.requestUpdate(ribbonUpdater); } ``` -You can `await` the call of **requestUpdate()** if the parent function is asynchronous, but note that the Office application controls when it updates the state of the ribbon. The **requestUpdate()** method queues a request to update. The method will resolve the promise object as soon as it has queued the request, not when the ribbon actually updates. +> [!TIP] +> You can `await` the call of **requestUpdate()** if the parent function is asynchronous, but note that the Office application controls when it updates the state of the ribbon. The **requestUpdate()** method queues a request to update. The method will resolve the promise object as soon as it has queued the request, not when the ribbon actually updates. -## Change the state in response to an event +### Toggle tab visibility and the enabled status of a button at the same time + +The **requestUpdate** method is also used to toggle the visibility of a custom contextual tab. For details about this and example code, see [Create custom contextual tabs in Office Add-ins](contextual-tabs.md#toggle-tab-visibility-and-the-enabled-status-of-a-button-at-the-same-time). + +# [Context menu](#tab/context-menu) -A common scenario in which the ribbon state should change is when a user-initiated event changes the add-in context. +To programmatically change the availability of a custom item on a context menu, perform the following steps. -Consider a scenario in which a button should be enabled when, and only when, a chart is activated. The first step is to set the [Enabled](/javascript/api/manifest/enabled) element for the button in the manifest to `false`. See above for an example. +1. Create a [ContextMenuUpdaterData](/javascript/api/office/office.contextmenuupdaterdata) object. This object defines the context menu controls you want to update. It specifies the following: + - The ID of each context menu item you want to update. The ID must match that specified in the manifest. + - The availability status of the control. +1. Send your request to update the context menu by passing the **ContextMenuUpdaterData** object to [Office.contextMenu.requestUpdate](/javascript/api/office/office.contextmenu#office-office-contextmenu-requestupdate-member(1)). -Second, assign handlers. This is commonly done in the **Office.onReady** function as in the following example which assigns handlers (created in a later step) to the **onActivated** and **onDeactivated** events of all the charts in the worksheet. + > [!IMPORTANT] + > The Office application controls when it updates the state of the context menu. The **requestUpdate()** method queues an update request and resolves the promise object as soon as it queues the request, not when the ribbon actually updates. + +The following is an example of how to change the availability of custom buttons on a context menu by configuring the `enabled` property of each button. ```javascript -Office.onReady(async () => { -    await Excel.run(context => { -        const charts = context.workbook.worksheets -            .getActiveWorksheet() -            .charts; -        charts.onActivated.add(enableChartFormat); -        charts.onDeactivated.add(disableChartFormat); -        return context.sync(); -    }); +await Office.contextMenu.requestUpdate({ + controls: [ + { + id: Addin.CtxMenu.Button1, + enabled: true + }, + { + id: Addin.CtxMenu.Button2, + enabled: false + }, + ] }); ``` -Third, define the `enableChartFormat` handler. The following is a simple example, but see [Best practice: Test for control status errors](#best-practice-test-for-control-status-errors) below for a more robust way of changing a control's status. +--- -```javascript -function enableChartFormat() { - const button = { - id: "ChartFormatButton", - enabled: true - }; - const parentGroup = { - id: "MyGroup", - controls: [button] - }; - const parentTab = { - id: "CustomChartTab", - groups: [parentGroup] - }; - const ribbonUpdater = {tabs: [parentTab]}; - Office.ribbon.requestUpdate(ribbonUpdater); -} -``` +## Change the state in response to an event -Fourth, define the `disableChartFormat` handler. It would be identical to `enableChartFormat` except that the **enabled** property of the button object would be set to `false`. +A common scenario in which the state of a ribbon or context menu control should change is when a user-initiated event changes the add-in context. Consider a scenario in which a button should be available when, and only when, a chart is activated. Although the following example uses ribbon controls, a similar implementation can be applied to custom items on a context menu. + +1. First, set the `<Enabled>` element for the button in the manifest to `false`. For guidance on how to configure this, see [Deactivate ribbon controls at launch](#deactivate-ribbon-controls-at-launch). +1. Then, assign handlers. This is commonly done in the **Office.onReady** function as in the following example. In the example, handlers (created in a later step) are assigned to the **onActivated** and **onDeactivated** events of all the charts in an Excel worksheet. + + ```javascript + Office.onReady(async () => { +     await Excel.run((context) => { +         const charts = context.workbook.worksheets +             .getActiveWorksheet() +             .charts; +         charts.onActivated.add(enableChartFormat); +         charts.onDeactivated.add(disableChartFormat); +         return context.sync(); +     }); + }); + ``` -### Toggle tab visibility and the enabled status of a button at the same time +1. Define the `enableChartFormat` handler. The following is a simple example. For a more robust way of changing a control's status, see [Best practice: Test for control status errors](#best-practice-test-for-control-status-errors). -The **requestUpdate** method is also used to toggle the visibility of a custom contextual tab. For details about this and example code, see [Create custom contextual tabs in Office Add-ins](contextual-tabs.md#toggle-tab-visibility-and-the-enabled-status-of-a-button-at-the-same-time). + ```javascript + function enableChartFormat() { + const button = + { + id: "ChartFormatButton", + enabled: true + }; + const parentGroup = + { + id: "MyGroup", + controls: [button] + }; + const parentTab = + { + id: "CustomChartTab", + groups: [parentGroup] + }; + const ribbonUpdater = { tabs: [parentTab] }; + Office.ribbon.requestUpdate(ribbonUpdater); + } + ``` + +1. Define the `disableChartFormat` handler. It's identical to the `enableChartFormat` handler, except that the **enabled** property of the button object is set to `false`. ## Best practice: Test for control status errors -In some circumstances, the ribbon does not repaint after `requestUpdate` is called, so the control's clickable status does not change. For this reason it is a best practice for the add-in to keep track of the status of its controls. The add-in should conform to the following rules. +In some circumstances, the ribbon or context menu doesn't repaint after `requestUpdate` is called, so the control's clickable status doesn't change. For this reason it's a best practice for the add-in to keep track of the status of its controls. The add-in should conform to the following rules. -1. Whenever `requestUpdate` is called, the code should record the intended state of the custom buttons and menu items. -1. When a custom control is clicked, the first code in the handler, should check to see if the button should have been clickable. If shouldn't have been, the code should report or log an error and try again to set the buttons to the intended state. +- Whenever `requestUpdate` is called, the code should record the intended state of the custom buttons and menu items. +- When a custom control is selected, the first code in the handler should check to see if the button should have been available. If it shouldn't have been available, the code should report or log an error and try again to set the buttons to the intended state. -The following example shows a function that disables a button and records the button's status. Note that `chartFormatButtonEnabled` is a global boolean variable that is initialized to the same value as the [Enabled](/javascript/api/manifest/enabled) element for the button in the manifest. +The following example shows a function that deactivates a button on the ribbon and records the button's status. In this example, `chartFormatButtonEnabled` is a global boolean variable that's initialized to the same value as the [Enabled](/javascript/api/manifest/enabled) element for the button in the add-in's manifest. Although the example uses a ribbon button, a similar implementation can be applied to custom items on a context menu. ```javascript function disableChartFormat() { - const button = { - id: "ChartFormatButton", - enabled: false - }; - const parentGroup = { - id: "MyGroup", - controls: [button] - }; - const parentTab = { - id: "CustomChartTab", - groups: [parentGroup] - }; - const ribbonUpdater = {tabs: [parentTab]}; + const button = + { + id: "ChartFormatButton", + enabled: false + }; + const parentGroup = + { + id: "MyGroup", + controls: [button] + }; + const parentTab = + { + id: "CustomChartTab", + groups: [parentGroup] + }; + const ribbonUpdater = { tabs: [parentTab] }; Office.ribbon.requestUpdate(ribbonUpdater); chartFormatButtonEnabled = false; @@ -187,10 +294,10 @@ The following example shows how the button's handler tests for an incorrect stat function chartFormatButtonHandler() { if (chartFormatButtonEnabled) { - // Do work here + // Do work here. } else { - // Report the error and try again to disable. + // Report the error and try to make the button unavailable again. reportError("That action is not possible at this time."); disableChartFormat(); } @@ -199,24 +306,27 @@ function chartFormatButtonHandler() { ## Error handling -In some scenarios, Office is unable to update the ribbon and will return an error. For example, if the add-in is upgraded and the upgraded add-in has a different set of custom add-in commands, then the Office application must be closed and reopened. Until it is, the `requestUpdate` method will return the error `HostRestartNeeded`. The following is an example of how to handle this error. In this case, the `reportError` method displays the error to the user. +In some scenarios, Office is unable to update the ribbon or context menu and will return an error. For example, if the add-in is upgraded and the upgraded add-in has a different set of custom add-in commands, then the Office application must be closed and reopened. Until it is, the `requestUpdate` method will return the error `HostRestartNeeded`. The following is an example of how to handle this error. In this case, the `reportError` method displays the error to the user. Although the example uses a ribbon button, a similar implementation can be applied to custom items on a context menu. ```javascript function disableChartFormat() { try { - const button = { - id: "ChartFormatButton", - enabled: false - }; - const parentGroup = { - id: "MyGroup", - controls: [button] - }; - const parentTab = { - id: "CustomChartTab", - groups: [parentGroup] - }; - const ribbonUpdater = {tabs: [parentTab]}; + const button = + { + id: "ChartFormatButton", + enabled: false + }; + const parentGroup = + { + id: "MyGroup", + controls: [button] + }; + const parentTab = + { + id: "CustomChartTab", + groups: [parentGroup] + }; + const ribbonUpdater = { tabs: [parentTab] }; Office.ribbon.requestUpdate(ribbonUpdater); chartFormatButtonEnabled = false; @@ -228,3 +338,9 @@ function disableChartFormat() { } } ``` + +## See also + +- [Add-in commands](add-in-commands.md) +- [Create add-in commands with the add-in only manifest](../develop/create-addin-commands.md) +- [Create custom contextual tabs in Office Add-ins](contextual-tabs.md) diff --git a/docs/design/fabric-core.md b/docs/design/fabric-core.md index b0640376ab..376efa7662 100644 --- a/docs/design/fabric-core.md +++ b/docs/design/fabric-core.md @@ -22,7 +22,7 @@ If your add-in's UI isn't React-based, you can also make use of a set of non-Rea 1. Add the content delivery network (CDN) reference to the HTML on your page. ```html - <link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/9.6.1/css/fabric.min.css"> + <link rel="stylesheet" href="https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/office-ui-fabric-core/11.0.0/css/fabric.min.css"> ``` 2. Use Fabric Core icons and fonts. @@ -52,7 +52,6 @@ The following sample add-ins use Fabric Core and/or Office UI Fabric JS componen - [Excel Add-in JavaScript SalesTracker](https://github.com/OfficeDev/Excel-Add-in-JavaScript-SalesTracker) - [Excel Add-in SalesLeads](https://github.com/OfficeDev/Excel-Add-in-SalesLeads) - [Excel Add-in WoodGrove Expense Trends](https://github.com/OfficeDev/Excel-Add-in-WoodGrove-Expense-Trends) -- [Excel Content Add-in Humongous Insurance](https://github.com/OfficeDev/Excel-Content-Add-in-Humongous-Insurance) - [Office Add-in Fabric UI Sample](https://github.com/OfficeDev/Office-Add-in-Fabric-UI-Sample) - [Office-Add-in-UX-Design-Patterns-Code](https://github.com/OfficeDev/Office-Add-in-UX-Design-Patterns-Code) - [Outlook Add-in GifMe](https://github.com/OfficeDev/Outlook-Add-in-GifMe) diff --git a/docs/design/first-run-experience-patterns.md b/docs/design/first-run-experience-patterns.md index 57b72c3d6b..3273e5270c 100755 --- a/docs/design/first-run-experience-patterns.md +++ b/docs/design/first-run-experience-patterns.md @@ -1,24 +1,50 @@ --- title: First-run experience patterns for Office Add-ins description: Learn the best practices for designing first-run experiences in Office Add-ins. -ms.date: 08/09/2024 +ms.date: 08/12/2025 ms.topic: best-practice ms.localizationpriority: medium --- # First-run experience patterns -A first-run experience (FRE) is a user's introduction to your add-in. An FRE is presented when a user opens an add-in for the first time and provides them with insight into the functions, features, and/or benefits of the add-in. This experience helps shape the user's impression of an add-in and can strongly influence their likelihood to come back to and continue using your add-in. +A well-designed first-run experience (FRE) introduces users to your Office Add-in. It guides them through its core features and benefits. An effective FRE not only helps users get started quickly but also increases engagement and retention by making a positive first impression. + +## Why first-run experiences matter + +The initial moments with your add-in set the tone for future interactions. A clear, concise FRE can: + +- Highlight your add-in's unique value. +- Reduce user confusion and support requests. +- Encourage users to take meaningful actions. +- Foster ongoing usage and loyalty. + +## Key principles for first-run experiences + +- **Keep it simple**: Focus on the essential actions and benefits. Avoid overwhelming users with too much information. +- **Be actionable**: Provide clear next steps or calls to action that help users realize immediate value. +- **Offer flexibility**: Allow users to skip or revisit the FRE as needed. +- **Engage visually**: Use graphics, carousels, or videos to make the experience memorable and easy to follow. + +## FRE patterns for Office Add-ins + +Explore these proven patterns to design an effective first-run experience: + +- [Carousel](#carousel): Guide users through a sequence of screens highlighting features and benefits, with options to advance or skip. +- [Value placemat](#value-placemat): Present your add-in’s value proposition, logo, feature summary, and a call-to-action in a single, visually engaging layout. +- [Video placemat](#video-placemat): Use a short video to demonstrate your add-in’s capabilities, paired with a clear call-to-action. + +Choose the pattern that best fits your add-in's complexity and user needs. Consider showing the FRE periodically if your add-in is used infrequently, to help users stay familiar with its features. ## Best practices Follow these best practices when crafting your first-run experience. -|Do|Don't| +| Do | Don't | |:------|:------| -|Provide a simple and brief introduction to the main actions in the add-in. | Don't include information and call-outs that aren't relevant to getting started. | -|Give users the opportunity to complete an action that will positively impact their use of the add-in. | Don't expect users to learn everything at once. Focus on the action that provides the most value. | -|Create an engaging experience that users will want to complete. | Don't force the users to click through the first-run experience. Give users an option to bypass the first-run experience. | +| Provide a simple and brief introduction to the main actions in the add-in. | Don't include information and call-outs that aren't relevant to getting started. | +| Give users the opportunity to complete an action that will positively impact their use of the add-in. | Don't expect users to learn everything at once. Focus on the action that provides the most value. | +| Create an engaging experience that users will want to complete. | Don't force the users to click through the first-run experience. Give users an option to bypass the first-run experience. | Consider whether showing users the first-run experience once or periodically is important to your scenario. For example, if your add-in is only utilized periodically, users may become less familiar with your add-in and may benefit from another interaction with the first-run experience. @@ -50,7 +76,7 @@ The value placemat communicates your add-in's value proposition through logo pla For an example that uses the value placemat pattern, see the [first-run experience tutorial](../tutorials/first-run-experience-tutorial.md). -### Video placemat +## Video placemat The video placemat shows users a video before they start using your add-in. diff --git a/docs/design/interface-elements.md b/docs/design/interface-elements.md index 4696bac9dc..a7c964309c 100644 --- a/docs/design/interface-elements.md +++ b/docs/design/interface-elements.md @@ -1,7 +1,7 @@ --- title: Office UI elements for Office Add-ins description: Get an overview of the different kinds of UI elements in an Office Add-in. -ms.date: 08/18/2023 +ms.date: 03/11/2025 ms.topic: overview ms.localizationpriority: medium --- @@ -22,7 +22,7 @@ Use [add-in commands](add-in-commands.md) to add entry points to your add-in to |Command type|Description| |:-----------|:----------| |Ribbon buttons, menus, and tabs|Use to add custom buttons, menus (dropdowns), or tabs to the default ribbon in Office. Use buttons and menus to trigger an action in Office. Use tabs to group and organize buttons and menus.| -|Context menus| Use to extend the default context menu. Context menus are displayed when, for example, users right-click text in an Office document or a table in Excel.| +|Context menus| Use to extend the default context menu. Context menus are displayed when, for example, users right-click (or select and hold) text in an Office document or an object in Excel.| ## HTML containers diff --git a/docs/design/keyboard-shortcuts.md b/docs/design/keyboard-shortcuts.md index 1ae8bb4894..060934361a 100644 --- a/docs/design/keyboard-shortcuts.md +++ b/docs/design/keyboard-shortcuts.md @@ -1,314 +1,494 @@ ---- +--- title: Custom keyboard shortcuts in Office Add-ins description: Learn how to add custom keyboard shortcuts, also known as key combinations, to your Office Add-in. -ms.date: 06/28/2024 +ms.date: 09/23/2025 ms.topic: how-to ms.localizationpriority: medium --- # Add custom keyboard shortcuts to your Office Add-ins -Keyboard shortcuts, also known as key combinations, enable your add-in's users to work more efficiently. Keyboard shortcuts also improve the add-in's accessibility for users with disabilities by providing an alternative to the mouse. +Keyboard shortcuts, also known as key combinations, make it possible for your add-in's users to work more efficiently. Keyboard shortcuts also improve the add-in's accessibility for users with disabilities by providing an alternative to the mouse. + +There are three steps to add keyboard shortcuts to an add-in. + +1. [Configure the add-in's manifest to use a shared runtime](#define-custom-keyboard-shortcuts). +1. [Define custom keyboard shortcuts](#define-custom-keyboard-shortcuts) and the actions they'll run. +1. [Map custom actions to their functions](#map-custom-actions-to-their-functions) using the [Office.actions.associate](/javascript/api/office/office.actions#office-office-actions-associate-member) API. + +## Prerequisites + +Keyboard shortcuts are currently only supported in the following platforms and build of **Excel** and **Word**. + +- Office on the web +- Office on Windows + - **Excel**: Version 2102 (Build 13801.20632) and later + - **Word**: Version 2408 (Build 17928.20114) and later +- Office on Mac + - **Excel**: Version 16.55 (21111400) and later + - **Word**: Version 16.88 (24081116) and later + +Additionally, keyboard shortcuts only work on platforms that support the following requirement sets. For information about requirement sets and how to work with them, see [Specify Office applications and API requirements](../develop/specify-office-hosts-and-api-requirements.md). + +- [SharedRuntime 1.1](/javascript/api/requirement-sets/common/shared-runtime-requirement-sets) +- [KeyboardShortcuts 1.1](/javascript/api/requirement-sets/common/keyboard-shortcuts-requirement-sets) (required if the add-in provides its users with the option to customize keyboard shortcuts) -[!include[Keyboard shortcut prerequisites](../includes/keyboard-shortcuts-prerequisites.md)] +> [!TIP] +> To start with a working version of an add-in with keyboard shortcuts already configured, clone and run the [Use keyboard shortcuts for Office Add-in actions](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/office-keyboard-shortcuts) sample. When you're ready to add keyboard shortcuts to your own add-in, continue with this article. + +## Define custom keyboard shortcuts + +The process to define custom keyboard shortcuts for your add-in varies depending on the type of manifest your add-in uses. Select the tab for the type of manifest you're using. + +> [!TIP] +> To learn more about manifests for Office Add-ins, see [Office Add-ins manifest](../develop/add-in-manifests.md). + +# [Unified app manifest for Microsoft 365](#tab/jsonmanifest) > [!NOTE] -> To start with a working version of an add-in with keyboard shortcuts already enabled, clone and run the sample [Excel Keyboard Shortcuts](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-keyboard-shortcuts). When you're ready to add keyboard shortcuts to your own add-in, continue with this article. +> Implementing keyboard shortcuts with the unified app manifest for Microsoft 365 is in public developer preview. This shouldn't be used in production add-ins. We invite you to try it out in test or development environments. For more information, see the [Microsoft 365 app manifest schema reference](/microsoft-365/extensibility/schema/?view=m365-app-prev&preserve-view=true). -There are three steps to add keyboard shortcuts to an add-in. +If your add-in uses the unified app manifest for Microsoft 365, custom keyboard shortcuts and their actions are defined in the manifest. -1. [Configure the add-in's manifest](#configure-the-manifest). -1. [Create or edit the shortcuts JSON file](#create-or-edit-the-shortcuts-json-file) to define actions and their keyboard shortcuts. -1. [Add one or more runtime calls](#create-a-mapping-of-actions-to-their-functions) of the [Office.actions.associate](/javascript/api/office/office.actions#office-office-actions-associate-member(1)) API to map a function to each action. +1. In your add-in project, open the **manifest.json** file. +1. Add the following object to the [`"extensions.runtimes"`](/microsoft-365/extensibility/schema/extension-runtimes-array?view=m365-app-prev&preserve-view=true) array. Note the following about this markup. + - The [`"actions"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item?view=m365-app-prev&preserve-view=true) objects specify the functions your add-in can run. In the following example, an add-in will be able to show and hide a task pane. You'll create these functions in a later section. Currently, custom keyboard shortcuts can only run actions that are of type `"executeFunction"`. + - While the [`"actions.displayName"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item?view=m365-app-prev&preserve-view=true#displayname) property is optional, it's required if a custom keyboard shortcut will be created for the action. This property is used to describe the action of a keyboard shortcut. The description you provide appears in the dialog that's shown to a user when there's a shortcut conflict between multiple add-ins or with Microsoft 365. Office appends the name of the add-in in parentheses at the end of the description. For more information on how conflicts with keyboard shortcuts are handled, see [Avoid key combinations in use by other add-ins](#avoid-key-combinations-in-use-by-other-add-ins). -## Configure the manifest + ```json + { + "id": "TaskPaneRuntime", + "type": "general", + "code": { + "page": "https://localhost:3000/taskpane.html" + }, + "lifetime": "long", + "actions": [ + { + "id": "ShowTaskpane", + "type": "executeFunction", + "displayName": "Show task pane" + }, + { + "id": "HideTaskpane", + "type": "executeFunction", + "displayName": "Hide task pane" + } + ] + } + ``` -There are two small changes to make to the manifest. One is to enable the add-in to use a shared runtime and the other is to point to a JSON-formatted file where you defined the keyboard shortcuts. +1. Add the following to the [`"extensions"`](/microsoft-365/extensibility/schema/root#extensions) array. Note the following about the markup. + - The SharedRuntime 1.1 requirement set is specified in the [`"requirements.capabilities"`](/microsoft-365/extensibility/schema/requirements-extension-element-capabilities?view=m365-app-prev&preserve-view=true) object to support custom keyboard shortcuts. + - Each [`"shortcuts"`](/microsoft-365/extensibility/schema/extension-shortcut) object represents a single action that's invoked by a keyboard shortcut. It specifies the supported key combinations for various platforms, such as Office on the web, on Windows, and on Mac. For guidance on how to create custom key combinations, see [Guidelines for custom key combinations](#guidelines-for-custom-key-combinations). + - A default key combination must be specified. It's used on all supported platforms if there isn't a specific combination configured for a particular platform. + - The value of the `"actionId"` property must match the value specified in the `"id"` property of the applicable `"extensions.runtimes.actions"` object. -### Configure the add-in to use a shared runtime + ```json + "keyboardShortcuts": [ + { + "requirements": { + "capabilities": [ + { + "name": "SharedRuntime", + "minVersion": "1.1" + } + ] + }, + "shortcuts": [ + { + "key": { + "default": "Ctrl+Alt+Up", + "mac": "Command+Shift+Up", + "web": "Ctrl+Alt+1", + "windows": "Ctrl+Alt+Up" + }, + "actionId": "ShowTaskpane" + }, + { + "key": { + "default": "Ctrl+Alt+Down", + "mac": "Command+Shift+Down", + "web": "Ctrl+Alt+2", + "windows": "Ctrl+Alt+Down" + }, + "actionId": "HideTaskpane" + } + ] + } + ] + ``` -Adding custom keyboard shortcuts requires your add-in to use the [shared runtime](../testing/runtimes.md#shared-runtime). For more information, see [Configure an add-in to use a shared runtime](../develop/configure-your-add-in-to-use-a-shared-runtime.md). +> [!NOTE] +> If you've defined keyboard shortcuts for an add-in that uses the unified manifest and want to publish it to [Microsoft Marketplace](../publish/publish-office-add-ins-to-appsource.md), you must specify JSON resource files for the custom shortcuts and their localized strings (if applicable) in the manifest. These resource files are used for backward compatibility on platforms that don't directly support the unified manifest. To learn how to configure this in your manifest, see [Support backward compatibility for add-ins with a unified manifest in Microsoft Marketplace](#support-backward-compatibility-for-add-ins-with-a-unified-manifest-in-microsoft-marketplace). -### Link the mapping file to the manifest +# [Add-in only manifest](#tab/xmlmanifest) -Immediately *below* (not inside) the **\<VersionOverrides\>** element in the manifest, add an [ExtendedOverrides](/javascript/api/manifest/extendedoverrides) element. Set the `Url` attribute to the full URL of a JSON file in your project that you'll create in a later step. +### Configure the manifest to use a shared runtime -```xml - ... - </VersionOverrides> - <ExtendedOverrides Url="https://contoso.com/addin/shortcuts.json"></ExtendedOverrides> -</OfficeApp> -``` +To customize keyboard shortcuts for your add-in, you must first configure the add-in manifest to use a [shared runtime](../testing/runtimes.md#shared-runtime). For guidance on how to configure your add-in to use a shared runtime, see [Configure an add-in to use a shared runtime](../develop/configure-your-add-in-to-use-a-shared-runtime.md). -## Create or edit the shortcuts JSON file +### Create or edit the shortcuts JSON file -Create a JSON file in your project. Be sure the path of the file matches the location you specified for the `Url` attribute of the [ExtendedOverrides](/javascript/api/manifest/extendedoverrides) element. This file will describe your keyboard shortcuts, and the actions that they will invoke. +If your add-in uses an add-in only manifest, custom keyboard shortcuts are defined in a JSON file. This file describes your keyboard shortcuts and the actions that they'll invoke. The complete schema for the JSON file is at [extended-manifest.schema.json](https://developer.microsoft.com/json-schemas/office-js/extended-manifest.schema.json). -1. Inside the JSON file, there are two arrays. The actions array will contain objects that define the actions to be invoked and the shortcuts array will contain objects that map key combinations onto actions. Here is an example. +1. In your add-in project, create a JSON file. +1. Add the following markup to the file. Note the following about the code. + - The `"actions"` array contains objects that define the actions to be invoked. The [`"actions.id"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item#id) and `"actions.name"` properties are required. + - The `"actions.id"` property uniquely identifies the action to invoke using a keyboard shortcut. + - The `"actions.name"` property must describe the action of a keyboard shortcut. The description you provide appears in the dialog that's shown to a user when there's a shortcut conflict between multiple add-ins or with Microsoft 365. Office appends the name of the add-in in parentheses at the end of the description. For more information on how conflicts with keyboard shortcuts are handled, see [Avoid key combinations in use by other add-ins](#avoid-key-combinations-in-use-by-other-add-ins). + - The `"type"` property is optional. Currently, only the `"ExecuteFunction"` type is supported. + - The specified actions will be mapped to functions that you create in a later step. In the example, you'll later map `"ShowTaskpane"` to a function that calls the `Office.addin.showAsTaskpane` method and `"HideTaskpane"` to a function that calls the `Office.addin.hide` method. + - The `"shortcuts"` array contains objects that map key combinations to actions. The `"shortcuts.action"`, `"shortcuts.key"`, and `"shortcuts.key.default"` properties are required. + - The value of the `"shortcuts.action"` property must match the `"actions.id"` property of the applicable action object. + - It's possible to customize shortcuts to be platform-specific. In the example, the `"shortcuts"` object customizes shortcuts for each of the following platforms: `"windows"`, `"mac"`, and `"web"`. You must define a default shortcut key for each shortcut. This is used as a fallback key if a key combination isn't specified for a particular platform. + + > [!TIP] + > For guidance on how to create custom key combinations, see [Guidelines for custom key combinations](#guidelines-for-custom-key-combinations). ```json { "actions": [ { - "id": "SHOWTASKPANE", + "id": "ShowTaskpane", "type": "ExecuteFunction", - "name": "Show task pane for add-in" + "name": "Show task pane" }, { - "id": "HIDETASKPANE", + "id": "HideTaskpane", "type": "ExecuteFunction", - "name": "Hide task pane for add-in" + "name": "Hide task pane" } ], "shortcuts": [ { - "action": "SHOWTASKPANE", + "action": "ShowTaskpane", "key": { - "default": "Ctrl+Alt+Up" + "default": "Ctrl+Alt+Up", + "mac": "Command+Shift+Up", + "web": "Ctrl+Alt+1", + "windows": "Ctrl+Alt+Up" } }, { - "action": "HIDETASKPANE", + "action": "HideTaskpane", "key": { - "default": "Ctrl+Alt+Down" + "default": "Ctrl+Alt+Down", + "mac": "Command+Shift+Down", + "web": "Ctrl+Alt+2", + "windows": "Ctrl+Alt+Up" } } ] } ``` - For more information about the JSON objects, see [Construct the action objects](#construct-the-action-objects) and [Construct the shortcut objects](#construct-the-shortcut-objects). The complete schema for the shortcuts JSON is at [extended-manifest.schema.json](https://developer.microsoft.com/json-schemas/office-js/extended-manifest.schema.json). +### Link the mapping file to the manifest + +1. In your add-in project, open the **manifest.xml** file. +1. Immediately *below* (not inside) the `<VersionOverrides>` element in the manifest, add an [ExtendedOverrides](/javascript/api/manifest/extendedoverrides) element. Set the `Url` attribute to the full URL of the JSON file you created in a previous step. - > [!NOTE] - > You can use "CONTROL" in place of "Ctrl" throughout this article. +```xml + ... + </VersionOverrides> + <ExtendedOverrides Url="https://contoso.com/addin/shortcuts.json"></ExtendedOverrides> +</OfficeApp> +``` - The actions will be mapped to functions that you create. In this example, you'll map "SHOWTASKPANE" to a function that calls the [Office.addin.showAsTaskpane](/javascript/api/office/office.addin#office-office-addin-showastaskpane-member(1)) method and "HIDETASKPANE" to a function that calls the [Office.addin.hide](/javascript/api/office/office.addin#office-office-addin-hide-member(1)) method. +--- -## Create a mapping of actions to their functions +## Map custom actions to their functions -1. In your project, open the JavaScript file loaded by your HTML page in the **\<FunctionFile\>** element. -1. In the JavaScript file, use the [Office.actions.associate](/javascript/api/office/office.actions#office-office-actions-associate-member(1)) API to map each action that you specified in the JSON file to a JavaScript function. Add the following JavaScript to the file. Note the following about the code. +1. In your project, open the JavaScript file loaded by the HTML page specified in your manifest. - - The first parameter is one of the actions from the JSON file. - - The second parameter is the function that runs when a user presses the key combination that is mapped to the action in the JSON file. +1. In the JavaScript file, use the [Office.actions.associate](/javascript/api/office/office.actions#office-office-actions-associate-member) API to map each action you specified in an earlier step to a JavaScript function. Add the following JavaScript to the file. Note the following about the code. + - The first parameter is the name of an action that you mapped to a keyboard shortcut. The location of the name of the action depends on the type of manifest your add-in uses. + - **Unified app manifest for Microsoft 365**: The value of the `"extensions.keyboardShortcuts.shortcuts.actionId"` property in the **manifest.json** file. + - **Add-in only manifest**: The value of the `"actions.id"` property in the shortcuts JSON file. + - The second parameter is the function that runs when a user presses the key combination that's mapped to an action. ```javascript - Office.actions.associate("SHOWTASKPANE", showTaskPane); - Office.actions.associate("HIDETASKPANE", hideTaskPane); - - function showTaskPane() { - return Office.addin.showAsTaskpane() - .then(() => { - console.log("Task pane is visible."); + Office.actions.associate("ShowTaskpane", () => { + return Office.addin.showAsTaskpane() + .then(() => { + return; }) - .catch((error) => { - console.log(error.code); + .catch((error) => { + return error.code; }); - } + }); + ``` - function hideTaskPane() { + ```javascript + Office.actions.associate("HideTaskpane", () => { return Office.addin.hide() .then(() => { - console.log("Task pane is hidden."); + return; }) .catch((error) => { - console.log(error.code); - }) - } + return error.code; + }); + }); ``` -Following the previous steps lets your add-in toggle the visibility of the task pane by pressing **Ctrl+Alt+Up** and **Ctrl+Alt+Down**. The same behavior is shown in the [Excel keyboard shortcuts](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-keyboard-shortcuts) sample in the Office Add-in Samples repo in GitHub. +## Guidelines for custom key combinations -## Details and restrictions +Use the following guidelines to create custom key combinations for your add-ins. -### Construct the action objects +- A keyboard shortcut must include at least one modifier key (<kbd>Alt</kbd>/<kbd>Option</kbd>, <kbd>Ctrl</kbd>/<kbd>Cmd</kbd>, <kbd>Shift</kbd>) and only one other key. These keys must be joined with a `+` character. +- The <kbd>Cmd</kbd> modifier key is supported on the macOS platform. +- On macOS, the <kbd>Alt</kbd> key is mapped to the <kbd>Option</kbd> key. On Windows, the <kbd>Cmd</kbd> key is mapped to the <kbd>Ctrl</kbd> key. +- The <kbd>Shift</kbd> key can't be used as the only modifier key. It must be combined with either <kbd>Alt</kbd>/<kbd>Option</kbd> or <kbd>Ctrl</kbd>/<kbd>Cmd</kbd>. +- Key combinations can include characters "A-Z", "a-z", "0-9", and the punctuation marks "-", "_", and "+". By convention, lowercase letters aren't used in keyboard shortcuts. +- When two characters are linked to the same physical key on a standard keyboard, then they're synonyms in a custom keyboard shortcut. For example, <kbd>Alt</kbd>+<kbd>a</kbd> and <kbd>Alt</kbd>+<kbd>A</kbd> are the same shortcut, as well as <kbd>Ctrl</kbd>+<kbd>-</kbd> and <kbd>Ctrl</kbd>+<kbd>\_</kbd> ("-" and "_" are linked to the same physical key). -Use the following guidelines when specifying the objects in the `actions` array of the shortcuts.json. +> [!NOTE] +> Custom keyboard shortcuts must be pressed simultaneously. KeyTips, also known as sequential key shortcuts (for example, <kbd>Alt</kbd>+<kbd>H</kbd>, <kbd>H</kbd>), aren't supported in Office Add-ins. -- The property names `id` and `name` are mandatory. -- The `id` property is used to uniquely identify the action to invoke using a keyboard shortcut. -- The `name` property must be a user friendly string describing the action. It must be a combination of the characters A - Z, a - z, 0 - 9, and the punctuation marks "-", "_", and "+". -- The `type` property is optional. Currently only `ExecuteFunction` type is supported. +### Browser shortcuts that can't be overridden -The following is an example. +When using custom keyboard shortcuts on the web, some keyboard shortcuts that are used by the browser can't be overridden by add-ins. The following list is a work in progress. If you discover other combinations that can't be overridden, please let us know by using the feedback tool at the bottom of this page. -```json - "actions": [ - { - "id": "SHOWTASKPANE", - "type": "ExecuteFunction", - "name": "Show task pane for add-in" - }, - { - "id": "HIDETASKPANE", - "type": "ExecuteFunction", - "name": "Hide task pane for add-in" - } - ] -``` +- <kbd>Ctrl</kbd>+<kbd>N</kbd> +- <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>N</kbd> +- <kbd>Ctrl</kbd>+<kbd>T</kbd> +- <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>T</kbd> +- <kbd>Ctrl</kbd>+<kbd>W</kbd> +- <kbd>Ctrl</kbd>+<kbd>PgUp</kbd>/<kbd>PgDn</kbd> -The complete schema for the shortcuts JSON is at [extended-manifest.schema.json](https://developer.microsoft.com/json-schemas/office-js/extended-manifest.schema.json). +### Avoid key combinations in use by other add-ins -### Construct the shortcut objects +There are many keyboard shortcuts that are already in use by Microsoft 365. Avoid registering keyboard shortcuts for your add-in that are already in use. However, there may be some instances where it's necessary to override existing keyboard shortcuts or handle conflicts between multiple add-ins that have registered the same keyboard shortcut. -Use the following guidelines when specifying the objects in the `shortcuts` array of the shortcuts.json. +In the case of a conflict, the user will see a dialog box the first time they attempt to use a conflicting keyboard shortcut. Note that the source of the text for the add-in option that's displayed in this dialog varies depending on the type of manifest your add-in uses. + - **Unified app manifest for Microsoft 365**: The value of the `"extensions.runtimes.actions.displayName"` property in the **manifest.json** file. + - **Add-in only manifest**: The value of the `"actions.name"` property in the shortcuts JSON file. -- The property names `action`, `key`, and `default` are required. -- The value of the `action` property is a string and must match one of the `id` properties in the action object. -- The `default` property can be any combination of the characters A - Z, a -z, 0 - 9, and the punctuation marks "-", "_", and "+". (By convention, lowercase letters aren't used in these properties.) -- The `default` property must contain the name of at least one modifier key (Alt, Ctrl, Shift) and only one other key. -- Shift cannot be used as the only modifier key. Combine Shift with either Alt or Ctrl. -- For Macs, we also support the Command modifier key. -- For Macs, Alt is mapped to the Option key. For Windows, Command is mapped to the Ctrl key. -- When two characters are linked to the same physical key in a standard keyboard, then they're synonyms in the `default` property; for example, Alt+a and Alt+A are the same shortcut, so are Ctrl+- and Ctrl+\_ because "-" and "_" are the same physical key. -- The "+" character indicates that the keys on either side of it are pressed simultaneously. +![A conflict modal with two different actions for a single shortcut.](../images/add-in-shortcut-conflict-modal.png) -The following is an example. +The user can select which action the keyboard shortcut will take. After making the selection, the preference is saved for future uses of the same shortcut. The shortcut preferences are saved per user, per platform. If the user wishes to change their preferences, they can invoke the **Reset Office Add-ins shortcut preferences** command from the **Tell me** search box. Invoking the command clears all of the user's add-in shortcut preferences and the user will again be prompted with the conflict dialog box the next time they attempt to use a conflicting shortcut. -```json - "shortcuts": [ - { - "action": "SHOWTASKPANE", - "key": { - "default": "Ctrl+Alt+Up" - } - }, - { - "action": "HIDETASKPANE", - "key": { - "default": "Ctrl+Alt+Down" - } - } - ] -``` +![The Tell me search box in Excel showing the reset Office Add-in shortcut preferences action.](../images/add-in-reset-shortcuts-action.png) -The complete schema for the shortcuts JSON is at [extended-manifest.schema.json](https://developer.microsoft.com/json-schemas/office-js/extended-manifest.schema.json). +For the best user experience, we recommend that you minimize keyboard shortcut conflicts with these good practices. -> [!NOTE] -> KeyTips, also known as sequential key shortcuts, such as the Excel shortcut to choose a fill color **Alt+H, H**, aren't supported in Office Add-ins. +- Use only keyboard shortcuts with the following pattern: <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Alt</kbd>+*x*, where *x* is some other key. +- Avoid using established keyboard shortcuts in Excel and Word. For a list, see the following: + - [Keyboard shortcuts in Excel](https://support.microsoft.com/office/1798d9d5-842a-42b8-9c99-9b7213f0040f) + - [Keyboard shortcuts in Word](https://support.microsoft.com/office/95ef89dd-7142-4b50-afb2-f762f663ceb2) +- When the keyboard focus is inside the add-in UI, <kbd>Ctrl</kbd>+<kbd>Space</kbd> and <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>F10</kbd> won't work as these are essential accessibility shortcuts. +- On a Windows or Mac computer, if the **Reset Office Add-ins shortcut preferences** command isn't available on the search menu, the user can manually add the command to the ribbon by customizing the ribbon through the context menu. -## Avoid key combinations in use by other add-ins +## Localize the description of a keyboard shortcut -There are many keyboard shortcuts that are already in use by Office. Avoid registering keyboard shortcuts for your add-in that are already in use. However, there may be some instances where it's necessary to override existing keyboard shortcuts or handle conflicts between multiple add-ins that have registered the same keyboard shortcut. +You may need to localize your custom keyboard shortcuts in the following scenarios. -In the case of a conflict, the user will see a dialog box the first time they attempt to use a conflicting keyboard shortcut. Note that the text for the add-in option that's displayed in this dialog comes from the `name` property in the action object in `shortcuts.json` file. +- Your add-in supports multiple locales. +- Your add-in supports different alphabets, writing systems, or keyboard layouts. -![A conflict modal with two different actions for a single shortcut.](../images/add-in-shortcut-conflict-modal.png) +Guidance on how to localize your keyboard shortcuts varies depending on the type of manifest your add-in uses. -The user can select which action the keyboard shortcut will take. After making the selection, the preference is saved for future uses of the same shortcut. The shortcut preferences are saved per user, per platform. If the user wishes to change their preferences, they can invoke the **Reset Office Add-ins shortcut preferences** command from the **Tell me** search box. Invoking the command clears all of the user's add-in shortcut preferences and the user will again be prompted with the conflict dialog box the next time they attempt to use a conflicting shortcut. +# [Unified app manifest for Microsoft 365](#tab/jsonmanifest) -![The Tell me search box in Excel showing the reset Office Add-in shortcut preferences action.](../images/add-in-reset-shortcuts-action.png) +To learn how to localize your custom keyboard shortcuts with the unified app manifest for Microsoft 365, see [Localize strings in your app manifest](/microsoftteams/platform/concepts/build-and-test/apps-localization). -For the best user experience, we recommend that you minimize conflicts with Excel with these good practices. +> [!NOTE] +> If you've defined keyboard shortcuts for an add-in that uses the unified manifest and want to publish it to [Microsoft Marketplace](../publish/publish-office-add-ins-to-appsource.md), you must specify JSON resource files for the custom shortcuts and their localized strings (if applicable) in the manifest. These resource files are used for backward compatibility on platforms that don't directly support the unified manifest. To learn how to configure this in your manifest, see [Support backward compatibility for add-ins with a unified manifest in Microsoft Marketplace](#support-backward-compatibility-for-add-ins-with-a-unified-manifest-in-microsoft-marketplace). -- Use only keyboard shortcuts with the following pattern: **Ctrl+Shift+Alt+*x***, where *x* is some other key. -- If you need more keyboard shortcuts, check the [list of Excel keyboard shortcuts](https://support.microsoft.com/office/1798d9d5-842a-42b8-9c99-9b7213f0040f), and avoid using any of them in your add-in. -- When the keyboard focus is inside the add-in UI, **Ctrl+Spacebar** and **Ctrl+Shift+F10** won't work as these are essential accessibility shortcuts. -- On a Windows or Mac computer, if the "Reset Office Add-ins shortcut preferences" command isn't available on the search menu, the user can manually add the command to the ribbon by customizing the ribbon through the context menu. +# [Add-in only manifest](#tab/xmlmanifest) -## Customize the keyboard shortcuts per platform +### Update the shortcuts JSON file -It's possible to customize shortcuts to be platform-specific. The following is an example of the `shortcuts` object that customizes the shortcuts for each of the following platforms: `windows`, `mac`, `web`. Note that you must still have a `default` shortcut key for each shortcut. +To define localized strings for your custom shortcuts, you must specify tokens in your add-in's shortcuts JSON file. The tokens name strings in the localization resource file, which you'll create in a later step. The following is an example that assigns a keyboard shortcut to a function (defined elsewhere) that displays the add-in's task pane. Note the following about this markup. -In the following example, the `default` key is the fallback key for any platform that isn't specified. The only platform not specified is Windows, so the `default` key will only apply to Windows. +- The tokens must have the format **${resource.*name-of-resource*}**. The resource name must match the applicable locale string specified in the localization resource file. +- Default strings *must be defined in the extended overrides file itself*. Default strings are used when the locale of the Microsoft 365 host application doesn't match any of the *ll-cc* properties in the resources file. Defining the default strings directly in the extended overrides file ensures that Microsoft 365 doesn't download the resource file when the locale of the Microsoft 365 application matches the default locale of the add-in (as specified in the manifest). ```json - "shortcuts": [ +{ + "actions": [ { - "action": "SHOWTASKPANE", - "key": { - "default": "Ctrl+Alt+Up", - "mac": "Command+Shift+Up", - "web": "Ctrl+Alt+1", - } - }, + "id": "ShowTaskpane", + "type": "ExecuteFunction", + "name": "${resource.ShowTaskpane_action_name}" + } + ], + "shortcuts": [ { - "action": "HIDETASKPANE", + "action": "ShowTaskpane", "key": { - "default": "Ctrl+Alt+Down", - "mac": "Command+Shift+Down", - "web": "Ctrl+Alt+2" + "default": "${resource.ShowTaskpane_default_shortcut}" } } - ] + ], + "resources": { + "default": { + "ShowTaskpane_default_shortcut": { + "value": "CTRL+SHIFT+A" + }, + "ShowTaskpane_action_name": { + "value": "Show task pane for add-in" + } + } + } +} ``` -## Localize the keyboard shortcuts JSON +### Create a localization resource file -If your add-in supports multiple locales, you'll need to localize the `name` property of the action objects. Also, if any of the locales that the add-in supports have different alphabets or writing systems, and hence different keyboards, you may need to localize the shortcuts also. For information about how to localize the keyboard shortcuts JSON, see [Localize extended overrides](../develop/localization.md#localize-extended-overrides). +The localization resource file, which is also JSON-formatted, has a top-level `resources` property that's divided into subproperties by locale. For each locale, a string is assigned to each token that was used in the shortcuts JSON file. The following is an example which has strings for `en-us` and `fr-fr`. In this example, the keyboard shortcut is the same in both locales, but that won't always be the case, especially when you're localizing for locales that have a different alphabet or writing system, and hence a different keyboard. -## Browser shortcuts that cannot be overridden +```json +{ + "resources":{ + "en-us": { + "ShowTaskpane_default_shortcut": { + "value": "CTRL+SHIFT+A" + }, + "ShowTaskpane_action_name": { + "value": "Show task pane for add-in" + }, + }, + "fr-fr": { + "ShowTaskpane_default_shortcut": { + "value": "CTRL+SHIFT+A" + }, + "ShowTaskpane_action_name": { + "value": "Afficher le volet de tâche pour add-in" + } + } + } +} +``` -When using custom keyboard shortcuts on the web, some keyboard shortcuts that are used by the browser cannot be overridden by add-ins. This list is a work in progress. If you discover other combinations that cannot be overridden, please let us know by using the feedback tool at the bottom of this page. +### Specify the localization resource file in the manifest -- Ctrl+N -- Ctrl+Shift+N -- Ctrl+T -- Ctrl+Shift+T -- Ctrl+W -- Ctrl+PgUp/PgDn +Use the `ResourceUrl` attribute of the [ExtendedOverrides](/javascript/api/manifest/extendedoverrides) element to point Microsoft 365 to the localization resource file. The following is an example. -## Enable custom keyboard shortcuts for specific users +```xml + ... + </VersionOverrides> + <ExtendedOverrides Url="https://contoso.com/addin/shortcuts.json" + ResourceUrl="https://contoso.com/addin/localization.json"> + </ExtendedOverrides> +</OfficeApp> +``` -Your add-in can enable users to reassign the actions of the add-in to alternate keyboard combinations. +--- + +## Turn on shortcut customization for specific users > [!NOTE] > The APIs described in this section require the [KeyboardShortcuts 1.1](/javascript/api/requirement-sets/common/keyboard-shortcuts-requirement-sets) requirement set. -Use the [Office.actions.replaceShortcuts](/javascript/api/office/office.actions#office-office-actions-replaceshortcuts-member) method to assign a user's custom keyboard combinations to your add-ins actions. The method takes a parameter of type `{[actionId:string]: string|null}`, where the `actionId`s are a subset of the action IDs that must be defined in the add-in's extended manifest JSON. The values are the user's preferred key combinations. The value can also be `null`, which will remove any customization for that `actionId` and revert to the default keyboard combination that is defined in the add-in's extended manifest JSON. +Users of your add-in can reassign the actions of the add-in to alternate keyboard combinations. -If the user is logged into Office, the custom combinations are saved in the user's roaming settings per platform. Customizing shortcuts are currently not supported for anonymous users. +Use the [Office.actions.replaceShortcuts](/javascript/api/office/office.actions#office-office-actions-replaceshortcuts-member) method to assign a user's custom keyboard combinations to your add-ins actions. The method takes a parameter of type `{[actionId:string]: string|null}`, where the `actionId`s are a subset of the action IDs that must be defined in the add-in's extended manifest JSON. The values are the user's preferred key combinations. The value can also be `null`, which will remove any customization for that `actionId` and revert to the specified default keyboard combination. + +If the user is logged into Microsoft 365, the custom combinations are saved in the user's roaming settings per platform. Customizing shortcuts aren't currently supported for anonymous users. ```javascript const userCustomShortcuts = { - SHOWTASKPANE:"CTRL+SHIFT+1", - HIDETASKPANE:"CTRL+SHIFT+2" + ShowTaskpane: "Ctrl+Shift+1", + HideTaskpane: "Ctrl+Shift+2" }; + Office.actions.replaceShortcuts(userCustomShortcuts) - .then(function () { - console.log("Successfully registered."); + .then(() => { + console.log("Successfully registered shortcut."); }) - .catch(function (ex) { - if (ex.code == "InvalidOperation") { - console.log("ActionId does not exist or shortcut combination is invalid."); + .catch((error) => { + if (error.code == "InvalidOperation") { + console.log("ActionId doesn't exist or shortcut combination is invalid."); } }); ``` -To find out what shortcuts are already in use for the user, call the [Office.actions.getShortcuts](/javascript/api/office/office.actions#office-office-actions-getshortcuts-member) method. This method returns an object of type `[actionId:string]:string|null}`, where the values represent the current keyboard combination the user must use to invoke the specified action. The values can come from three different sources: +To find out what shortcuts are already in use for the user, call the [Office.actions.getShortcuts](/javascript/api/office/office.actions#office-office-actions-getshortcuts-member) method. This method returns an object of type `[actionId:string]:string|null}`, where the values represent the current keyboard combination the user must use to invoke the specified action. The values can come from three different sources. -- If there was a conflict with the shortcut and the user has chosen to use a different action (either native or another add-in) for that keyboard combination, the value returned will be `null` since the shortcut has been overridden and there is no keyboard combination the user can currently use to invoke that add-in action. +- If there was a conflict with the shortcut and the user has chosen to use a different action (either native or another add-in) for that keyboard combination, the value returned will be `null` since the shortcut has been overridden and there's no keyboard combination the user can currently use to invoke that add-in action. - If the shortcut has been customized using the [Office.actions.replaceShortcuts](/javascript/api/office/office.actions#office-office-actions-replaceshortcuts-member) method, the value returned will be the customized keyboard combination. -- If the shortcut has not been overridden or customized, it will return the value from the add-in's extended manifest JSON. +- If the shortcut hasn't been overridden or customized, the value returned varies depending on the type of manifest the add-in uses. + - **Unified app manifest for Microsoft 365**: The shortcut specified in the **manifest.json** file of the add-in. + - **Add-in only manifest**: The shortcut specified in the shortcuts JSON file of the add-in. The following is an example. ```javascript Office.actions.getShortcuts() - .then(function (userShortcuts) { + .then((userShortcuts) => { for (const action in userShortcuts) { let shortcut = userShortcuts[action]; console.log(action + ": " + shortcut); } }); - ``` -As described in [Avoid key combinations in use by other add-ins](#avoid-key-combinations-in-use-by-other-add-ins), it's a good practice to avoid conflicts in shortcuts. To discover if one or more key combinations are already in use pass them as an array of strings to the [Office.actions.areShortcutsInUse](/javascript/api/office/office.actions#office-office-actions-areshortcutsinuse-member) method. The method returns a report containing key combinations that are already in use in the form of an array of objects of type `{shortcut: string, inUse: boolean}`. The `shortcut` property is a key combination, such as "CTRL+SHIFT+1". If the combination is already registered to another action, the `inUse` property is set to `true`. For example, `[{shortcut: "CTRL+SHIFT+1", inUse: true}, {shortcut: "CTRL+SHIFT+2", inUse: false}]`. The following code snippet is an example: +As described in [Avoid key combinations in use by other add-ins](#avoid-key-combinations-in-use-by-other-add-ins), it's a good practice to avoid conflicts in shortcuts. To discover if one or more key combinations are already in use, pass them as an array of strings to the [Office.actions.areShortcutsInUse](/javascript/api/office/office.actions#office-office-actions-areshortcutsinuse-member) method. The method returns a report containing key combinations that are already in use in the form of an array of objects of type `{shortcut: string, inUse: boolean}`. The `shortcut` property is a key combination, such as "Ctrl+Shift+1". If the combination is already registered to another action, the `inUse` property is set to `true`. For example, `[{shortcut: "Ctrl+Shift+1", inUse: true}, {shortcut: "Ctrl+Shift+2", inUse: false}]`. The following code snippet is an example. ```javascript -const shortcuts = ["CTRL+SHIFT+1", "CTRL+SHIFT+2"]; +const shortcuts = ["Ctrl+Shift+1", "Ctrl+Shift+2"]; Office.actions.areShortcutsInUse(shortcuts) - .then(function (inUseArray) { - const availableShortcuts = inUseArray.filter(function (shortcut) { return !shortcut.inUse; }); + .then((inUseArray) => { + const availableShortcuts = inUseArray.filter((shortcut) => { + return !shortcut.inUse; + }); console.log(availableShortcuts); - const usedShortcuts = inUseArray.filter(function (shortcut) { return shortcut.inUse; }); + const usedShortcuts = inUseArray.filter((shortcut) => { + return shortcut.inUse; + }); console.log(usedShortcuts); }); +``` + +## Implement custom keyboard shortcuts across supported Microsoft 365 apps + +You can implement a custom keyboard shortcut to be used across supported Microsoft 365 apps, such as Excel and Word. If the implementation to perform the same task is different on each app, you must use the `Office.actions.associate` method to call a different callback function for each app. The following code is an example. +```javascript +const host = Office.context.host; +if (host === Office.HostType.Excel) { + Office.actions.associate("ChangeFormat", changeFormatExcel); +} else if (host === Office.HostType.Word) { + Office.actions.associate("ChangeFormat", changeFormatWord); +} +... +``` + +## Support backward compatibility for add-ins with a unified manifest in Microsoft Marketplace + +To publish an add-in that uses the unified manifest and implements custom keyboard shortcuts to Microsoft Marketplace, you must specify JSON resource files for the shortcuts and their localized strings (if applicable) in the manifest. This ensures your add-in's keyboard shortcuts and its localized resources work on platforms that don't directly support the unified manifest (for information on supported clients and platforms, see [Office Add-ins with the unified app manifest for Microsoft 365](../develop/unified-manifest-overview.md#client-and-platform-support)). + +### Create JSON resource files + +For guidance on how to create a shortcuts JSON file, see [Create or edit the shortcuts JSON file](#create-or-edit-the-shortcuts-json-file). If your custom shortcuts are supplemented with localized strings, you must define resource tokens in your shortcuts JSON file and create a localization resource file. For guidance, see [Update the shortcuts JSON file](#update-the-shortcuts-json-file) and [Create a localization resource file](#create-a-localization-resource-file). + +### Specify the JSON resource files in the manifest + +In your add-in's manifest, specify the JSON resource files in the [`"extensions.keyboardShortcuts.keyMappingFiles"`](/microsoft-365/extensibility/schema/extension-keyboard-shortcut?view=m365-app-prev&preserve-view=true#keymappingfiles) object. + +- For the shortcuts JSON file, provide its full HTTPS URL in the [`"extensions.keyboardShortcuts.keyMappingFiles.shortcutsUrl"`](/microsoft-365/extensibility/schema/keyboard-shortcuts-mapping-files?view=m365-app-prev&preserve-view=true#shortcutsurl) property. +- For the localization resource file, provide its full HTTPS URL in the [`"extensions.keyboardShortcuts.keyMappingFiles.localizationResourceUrl"`](/microsoft-365/extensibility/schema/keyboard-shortcuts-mapping-files?view=m365-app-prev&preserve-view=true#localizationresourceurl) property. + +The following is an example of how to specify shortcuts and localization resource files in the manifest. + +```json +"keyboardShortcuts": [ + { + ... + "shortcuts": [ + ... + ], + "keyMappingFiles": { + "shortcutsUrl": "https://contoso.com/addin/shortcuts.json", + "localizationResourceUrl": "https://contoso.com/addin/localization.json" + } + } +] ``` -## Next Steps +## See also -- See the [Excel keyboard shortcuts](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-keyboard-shortcuts) sample add-in. -- Get an overview of working with extended overrides in [Work with extended overrides of the manifest](../develop/extended-overrides.md). +- [Office Add-in sample: Use keyboard shortcuts for Office Add-in actions](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/office-keyboard-shortcuts) +- [Shared runtime requirement sets](/javascript/api/requirement-sets/common/shared-runtime-requirement-sets) +- [Keyboard shortcuts requirement sets](/javascript/api/requirement-sets/common/keyboard-shortcuts-requirement-sets) diff --git a/docs/design/microsoft-365-extension-management-icons.md b/docs/design/microsoft-365-extension-management-icons.md new file mode 100644 index 0000000000..40adf6986e --- /dev/null +++ b/docs/design/microsoft-365-extension-management-icons.md @@ -0,0 +1,19 @@ +--- +title: Design icons for add-in acquisition and management +description: Get design guidance for the icons that represent an add-in in the UIs for app acquisition and managment. +ms.date: 11/03/2025 +ms.topic: best-practice +ms.localizationpriority: medium +--- + +# Design icons for add-in acquisisiton and management + +An Office add-in is an App for Microsoft 365, just as are Teams apps and Copilot extensions. If the add-in uses the [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md), then it must conform to the requirements for Microsoft 365 extensions. In particular, it must have two icons that represent it in the app acquisition and managment UI of Teams, Office, Copilot, and other Microsoft 365 applications. + +> [!NOTE] +> +> - This article isn't relevant to add-ins that use the [add-in only manifest](../develop/xml-manifest-overview.md). +> - This article *isn't* about designing icons for an add-in's ribbon buttons. For guidance about those, start with [Icon guidelines for Office Add-ins](add-in-icons.md). +> - For guidance about designing icons that represent an add-in Microsoft Marketplace, see [Create an icon for your add-in](/partner-center/marketplace-offers/create-effective-office-store-listings#create-an-icon-for-your-add-in). + +[!INCLUDE [Microsoft 365 icon design guidance](~/../reusable-content/microsoft-365-development/includes/design-microsoft-365-extension-icons.md)] \ No newline at end of file diff --git a/docs/design/using-motion-office-addins.md b/docs/design/using-motion-office-addins.md index 8ea02e6595..09c85be98b 100644 --- a/docs/design/using-motion-office-addins.md +++ b/docs/design/using-motion-office-addins.md @@ -1,7 +1,7 @@ --- title: Using motion in Office Add-ins description: Get best practices for using transitions, motion, or animation in Office Add-ins. -ms.date: 06/27/2023 +ms.date: 10/29/2025 ms.topic: best-practice ms.localizationpriority: medium --- @@ -34,7 +34,7 @@ We recommend using [Fluent UI](../design/add-in-design.md) to create a visual co - [Fluent UI React motion patterns](https://react.fluentui.dev/?path=/docs/theme-motion--page) - [Fabric Core motion and animation patterns](https://developer.microsoft.com/fluentui#/styles/web/motion) -Use it to fit seamlessly in your add-in. It will help you create experiences that are more felt than observed. The animation CSS classes provide directionality, enter/exit, and duration specifics that reinforce Office mental models and provide opportunities for customers to learn how to interact with your add-in. +Use it to fit seamlessly in your add-in. It will help you create experiences that are more felt than observed. The animation CSS classes provide directionality, enter, exit, and duration specifics that reinforce Office mental models and provide opportunities for customers to learn how to interact with your add-in. ### Best practices diff --git a/docs/design/ux-design-pattern-templates.md b/docs/design/ux-design-pattern-templates.md index 5fb9e2f670..16659a272d 100755 --- a/docs/design/ux-design-pattern-templates.md +++ b/docs/design/ux-design-pattern-templates.md @@ -1,7 +1,7 @@ --- title: UX design patterns for Office Add-ins description: Get an overview of the UI design patterns for Office Add-ins, including patterns for navigation, authentication, first-run, and branding. -ms.date: 06/27/2023 +ms.date: 10/29/2025 ms.topic: overview ms.localizationpriority: medium --- @@ -36,10 +36,10 @@ The patterns are organized by key actions or experiences that are common in an a Browse each grouping to get an idea of how you can design your add-in using best practices. > [!NOTE] -> The example screens shown throughout this documentation are designed and displayed at a resolution of **1366x768**. +> The example screens shown throughout the design pattern documentation are designed and displayed at a resolution of **1366x768**. ## See also -- [Design tool kits](design-toolkits.md) +- [Office Add-in design language](add-in-design-language.md) - [Best practices for developing Office Add-ins](../concepts/add-in-development-best-practices.md) - [Fluent UI React in Office Add-ins](../quickstarts/fluent-react-quickstart.md) diff --git a/docs/design/voice-guidelines.md b/docs/design/voice-guidelines.md index 4268ce2093..b4d5244c5a 100644 --- a/docs/design/voice-guidelines.md +++ b/docs/design/voice-guidelines.md @@ -1,16 +1,16 @@ --- -title: Voice and tone guidelines for Office Add-ins +title: Writing and style guidelines for Office Add-ins description: Learn best practices in writing user help and other text for Office Add-ins. -ms.date: 05/18/2023 +ms.date: 06/16/2025 ms.topic: best-practice ms.localizationpriority: medium --- -# Voice and tone guidelines +# Writing and style guidelines -As you design your Office Add-ins, consider the voice that you use in your UI text and elements. Strive to match the voice and tone of the Office UI, which is conversational, engaging, and accessible to users. +As you design your Office Add-ins, consider the voice you use in your UI text and elements. Strive to match the voice and tone of the Office UI, which is conversational, engaging, and accessible to users. -- **Use a natural style.** Write the way that you speak. Avoid jargon and overly technical words and phrases. Use terms that are familiar to your users. +- **Use a natural style.** Write the way you speak. Avoid jargon and overly technical words and phrases. Use terms that are familiar to your users. - **Use simple, direct language.** Use short words and sentences, and active voice in your text. - **Be consistent.** Use the same words for the same concepts throughout. - **Engage the user.** Address the user as "you". Avoid using third person. Use imperatives for user tasks. diff --git a/docs/develop/add-in-manifests.md b/docs/develop/add-in-manifests.md index d51639a75a..2525bf28da 100644 --- a/docs/develop/add-in-manifests.md +++ b/docs/develop/add-in-manifests.md @@ -1,8 +1,8 @@ ---- +--- title: Office Add-ins manifest description: Get an overview of the Office Add-in manifest and its uses. ms.topic: overview -ms.date: 04/12/2024 +ms.date: 10/10/2025 ms.localizationpriority: high --- @@ -10,8 +10,8 @@ ms.localizationpriority: high Every Office add-in has a manifest. There are two types of manifests: -- **Add-in only manifest**: This is the only type of manifest that's currently supported for non-Outlook add-ins. Its format is XML. This type of manifest can't be used for an app that combines an add-in with some other kind of extension of the Microsoft 365 platform. -- **Unified manifest for Microsoft 365**: This is an expanded version of the JSON-formatted manifest that has been used for years as the manifest for Teams Apps. Add-ins that use this manifest can be combined with other kinds of extensions of the Microsoft 365 platform in a single app that's installable as a unit. +- **Add-in only manifest**: This type of manifest can be used for production add-ins in Excel, OneNote, Outlook, PowerPoint, Project, and Word. It can't be used for an app that combines an add-in with some other kind of extension of the Microsoft 365 platform. Its format is XML. +- **Unified manifest for Microsoft 365**: This is an expanded version of the JSON-formatted manifest that has been used for years as the manifest for Teams Apps. Add-ins that use this manifest can be combined with other kinds of Apps for Microsoft 365, that is, extensions of Microsoft 365, in a single app that's installable as a unit. You can use this type of manifest for production Outlook add-ins. It's available for preview in Excel, PowerPoint, and Word add-ins. [!INCLUDE [non-unified manifest clients note](../includes/non-unified-manifest-clients.md)] @@ -45,11 +45,11 @@ All image URIs, such as those used for [add-in commands](../design/add-in-comman All URLs to code or content files in the add-in should be **SSL-secured (HTTPS)**. [!INCLUDE [HTTPS guidance](../includes/https-guidance.md)] -## Best practices for submitting to AppSource +## Best practices for submitting to Microsoft Marketplace Make sure that the add-in ID is a valid and unique GUID. Various GUID generator tools are available on the web that you can use to create a unique GUID. -Add-ins submitted to AppSource must also include a support URL in the manifest. For more information, see [Validation policies for apps and add-ins submitted to AppSource](/legal/marketplace/certification-policies). +Add-ins submitted to Microsoft Marketplace must also include a support URL in the manifest. For more information, see [Validation policies for apps and add-ins submitted to Microsoft Marketplace](/legal/marketplace/certification-policies). ## Specify domains you want to open in the add-in window diff --git a/docs/develop/add-ins-with-angular2.md b/docs/develop/add-ins-with-angular2.md index 416dae2524..5b375ea4ed 100644 --- a/docs/develop/add-ins-with-angular2.md +++ b/docs/develop/add-ins-with-angular2.md @@ -2,7 +2,7 @@ title: Develop Office Add-ins with Angular description: Use Angular to create an Office Add-in as a single page application. ms.topic: best-practice -ms.date: 04/02/2024 +ms.date: 08/25/2025 ms.localizationpriority: medium --- @@ -117,7 +117,9 @@ ng serve --aot ## Support the Trident webview control -Older Office clients use the Trident webview control provided by Internet Explorer 11, as described in [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). There are a couple Angular-specific considerations to make if your add-in needs to support these Office versions. +Older Office clients use the Trident webview control provided by Internet Explorer 11, as described in [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). *Angular versions 12 and later are incompatible with the Trident webview, so an add-in based on Angular version 12 or later won't run on older Office clients.* + +If you need to support older versions of Office, you must use an Angular version between 2 and 11, such as Angular 10. In addition, there are a couple Angular-specific considerations to make if your add-in needs to support these Office versions. Angular depends on a few `window.history` APIs. These APIs don't work in the Trident webview. When these APIs don't work, your add-in may not work properly, for example, it may load a blank task pane. To mitigate this, Office.js nullifies those APIs. However, if you're dynamically loading Office.js, AngularJS may load before Office.js. In that case, you should disable the `window.history` APIs by adding the following code to your add-in's **index.html** page. diff --git a/docs/develop/addressing-same-origin-policy-limitations.md b/docs/develop/addressing-same-origin-policy-limitations.md index ec1468d775..01b059496c 100644 --- a/docs/develop/addressing-same-origin-policy-limitations.md +++ b/docs/develop/addressing-same-origin-policy-limitations.md @@ -42,7 +42,7 @@ Another way to address same-origin policy limitations is to provide server-side To learn more about cross-origin resource sharing, see the many resources available on the web, such as [Cross-Origin Resource Sharing (CORS)](https://web.dev/cross-origin-resource-sharing/). > [!NOTE] -> For information on how to use CORS in an Outlook add-in that implements event-based activation or integrated spam reporting (preview), see [Use single sign-on (SSO) or cross-origin resource sharing (CORS) in your event-based or spam-reporting Outlook add-in](../outlook/use-sso-in-event-based-activation.md). +> For information on how to use CORS in an Outlook add-in that implements event-based activation or integrated spam reporting, see [Use single sign-on (SSO) or cross-origin resource sharing (CORS) in your event-based or spam-reporting Outlook add-in](../develop/use-sso-in-event-based-activation.md). ## Build your own proxy using IFRAME and POST MESSAGE (Cross-Window Messaging) diff --git a/docs/develop/agent-and-add-in.md b/docs/develop/agent-and-add-in.md new file mode 100644 index 0000000000..6840c4f062 --- /dev/null +++ b/docs/develop/agent-and-add-in.md @@ -0,0 +1,357 @@ +--- +title: Add a Copilot agent to an add-in +description: Learn how to add a Copilot agent to an add-in. +ms.date: 10/17/2025 +ms.topic: how-to +ms.service: microsoft-365 +ms.localizationpriority: medium +--- + +# Add a Copilot agent to an add-in + +Adding a Copilot agent to an Office Add-in provides two benefits: + +- Copilot becomes a natural language interface for the add-in's functionality. +- The agent can pass parameters to the JavaScript it invokes, which isn't possible when a [function command](../design/add-in-commands.md#types-of-add-in-commands) is invoked from a button or menu item. + +> [!NOTE] +> This article assumes that you're familiar with the overview [Combine Copilot Agents with Office Add-ins](../design/agent-and-add-in-overview.md) and the Copilot documentation that it refers to. We also recommend that you complete the quick start [Build your first add-in as a Copilot skill](../quickstarts/agent-and-add-in-quickstart.md). + +> [!IMPORTANT] +> This feature requires the [unified manifest for Microsoft 365](unified-manifest-overview.md). If your add-in uses the add-in only manifest, you must first [convert it to use the unified manifest](convert-xml-to-json-manifest.md) before you can add a Copilot agent to it. Before you continue with this article, you should know how to package the manifest and other files into an app package zip file and sideload it to an Office application for testing. + +## Major tasks + +The following are the main tasks for adding a Copilot agent to your add-in. Details are in the subsections. + +- [Create the functions for the agent's actions](#create-the-functions-for-the-agents-actions) that will implement the Copilot agent's actions. +- [Update the manifest](#update-the-manifest) +- [Create the agent and API plug-in configuration](#create-the-agent-and-api-plug-in-configuration) +- [Create the app package](#create-the-app-package) +- [Test the agent](#test-the-agent) +- [Make changes in the app](#make-changes-in-the-app) + +### Create the functions for the agent's actions + +If your add-in includes one or more [function commands](../design/add-in-commands.md#types-of-add-in-commands), then your project already has a JavaScript or TypeScript file that defines the functions for these commands (usually called **commands.js** or **commands.ts**) and a UI-less HTML file (usually called **commands.html**) that has a `<script>` tag to load the function file. We recommend that you use this same function file to define the functions for your agent's actions. Skip to the section [Update the function file](#update-the-function-file). + +#### Create the source files + +If your project doesn't already have such files, then create them with the following steps. The folder and file structure and names in these steps aren't mandatory, but we recommend them to minimize incompatibilities with add-in development tooling and configuration for bundlers and transpilers where applicable. + +1. Ensure that there's a folder **\src** off the root of the project, and that it has a child folder named **\commands**. +1. Create a **commands.js** (or .ts) file in the **\commands** folder. You add content to it in a later step. +1. Create a **commands.html** file in the **\commands** folder with the following content. Note the following about this markup. + + - The `<body>` element is empty because the file has no UI. Its only purpose is to load JavaScript files. + - The Office JavaScript Library and the **commands.js** file that you created in the preceding step is explicitly loaded. + + > [!NOTE] + > It's common in Office Add-in development to use tools like [webpack](https://webpack.js.org/) and its plug-ins to automatically inject `<script>` tags into HTML files at build time. If you use such a tool, you shouldn't include any `<script>` tags in your source file that are going to be inserted by the tool. + + ```html + <!DOCTYPE html> + <html> + <head> + <meta charset="UTF-8" /> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + + <!-- Office JavaScript Library --> + <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script> + <!-- Function command file --> + <script src="http://github.com/commands.js" type="text/javascript"></script> + </head> + <body> + </body> + </html> + ``` + +#### Update the function file + +Define the functions for your agent's actions with the following steps. These assume the most common folder and file structure and names. + +Open the function file (usually, the **\src\commands\commands.js** (or .ts)) and add the functions that implement the agent's actions. Keep the following points in mind as you work. + +- Like all code that calls APIs in the Office JavaScript Library, the file must [initialize the library](initialize-add-in.md), usually by calling `Office.onReady`. +- Functions that are invoked by agents take a `message` parameter that specifies the values that Office will use when it calls functions from the Office JavaScript Library. This object can be parsed with the `JSON.parse` method. The values of the object are specified by users in natural language. +- Unlike the functions that are invoked with add-in commands, these functions don't have an `Office.AddinCommands.Event` parameter, and they don't call the `Office.AddinCommands.Event.completed` method. Instead, functions that are invoked by agents return a result object from the JavaScript runtime back to the Copilot runtime. +- Functions invoked from Copilot have less time to complete than functions invoked from a function command. The latter have five minutes to complete or Office shuts down the JavaScript runtime. But Copilot-invoked functions have only two minutes to return a result or the runtime is shut down. +- For each function, there must be a call of [Office.actions.associate](/javascript/api/office/office.actions#office-office-actions-associate-member(1)) to tell Office which function in the file should be run when the agent action is invoked. The `associate` function maps the function name to an action ID that you configure in the manifest in a later step. If you define multiple functions in the same file, your code must call `associate` for each one. + +The following is an example. + +```javascript +Office.onReady(function() { + // Add any initialization code here. +}); + +async function fillColorFromUserData(message) { + const {cell, color} = JSON.parse(message); + await Excel.run(async (context) => { + context.workbook.worksheets + .getActiveWorksheet() + .getRange(cell).format.fill.color = color; + await context.sync(); + }); + return "Cell color changed."; +} + +Office.actions.associate("FillColor", fillColorFromUserData); +``` + +### Update the manifest + +There are three major parts to configuring the manifest for the Copilot agent as described in the following subsections. + +#### Use the preview manifest schema + +Ensure that the manifest references the preview version of the manifest schema with the following steps. + +1. At the top of the manifest, ensure that the [`"$schema"`](/microsoft-365/extensibility/schema/root#schema-4) property is the following: + + ```json + "$schema": "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.schema.json", + ``` + +1. Ensure that the [`"manifestVersion"`](/microsoft-365/extensibility/schema/root#manifestversion) property is set to "devPreview". + +#### Configure the runtime + +1. In the [`"extensions.runtimes"`](/microsoft-365/extensibility/schema/extension-runtimes-array) array, ensure that there's a runtime object that is oriented to running UI-less JavaScript functions. It's critical that the object have a [`"code.page"`](/microsoft-365/extensibility/schema/extension-runtime-code#page) property that specifies the absolute URL to the UI-less HTML file that you created (or edited) earlier in [Update the function file](#update-the-function-file). +1. In the [`"actions"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item) array of that same runtime object, add an object whose `"type"` property is set to "executeDataFunction" and whose `"id"` property is an exact match for the first parameter of the call to `Office.actions.associate` in a function that you created in [Update the function file](#update-the-function-file). +1. Repeat the preceding step for each function you created to implement an agent action. + +The runtime object should look similar to the following. There may be other properties of the runtime object, other runtime objects in the `"runtimes"` array, and other action objects in the `"actions"` array. + +```json +"runtimes": [ + { + "id": "CommandsRuntime", + "type": "general", + "code": { + "page": "https://localhost:3000/commands.html" + }, + "lifetime": "short", + "actions": [ + { + "id": "FillColor", + "type": "executeDataFunction", + } + ] + } +] +``` + +#### Declare the agent + +1. If there isn't one already, add a ["copilotAgents"](/microsoft-365/extensibility/schema/root-copilot-agents) object to the root of the manifest and ensure that it has a child ["declarativeAgents"](/microsoft-365/extensibility/schema/declarative-agent-ref) array. +1. Add an object to the `"declarativeAgents"` array and specify a unique and descriptive [`"id"`](/microsoft-365/extensibility/schema/declarative-agent-ref#id) for it. +1. Assign the object's [`"file"`](/microsoft-365/extensibility/schema/declarative-agent-ref#file) property the relative URL of the declarative agent configuration file. You create that file in a later step. + + The following is an example. + + ```json + "copilotAgents": { + "declarativeAgents": [ + { + "id": "ContosoCopilotAgent", + "file": "declarativeAgent.json" + } + ] + }, + ``` + +> [!TIP] +> To maximize compatibility with Microsoft tools for add-in development, we recommend that you create a folder named **appPackage** in the root of the project and move the manifest into it. + +### Create the agent and API plug-in configuration + +1. Create a file in the same folder where your manifest is and give it the name used in the `"copilot.declarativeAgents.file"` property, such as **declarativeAgent.json**. +1. Paste the following content into the file. + + ```json + { + "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.5/schema.json", + "version": "v1.5", + "name": "Excel Add-in + Agent", + "description": "Agent for working with Excel cells.", + "instructions": "You are an agent for working with an add-in. You can work with any cells, not just a well-formatted table.", + "conversation_starters": [ + { + "title": "Change cell color", + "text": "I want to change the color of cell B2 to orange" + } + ], + "actions": [ + { + "id": "localExcelPlugin", + "file": "Office-API-local-plugin.json" + } + ] + } + ``` + + [!INCLUDE [Validation warning about missing 'auth' property](../includes/auth-property-warning-note.md)] + +1. *Replace the property values with new values that are appropriate for your add-in.* For more information about these properties, see [Declarative agent manifest object](/microsoft-365-copilot/extensibility/declarative-agent-manifest-1.2#declarative-agent-manifest-object). + + > [!NOTE] + > You create the file that you specify in the `"actions.file"` property in the next step. In the example above, this is the file **Office-API-local-plugin.json**. + +1. Create another file in the folder with your manifest and give it the name you assigned to the `"actions.file"` property in the preceding step; for example, **Office-API-local-plugin.json**. +1. Paste the following content into the file. + + ```json + { + "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.3/schema.json", + "schema_version": "v2.3", + "name_for_human": "Excel Add-in + Agent", + "description_for_human": "Add-in Actions in Agents", + "namespace": "addinfunction", + "functions": [ + { + "name": "FillColor", + "description": "fillcolor changes a single cell location to a specific color.", + "parameters": { + "type": "object", + "properties": { + "cell": { + "type": "string", + "description": "A cell location in the format of A1, B2, etc.", + "default" : "B2" + }, + "color": { + "type": "string", + "description": "A color in hex format, e.g., #30d5c8", + "default" : "#30d5c8" + } + }, + "required": ["cell", "color"] + }, + "returns": { + "type": "string", + "description": "A string indicating the result of the action." + }, + "states": { + "reasoning": { + "description": "`FillColor` changes the color of a single cell based on the grid location and a color value.", + "instructions": "The user will pass ask for a color that isn't in the hex format needed in most cases, make sure to convert to the closest approximation in the right format." + }, + "responding": { + "description": "`FillColor` changes the color of a single cell based on the grid location and a color value.", + "instructions": "If there is no error present, tell the user the cell location and color that was set." + } + } + } + ], + "runtimes": [ + { + "type": "LocalPlugin", + "spec": { + "local_endpoint": "Microsoft.Office.Addin", + "allowed_host": ["workbook"] + }, + "run_for_functions": ["FillColor"] + } + ] + } + ``` + +1. *With some exceptions noted later, replace the property values with new values that are appropriate for your add-in.* For more information about these properties, see [API plugin manifest schema 2.3 for Microsoft 365 Copilot](/microsoft-365-copilot/extensibility/api-plugin-manifest-2.3). + + As you work, keep the following points in mind. + + - Do *not* change the `"namespace"`, `"runtimes.type"`, or `"runtimes.spec.local_endpoint"` values. + - The `"functions.name"` must be an exact match for both of the following: + + - An `"extensions.runtimes.actions.id"` property in the manifest (for an action of type "executeDataFunction"). + - The first parameter of the call to `Office.actions.associate` in a function that you created in [Update the function file](#update-the-function-file). + + - The `"runtimes.run_for_functions"` array must include either the same string as `"functions.name"` or a wildcard string that matches it. + - The `"reasoning.description"` and `"reasoning.instructions"` refer to a JavaScript function, not a REST API. + - The `"runtimes.spec.local_endpoint"` property tells the Copilot agent to look for functions in an Office Add-in instead of at a REST service URL. + +### Create the app package + +> [!IMPORTANT] +> To test the agent, as described later in this article in [Test the agent](#test-the-agent), the domain segment of any absolute URLs in the manifest must be a localhost domain; for example, `localhost:3000`. You can change these segments to a production domain later. + +Using any zip utility, create a zip file that contains the following files. + +- The manifest +- The icon files referenced in the manifest's [`"icons.color"`](/microsoft-365/extensibility/schema/root-icons#color) and [`"icons.outline"`](/microsoft-365/extensibility/schema/root-icons#outline) +- The two files you created in [Create the agent and API plug-in configuration](#create-the-agent-and-api-plug-in-configuration) +- Any files referenced in the [`"localizationInfo.additionalLanguages"`](/microsoft-365/extensibility/schema/root-localization-info#additionallanguages) property + +> [!IMPORTANT] +> Most of these files have URLs in the manifest that are relative to the location of the manifest, so the folder structure of the zip file must maintain this structure. For example, if the `"icons.color"` value is "/assets/icon-32.png", then there must be an **/assets** folder in the zip file with the **icon-32.png** file in it. + +> [!TIP] +> To maximize compatibility with Microsoft tools for add-in development, we recommend that you create a subfolder named **build** in the **appPackage** folder and create the zip file in it. + +### Test the agent + +The three major steps to test the agent — sideloading, starting a server, and running the agent — are described in the following subsections. + +#### Sideload the agent and add-in + +Sideloading is done through Teams even when there's no Teams feature in the app. The steps are as follows. + +1. Close all Office applications, and then clear the Office cache following the instructions at [Manually clear the cache](../testing/clear-cache.md#manually-clear-the-cache). +1. Open Teams and select **Apps** from the app bar, then select **Manage your apps** at the bottom of the **Apps** pane. +1. Select **Upload an app** in the **Apps** dialog, and then in the dialog that opens, select **Upload a custom app**. +1. In the **Open** dialog, navigate to, and select, the package zip file. +1. Select **Add** in the dialog that opens. +1. When you're prompted that the app was added, *don't* open it in Teams. Instead, close Teams. + +#### Start the server + +Your task is to start a local web server that hosts your project's HTML and JavaScript files. How you do this depends on several factors including the folder structure of your project, the tools you use, such as a bundler, task manager, server application, and how you have configured those tools. Since you're adding an agent to an existing add-in project, you already know how to do this. The following instruction applies only to projects that meet the following conditions. + +- There's a **webpack.config.js** file in the root of the project that is similar to the ones in add-in projects that are created with the [Yeoman Generator for Office Add-ins](yeoman-generator-overview.md) or [Microsoft 365 Agent Toolkit](teams-toolkit-overview.md). +- There's a **package.json** file in the root of the project similar to the ones created by the same two tools and the file has a "scripts" section with the following script in it. + + ```json + "dev-server": "webpack serve --mode development" + ``` + +In a command prompt or Visual Studio Code **TERMINAL** in the root of the project, run `npm run dev-server` to start the server on localhost. + +#### Run the agent + +1. Open the Office application (Excel, PowerPoint, or Word) that your combined agent and add-in targets. Wait until the add-in has loaded. This may take as much as two minutes. Depending on your version of Office, ribbon buttons and other artifacts may appear automatically. In recent versions, you need to manually activate the add-in: Select the **Add-ins** button on the **Home** ribbon, and then in the flyout that opens, select your add-in. It will have the name from the name from the [`"name.short"`](/microsoft-365/extensibility/schema/root-name) property in the manifest. +1. The process of opening your agent depends on the UI for Copilot in Office applications which is in transition. + + - If there is a **Copilot** *button* on the ribbon (not a dropdown menu), select the **Copilot** button to open the **Copilot** pane. + - If there is a **Copilot** dropdown menu, open the menu and select **App Skills** to open the **Copilot** pane. + +1. In the **Copilot** pane, select the hamburger control. +1. In the pane, your agent should be in the list of agents. It has the name specified in the `"name"` property of the declarative agent configuration file (which may not be the same as the name from the `"name.short"` property in the manifest); for example, **Excel Agent**. You may need to select **See more** to ensure that all agents are listed. If the agent isn't listed, try one or both of the following actions. + + - Wait a few minutes and reload Copilot. + - With Copilot open to the list of agents, click the cursor on the **Copilot** pane and press <kbd>Ctrl</kbd>+<kbd>R</kbd>. + + :::image type="content" source="../images/copilot-agent-list.png" alt-text="A screenshot of the agent list in the Copilot pane in an Office application"::: + +1. When the agent is listed, select it and the pane for the agent opens. The conversation starters you configured in the `"conversation_starters"` property of declarative agent configuration file will be displayed. +1. Select a conversation starter, and then press the **Send** control in the conversation box at the bottom of the pane. Select **Confirm** in response to the confirmation prompt. The agent action occurs. +1. Try entering prompts the conversation box that are different from the conversation starters, but that your agent should be able to do. + +### Make changes in the app + +Live reloading and hot reloading for a combined add-in and agent aren't supported in the preview period. To make changes, first shut down the server and uninstall the agent and add-in with these steps. + +1. Close the Office application. +1. If the web server is running in the Visual Studio Code **TERMINAL**, give the terminal focus and press <kbd>Ctrl</kbd>+<kbd>C</kbd>. Choose "Y" in response to the prompt to end the process. Then go to the next step. If the web server is running in a separate window, skip this step and go to the next step. +1. In a command prompt or Visual Studio Code **TERMINAL** in the root of the project, run `npm run stop`. +1. Clear the Office cache following the instructions at [Manually clear the cache](../testing/clear-cache.md#manually-clear-the-cache). +1. Open Teams and select **Apps** from the app bar, then select **Manage your apps** at the bottom of the **Apps** pane. +1. Find your agent in the list of apps. It will have the name specified in the `"name"` property of the declarative agent configuration file; for example, **Excel Add-in + Agent**. +1. Select the arrow head to the left of the name to expand its row. +1. Select the trash can icon near the right end of the row, and then select **Remove** in the prompt. + +Make your changes and then repeat the steps in [Test the agent](#test-the-agent). + +## Troubleshooting + +See [Troubleshooting combined add-ins and agents](../design/agent-and-add-in-overview.md#troubleshooting-combined-agents-and-add-ins). diff --git a/docs/develop/agents-toolkit-overview.md b/docs/develop/agents-toolkit-overview.md new file mode 100644 index 0000000000..f81271229a --- /dev/null +++ b/docs/develop/agents-toolkit-overview.md @@ -0,0 +1,110 @@ +--- +title: Create Office Add-in projects using Microsoft 365 Agents Toolkit +description: Learn how to create Office Add-in projects using Microsoft 365 Agents Toolkit. +ms.date: 08/13/2025 +ms.localizationpriority: high +--- + +# Create Office Add-in projects with Microsoft 365 Agents Toolkit + +A primary tool for developing Microsoft 365 apps and agents, including Office Add-ins, is Microsoft 365 Agents Toolkit. + +Add-ins created with Agents Toolkit use the [unified manifest for Microsoft 365](unified-manifest-overview.md). + + [!INCLUDE [Unified manifest support note for Office applications](../includes/unified-manifest-support-note.md)] + +> [!TIP] +> There's another Visual Studio Code extension that creates Office Add-ins that use the add-in only manifest. See [Create Office Add-in projects using Office Add-ins Development Kit for Visual Studio Code](development-kit-overview.md). + + [!INCLUDE [non-unified manifest clients note](../includes/non-unified-manifest-clients.md)] + +Install the latest version of Agents Toolkit into Visual Studio Code as described in [Install Microsoft 365 Agents Toolkit](/microsoftteams/platform/toolkit/install-teams-toolkit?tabs=vscode). + +> [!IMPORTANT] +> You can create an Outlook add-in with the latest released version of Agents Toolkit. To create an add-in for Excel, PowerPoint, or Word, install the prerelease version as described in [Install a prerelease version](/microsoftteams/platform/toolkit/install-teams-toolkit?tabs=vscode#install-a-prerelease-version). The toolkit creates projects that use the [unified manifest for Microsoft 365](json-manifest-overview.md). Support for this manifest in Excel, PowerPoint, and Word is preview only. + +## Create an Office Add-in project + +1. Open Visual Studio Code and select the Agents Toolkit icon in the **Activity Bar**. + + :::image type="content" source="../images/atk-toolkit-icon.png" alt-text="Agents Toolkit icon."::: + +1. Select **Create a New App**. +1. The **New Project** dropdown menu opens. The options listed will vary depending on your version of Agents Toolkit. Select **Office Add-in**. + + :::image type="content" source="../images/atk-toolkit-new-project-list.png" alt-text="The options in New Project dropdown menu. One option is called 'Office Add-in'."::: + +1. The **App Features Using an Office Add-in** dropdown menu opens. The options listed will vary depending on your version of Agents Toolkit. Select **Task pane**. + + :::image type="content" source="../images/teams-toolkit-create-office-task-pane-capability.png" alt-text="The options in the App Features Using an Office Add-in dropdown menu. The option 'Task pane' is selected."::: + +1. In the **Workspace Folder** dialog that opens, select the folder where you want to create the project. +1. Give a name to the project (with no spaces) when prompted. Agents Toolkit will create the project with basic files and scaffolding. It will then open the project *in a second Visual Studio Code window*. Close the original Visual Studio Code window. + + > [!NOTE] + > The project that's generated is configured to be installable on Excel, Outlook, PowerPoint, and Word. You can edit the manifest and source files as needed to change which Office applications are supported. + +1. In the Visual Studio Code **TERMINAL** navigate to the root of the project and run `npm install`. +1. After the installation completes, verify that you can sideload your add-in from Visual Studio Code. The steps to sideload vary depending on the Office application on which you want to test the add-in. + +### Sideload in Excel, PowerPoint, or Word + +> [!NOTE] +> This section only applies if you are developing the add-in on a *Windows* computer. + +1. Select **View** | **Run** in Visual Studio Code. In the **RUN AND DEBUG** dropdown menu, select one of these options: + + - **Excel Desktop (Edge Chromium)** + - **PowerPoint Desktop (Edge Chromium)** + - **Word Desktop (Edge Chromium)** + +1. Press <kbd>F5</kbd>. The project builds and a Node dev-server window opens. This process may take a couple of minutes. Eventually, the desktop version of the Office application you selected opens. + + > [!NOTE] + > If this is the first time that you have sideloaded an Office Add-in on your computer (or the first time in over a month), you may be prompted to delete an old certificate and/or to install a new one. Agree to both prompts. + +1. A **Contoso Add-in** tab with two buttons will appear on the **Home** ribbon. Use one button to perform an action in the open Office document. Use the other to open the add-in's task pane. + + > [!NOTE] + > Regardless of which button you select, a **WebView Stop On Load** prompt appears. Select **OK**. + + > [!TIP] + > Sideloading in Office on Windows also makes the add-in available in Office on the web, so you can test it on that platform too. After this step is complete, minimize the Office on Windows application window and in a browser, navigate to `https://excel.cloud.microsoft/`, `https://word.cloud.microsoft/`, or `https://powerpoint.cloud.microsoft/`, whichever is appropriate for the add-in you're testing. Open a new or existing document in the Office application on the web. The buttons should appear on the **Home** ribbon just as they do in Office on Windows. + +1. To stop debugging and uninstall the add-in, select **Run** | **Stop Debugging** in Visual Studio Code. + + > [!NOTE] + > If the preceding step seems to have no effect, uninstall the add-in by opening a **TERMINAL** in Visual Studio Code, and then running the command `npm run stop`. Closing the server window doesn't reliably stop the server and closing the Office application doesn't reliably cause Office to unacquire the add-in. + +#### Other ways to sideload + +See [Sideload Office Add-ins that use the unified manifest for Microsoft 365](../testing/sideload-add-in-with-unified-manifest.md) for alternative ways to sideload an Excel, PowerPoint, or Word add-in, including through the app store in Teams. + +### Sideload in Outlook + +> [!NOTE] +> If your development computer is Windows, be sure that your Outlook client is classic Outlook for Windows, not [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627). There is currently a bug that prevents add-ins created with Agents Toolkit from properly sideloading in new Outlook for Windows or in Outlook on the web. + +1. Ensure that your account in your Microsoft 365 developer tenancy is also an email account in desktop Outlook. If it isn't, follow the guidance in [Add an email account to Outlook](https://support.microsoft.com/office/e9da47c4-9b89-4b49-b945-a204aeea6726). +1. **Close Outlook desktop**. +1. In Visual Studio Code, open Agents Toolkit. +1. In the **ACCOUNTS** section, verify that you're signed into Microsoft 365. +1. Select **View** | **Run** in Visual Studio Code. In the **RUN AND DEBUG** dropdown menu, select the option, **Outlook Desktop (Edge Chromium)**, and then press <kbd>F5</kbd>. The project builds and a Node dev-server window opens. This process may take a couple of minutes and then Outlook desktop will open. + + > [!NOTE] + > If this is the first time that you have sideloaded an Office Add-in on your computer (or the first time in over a month), you may be prompted to delete an old certificate and/or to install a new one. Agree to both prompts. + +1. Open the **Inbox** *of your Microsoft 365 account identity* and open any message. A **Contoso Add-in** tab with two buttons will appear on the **Home** ribbon (or the **Message** ribbon, if you have opened the message in its own window). +1. Click the **Show Taskpane** button and a task pane opens. Click the **Perform an action** button and a small notification appears near the top of the message. + + > [!NOTE] + > Regardless of which button you select, a **WebView Stop On Load** prompt appears. Select **OK**. + +1. To stop debugging and uninstall the add-in, select **Run** | **Stop Debugging** in Visual Studio Code. + + > [!NOTE] + > If the preceding step seems to have no effect, uninstall the add-in by opening a **TERMINAL** in Visual Studio Code, and then running the command `npm run stop`. Closing the server window doesn't reliably stop the server and closing the Office application doesn't reliably cause Office to unacquire the add-in. + +## Develop your project + +Now you can change and develop the project. In places where the guidance in the Office Add-ins documentation branches depending on what type of manifest is being used, be sure to follow the guidance for the unified manifest. diff --git a/docs/develop/application-specific-api-model.md b/docs/develop/application-specific-api-model.md index 0985268bc2..e28e7f7605 100644 --- a/docs/develop/application-specific-api-model.md +++ b/docs/develop/application-specific-api-model.md @@ -1,7 +1,7 @@ --- title: Using the application-specific API model description: Learn about the promise-based API model for Excel, OneNote, PowerPoint, Visio, and Word add-ins. -ms.date: 10/20/2023 +ms.date: 02/12/2025 ms.localizationpriority: medium --- @@ -288,9 +288,11 @@ await Excel.run(async (context) => { }); ``` -## Application undo stack +## Undo support -When an application-specific API is processed, the undo stack of the application is cleared. This means that you can't undo changes made prior to any action done by an add-in (unless that add-in only uses Common APIs or doesn't interact with the file). The same is true for changes made by the add-in. +Undo is partially supported by the application-specific Office JavaScript APIs. This means that users may be able to revert changes made by add-ins through the undo command. If a particular API doesn't support undo, the application's undo stack is cleared. This means that you won't be able to undo the effects of that API or anything prior to calling that API. + +API support for undo is continuing to expand but is currently incomplete. We advise against designing your add-in in such a way that it relies on undo support. ## See also diff --git a/docs/develop/asynchronous-programming-in-office-add-ins.md b/docs/develop/asynchronous-programming-in-office-add-ins.md index a3ce49d0d4..3848858bf8 100644 --- a/docs/develop/asynchronous-programming-in-office-add-ins.md +++ b/docs/develop/asynchronous-programming-in-office-add-ins.md @@ -1,7 +1,7 @@ --- title: Asynchronous programming in Office Add-ins description: Learn how the Office JavaScript library uses asynchronous programming in Office Add-ins. -ms.date: 03/21/2023 +ms.date: 12/27/2024 ms.localizationpriority: medium --- @@ -9,29 +9,23 @@ ms.localizationpriority: medium [!include[information about the common API](../includes/alert-common-api-info.md)] -Why does the Office Add-ins API use asynchronous programming? Because JavaScript is a single-threaded language, if script invokes a long-running synchronous process, all subsequent script execution will be blocked until that process completes. Because certain operations against Office web clients (but desktop clients as well) could block execution if they are run synchronously, most of the Office JavaScript APIs are designed to execute asynchronously. This makes sure that Office Add-ins are responsive and fast. It also frequently requires you to write callback functions when working with these asynchronous methods. +Why does the Office Add-ins API use asynchronous programming? JavaScript is a single-threaded language. If a script invokes a long-running synchronous process of the Office client, all subsequent scripts are blocked until that process completes. Being asynchronous makes sure that Office Add-ins are responsive and fast. -The names of all asynchronous methods in the API end with "Async", such as the `Document.getSelectedDataAsync`, `Binding.getDataAsync`, or `Item.loadCustomPropertiesAsync` methods. When an "Async" method is called, it executes immediately and any subsequent script execution can continue. The optional callback function you pass to an "Async" method executes as soon as the data or requested operation is ready. This generally occurs promptly, but there can be a slight delay before it returns. +The names of all asynchronous methods in the Common APIs end with "Async", such as the `Document.getSelectedDataAsync`, `Binding.getDataAsync`, or `Item.loadCustomPropertiesAsync` methods. When an "Async" method is called, it runs immediately. The rest of the script continues while the operation completes on the client-side. The optional callback function that you pass to an "Async" method runs as soon as the data or requested operation is ready. This generally occurs promptly, but there can be a slight delay. -The following diagram shows the flow of execution for a call to an "Async" method that reads the data the user selected in a document open in the server-based Word or Excel. At the point when the "Async" call is made, the JavaScript execution thread is free to perform any additional client-side processing (although none are shown in the diagram). When the "Async" method returns, the callback resumes execution on the thread, and the add-in can the access data, do something with it, and display the result. The same asynchronous execution pattern holds when working with Office client applications on Windows or on Mac. +The following diagram shows the flow of an "Async" method that reads the data the user selected in a document. When the "Async" call is made, the JavaScript thread is free to perform any additional client-side processing (although none is shown in the diagram). When the "Async" method returns, the callback resumes on the thread. The add-in can then access data, do something with it, and display the result. The pattern is the same across platforms. -![Diagram showing the command execution interaction over time with the user, the add-in page, and the web app server hosting the add-in.](../images/office-addins-asynchronous-programming-flow.png) - -Support for this asynchronous design in both rich and web clients is part of the "write once-run cross-platform" design goals of the Office Add-ins development model. For example, you can create a content or task pane add-in with a single code base that will run in both Excel on Windows and Excel on the web. +![Diagram showing the command execution interaction over time with the user, the add-in page, and the web app server that hosts the add-in.](../images/office-addins-asynchronous-programming-flow.png) ## Write the callback function for an "Async" method -The callback function you pass as the *callback* argument to an "Async" method must declare a single parameter that the add-in runtime will use to provide access to an [AsyncResult](/javascript/api/office/office.asyncresult) object when the callback function executes. You can write: - -- An anonymous function that must be written and passed directly in line with the call to the "Async" method as the *callback* parameter of the "Async" method. +The callback function you pass as the *callback* argument to an "Async" method must declare a single parameter. The add-in runtime uses that parameter to provide access to an [AsyncResult](/javascript/api/office/office.asyncresult) object for the callback function. -- A named function, passing the name of that function as the *callback* parameter of an "Async" method. - -An anonymous function is useful if you are only going to use its code once - because it has no name, you can't reference it in another part of your code. A named function is useful if you want to reuse the callback function for more than one "Async" method. +The callback function can either be an anonymous function or a named function. An anonymous function is useful if you are only going to use its code once - because it has no name, you can't reference it in another part of your code. A named function is useful if you want to reuse the callback function for more than one "Async" method. ### Write an anonymous callback function -The following anonymous callback function declares a single parameter named `result` that retrieves data from the [AsyncResult.value](/javascript/api/office/office.asyncresult#office-office-asyncresult-value-member) property when the callback returns. +The following anonymous callback function declares a single parameter named `result` for the data returned by the client. It retrieves and writes that data from the [AsyncResult.value](/javascript/api/office/office.asyncresult#office-office-asyncresult-value-member) property when the callback returns. ```js function (result) { @@ -39,11 +33,11 @@ function (result) { } ``` -The following example shows how to pass this anonymous callback function in line in the context of a full "Async" method call to the `Document.getSelectedDataAsync` method. +The following example shows this anonymous callback function in the context of a full "Async" method call to the `Document.getSelectedDataAsync(coercionType, callback)` method. - The first *coercionType* argument, `Office.CoercionType.Text`, specifies to return the selected data as a string of text. -- The second *callback* argument is the anonymous function passed in-line to the method. When the function executes, it uses the *result* parameter to access the `value` property of the `AsyncResult` object to display the data selected by the user in the document. +- The second *callback* argument is the anonymous function passed inline to the method. When the function runs, it uses the *result* parameter to access the `value` property of the `AsyncResult` object. It then displays the data selected by the user in the document. ```js Office.context.document.getSelectedDataAsync(Office.CoercionType.Text, @@ -58,13 +52,13 @@ function write(message){ } ``` -You can also use the parameter of your callback function to access other properties of the `AsyncResult` object. Use the [AsyncResult.status](/javascript/api/office/office.asyncresult#office-office-asyncresult-status-member) property to determine if the call succeeded or failed. If your call fails you can use the [AsyncResult.error](/javascript/api/office/office.asyncresult#office-office-asyncresult-error-member) property to access an [Error](/javascript/api/office/office.error) object for error information. +You can also use the parameter of your callback function to access other properties of the `AsyncResult` object. Use the [AsyncResult.status](/javascript/api/office/office.asyncresult#office-office-asyncresult-status-member) property to determine if the call succeeded or failed. If your call failed, use the [AsyncResult.error](/javascript/api/office/office.asyncresult#office-office-asyncresult-error-member) property to access an [Error](/javascript/api/office/office.error) object to help decide what to do. -For more information about using the `getSelectedDataAsync` method, see [Read and write data to the active selection in a document or spreadsheet](read-and-write-data-to-the-active-selection-in-a-document-or-spreadsheet.md). +For more information on the `getSelectedDataAsync` method, see [Read and write data to the active selection in a document or spreadsheet](read-and-write-data-to-the-active-selection-in-a-document-or-spreadsheet.md). ### Write a named callback function -Alternatively, you can write a named function and pass its name to the *callback* parameter of an "Async" method. For example, the previous example can be rewritten to pass a function named `writeDataCallback` as the *callback* parameter like this. +Alternatively, you can write a named function and pass its name to the *callback* parameter of an "Async" method. Here, the previous example is rewritten to pass a function named `writeDataCallback` as the *callback* parameter. ```js Office.context.document.getSelectedDataAsync(Office.CoercionType.Text, @@ -81,29 +75,25 @@ function write(message){ } ``` -## Differences in what's returned to the AsyncResult.value property +## Differences in what's returned to the `AsyncResult.value` property -The `asyncContext`, `status`, and `error` properties of the `AsyncResult` object return the same kinds of information to the callback function passed to all "Async" methods. However, what's returned to the `AsyncResult.value` property varies depending on the functionality of the "Async" method. +The `asyncContext`, `status`, and `error` properties of the `AsyncResult` object return the same kinds of information to the callback functions passed to all "Async" methods. However, what's returned to the `AsyncResult.value` property varies depending on the functionality of the "Async" method. -For example, the `addHandlerAsync` methods (of the [Binding](/javascript/api/office/office.binding), [CustomXmlPart](/javascript/api/office/office.customxmlpart), [Document](/javascript/api/office/office.document), [RoamingSettings](/javascript/api/outlook/office.roamingsettings), and [Settings](/javascript/api/office/office.settings) objects) are used to add event handler functions to the items represented by these objects. You can access the `AsyncResult.value` property from the callback function you pass to any of the `addHandlerAsync` methods, but since no data or object is being accessed when you add an event handler, the `value` property always returns **undefined** if you attempt to access it. +For example, the `addHandlerAsync` methods (of the [Binding](/javascript/api/office/office.binding), [CustomXmlPart](/javascript/api/office/office.customxmlpart), [Document](/javascript/api/office/office.document), [RoamingSettings](/javascript/api/outlook/office.roamingsettings), and [Settings](/javascript/api/office/office.settings) objects) are used to add event handler functions. The `AsyncResult.value` property in those callback functions always returns **undefined**, since no data or object is accessed when you add an event handler. -On the other hand, if you call the `Document.getSelectedDataAsync` method, it returns the data the user selected in the document to the `AsyncResult.value` property in the callback. Or, if you call the [Bindings.getAllAsync](/javascript/api/office/office.bindings#office-office-bindings-getallasync-member(1)) method, it returns an array of all of the `Binding` objects in the document. And, if you call the [Bindings.getByIdAsync](/javascript/api/office/office.bindings#office-office-bindings-getbyidasync-member(1)) method, it returns a single `Binding` object. +On the other hand, if you call the `Document.getSelectedDataAsync` method, it returns the data the user selected in the document as the `AsyncResult.value` property in the callback. Or, if you call the [Bindings.getAllAsync](/javascript/api/office/office.bindings#office-office-bindings-getallasync-member(1)) method, it returns an array of all of the `Binding` objects in the document. -For a description of what's returned to the `AsyncResult.value` property for an `Async` method, see the "Callback value" section of that method's reference topic. For a summary of all of the objects that provide `Async` methods, see the table at the bottom of the [AsyncResult](/javascript/api/office/office.asyncresult) object topic. +For a description of what's returned to the `AsyncResult.value` property for an `Async` method, see the **`callback`** section of that method's reference topic. ## Asynchronous programming patterns -The Office JavaScript API supports two kinds of asynchronous programming patterns. - -- Using nested callbacks -- Using the promises pattern +The Common APIs in the Office JavaScript API support two kinds of asynchronous programming patterns. -Asynchronous programming with callback functions frequently requires you to nest the returned result of one callback within two or more callbacks. If you need to do so, you can use nested callbacks from all "Async" methods of the API. - -Using nested callbacks is a programming pattern familiar to most JavaScript developers, but code with deeply nested callbacks can be difficult to read and understand. As an alternative to nested callbacks, the Office JavaScript API also supports an implementation of the promises pattern. +- Nested callbacks +- Promises > [!NOTE] -> In the current version of the Office JavaScript API, *built-in* support for the promises pattern only works with code for [bindings in Excel spreadsheets and Word documents](bind-to-regions-in-a-document-or-spreadsheet.md). However, you can wrap other functions that have callbacks inside your own custom Promise-returning function. For more information, see [Wrap Common APIs in Promise-returning functions](#wrap-common-apis-in-promise-returning-functions). +> In the current version of the Office JavaScript API, *built-in* support for the promises pattern only works with code for [bindings in Excel spreadsheets and Word documents](bind-to-regions-in-a-document-or-spreadsheet.md). However, you can wrap other functions that have callbacks inside your own custom `Promise`-returning function. For more information, see [Wrap Common APIs in Promise-returning functions](#wrap-common-apis-in-promise-returning-functions). ### Asynchronous programming using nested callback functions @@ -130,69 +120,26 @@ function write(message){ } ``` -This basic nested callback pattern can be used for all asynchronous methods in the Office JavaScript API. - -The following sections show how to use either anonymous or named functions for nested callbacks in asynchronous methods. - -#### Use anonymous functions for nested callbacks - -In the following example, two anonymous functions are declared inline and passed into the `getByIdAsync` and `getDataAsync` methods as nested callbacks. Because the functions are simple and inline, the intent of the implementation is immediately clear. - -```js -Office.context.document.bindings.getByIdAsync('myBinding', function (bindingResult) { - bindingResult.value.getDataAsync(function (getResult) { - if (getResult.status == Office.AsyncResultStatus.Failed) { - write('Action failed. Error: ' + asyncResult.error.message); - } else { - write('Data has been read successfully.'); - } - }); -}); - -// Function that writes to a div with id='message' on the page. -function write(message){ - document.getElementById('message').innerText += message; -} -``` - -#### Use named functions for nested callbacks - -In complex implementations, it may be helpful to use named functions to make your code easier to read, maintain, and reuse. In the following example, the two anonymous functions from the example in the previous section have been rewritten as functions named `deleteAllData` and `showResult`. These named functions are then passed into the `getByIdAsync` and `deleteAllDataValuesAsync` methods as callbacks by name. - -```js -Office.context.document.bindings.getByIdAsync('myBinding', deleteAllData); - -function deleteAllData(asyncResult) { - asyncResult.value.deleteAllDataValuesAsync(showResult); -} - -function showResult(asyncResult) { - if (asyncResult.status == Office.AsyncResultStatus.Failed) { - write('Action failed. Error: ' + asyncResult.error.message); - } else { - write('Data has been deleted successfully.'); - } -} - -// Function that writes to a div with id='message' on the page. -function write(message){ - document.getElementById('message').innerText += message; -} -``` +This basic nested callback pattern can be used for all asynchronous methods in the Common APIs. ### Asynchronous programming using the promises pattern to access data in bindings -Instead of passing a callback function and waiting for the function to return before execution continues, the promises programming pattern immediately returns a promise object that represents its intended result. However, unlike true synchronous programming, under the covers the fulfillment of the promised result is actually deferred until the Office Add-ins runtime environment can complete the request. An *onError* handler is provided to cover situations when the request can't be fulfilled. +Instead of passing a callback function and waiting for the function to return before the script continues, the promises programming pattern immediately returns a `Promise` object that represents its intended result. However, unlike true synchronous programming, under the covers the fulfillment of the promised result is actually deferred until the Office Add-ins runtime environment completes the request. An *onError* handler is provided to cover situations when the request can't be fulfilled. + +The Common APIs provide the [Office.select](/javascript/api/office#Office_select_expression__callback_) function to support the promises pattern when working with existing binding objects. The promise object returned to the `Office.select` function only supports the four methods directly accessible from the [Binding](/javascript/api/office/office.binding) object. -The Office JavaScript API provides the [Office.select](/javascript/api/office#Office_select_expression__callback_) function to support the promises pattern for working with existing binding objects. The promise object returned to the `Office.select` function supports only the four methods that you can access directly from the [Binding](/javascript/api/office/office.binding) object: [getDataAsync](/javascript/api/office/office.binding#office-office-binding-getdataasync-member(1)), [setDataAsync](/javascript/api/office/office.binding#office-office-binding-setdataasync-member(1)), [addHandlerAsync](/javascript/api/office/office.binding#office-office-binding-addhandlerasync-member(1)), and [removeHandlerAsync](/javascript/api/office/office.binding#office-office-binding-removehandlerasync-member(1)). +- [getDataAsync](/javascript/api/office/office.binding#office-office-binding-getdataasync-member(1)) +- [setDataAsync](/javascript/api/office/office.binding#office-office-binding-setdataasync-member(1)) +- [addHandlerAsync](/javascript/api/office/office.binding#office-office-binding-addhandlerasync-member(1)) +- [removeHandlerAsync](/javascript/api/office/office.binding#office-office-binding-removehandlerasync-member(1)) The promises pattern for working with bindings takes this form. -**Office.select(**_selectorExpression_, _onError_**).**_BindingObjectAsyncMethod_ +`Office.select(`*selectorExpression*`,` *onError*`).`*BindingObjectAsyncMethod*`;` -The *selectorExpression* parameter takes the form `"bindings#bindingId"`, where *bindingId* is the name ( `id`) of a binding that you created previously in the document or spreadsheet (using one of the "addFrom" methods of the `Bindings` collection: `addFromNamedItemAsync`, `addFromPromptAsync`, or `addFromSelectionAsync`). For example, the selector expression `bindings#cities` specifies that you want to access the binding with an **id** of 'cities'. +The *selectorExpression* parameter takes the form `"bindings#bindingId"`, where *bindingId* is the name ( `id`) of a binding that you created in the document or spreadsheet (using one of the "addFrom" methods of the `Bindings` collection: `addFromNamedItemAsync`, `addFromPromptAsync`, or `addFromSelectionAsync`). The example *selectorExpression* of `bindings#cities` specifies that you want to access the binding with an **id** of 'cities'. -The *onError* parameter is an error handling function which takes a single parameter of type `AsyncResult` that can be used to access an `Error` object, if the `select` function fails to access the specified binding. The following example shows a basic error handler function that can be passed to the *onError* parameter. +The *onError* parameter is an error handling function which takes a single parameter of type `AsyncResult`. This is used to access an `Error` object if the `select` function fails to access the specified binding. The following example shows a basic error handler function that can be passed to the *onError* parameter. ```js function onError(result){ @@ -206,11 +153,11 @@ function write(message){ } ``` -Replace the *BindingObjectAsyncMethod* placeholder with a call to any of the four `Binding` object methods supported by the promise object: `getDataAsync`, `setDataAsync`, `addHandlerAsync`, or `removeHandlerAsync`. Calls to these methods don't support additional promises. You must call them using the [nested callback function pattern](#asynchronous-programming-using-nested-callback-functions). +Replace the *BindingObjectAsyncMethod* placeholder with a call to any of the four `Binding` object methods supported by the promise object: `getDataAsync`, `setDataAsync`, `addHandlerAsync`, or `removeHandlerAsync`. Calls to these methods don't support additional promises. In that case, you must use the [nested callback function pattern](#asynchronous-programming-using-nested-callback-functions). -After a `Binding` object promise is fulfilled, it can be reused in the chained method call as if it were a binding (the add-in runtime won't asynchronously retry fulfilling the promise). If the `Binding` object promise can't be fulfilled, the add-in runtime will try again to access the binding object the next time one of its asynchronous methods is invoked. +After a `Binding` object promise is fulfilled, it can be reused in the chained method call as if it were a binding. If it's successful, the add-in runtime won't asynchronously retry fulfilling the promise. If the `Binding` object promise can't be fulfilled, the add-in runtime will try again to access the binding object the next time one of its asynchronous methods is invoked. -The following code example uses the `select` function to retrieve a binding with the `id` "`cities`" from the `Bindings` collection, and then calls the [addHandlerAsync](/javascript/api/office/office.binding#office-office-binding-addhandlerasync-member(1)) method to add an event handler for the [dataChanged](/javascript/api/office/office.bindingdatachangedeventargs) event of the binding. +The following example uses the `select` function to retrieve a binding with the `id` "`cities`" from the `Bindings` collection, and then calls the [addHandlerAsync](/javascript/api/office/office.binding#office-office-binding-addhandlerasync-member(1)) method to add an event handler for the [dataChanged](/javascript/api/office/office.bindingdatachangedeventargs) event of the binding. ```js function addBindingDataChangedEventHandler() { @@ -223,30 +170,19 @@ function addBindingDataChangedEventHandler() { ``` > [!IMPORTANT] -> The `Binding` object promise returned by the `Office.select` function provides access to only the four methods of the `Binding` object. If you need to access any of the other members of the `Binding` object, instead you must use the `Document.bindings` property and `Bindings.getByIdAsync` or `Bindings.getAllAsync` methods to retrieve the `Binding` object. For example, if you need to access any of the `Binding` object's properties (the `document`, `id`, or `type` properties), or need to access the properties of the [MatrixBinding](/javascript/api/office/office.matrixbinding) or [TableBinding](/javascript/api/office/office.tablebinding) objects, you must use the `getByIdAsync` or `getAllAsync` methods to retrieve a `Binding` object. +> The `Binding` object promise returned by the `Office.select` function provides access to only the four methods of the `Binding` object. If you need to access any of the other members of the `Binding` object, instead you must use the `Document.bindings` property and `Bindings.getByIdAsync` or `Bindings.getAllAsync` methods to retrieve the `Binding` object. ## Pass optional parameters to asynchronous methods The common syntax for all "Async" methods follows this pattern. - *AsyncMethod* `(` *RequiredParameters* `, [` *OptionalParameters* `],` *CallbackFunction* `);` - -All asynchronous methods support optional parameters, which are passed in as a JavaScript object that contains one or more optional parameters. The object containing the optional parameters is an unordered collection of key-value pairs with the ":" character separating the key and the value. Each pair in the object is comma-separated, and the entire set of pairs is enclosed in braces. The key is the parameter name, and value is the value to pass for that parameter. + *asyncMethod* `(` *requiredParameters* `, [` *optionalParameters* `],` *callbackFunction* `);` -You can create the object that contains optional parameters inline, or by creating an `options` object and passing that in as the *options* parameter. +All asynchronous methods support optional parameters. These are passed in as a JavaScript object. The object that contains the optional parameters is an *unordered* collection of key-value pairs. You can create the object that contains optional parameters inline, or by creating an `options` object and passing that in as the *options* parameter. ### Pass optional parameters inline -For example, the syntax for calling the [Document.setSelectedDataAsync](/javascript/api/office/office.document#office-office-document-setselecteddataasync-member(1)) method with optional parameters inline looks like this: - -```js - Office.context.document.setSelectedDataAsync(data, {coercionType: 'coercionType', asyncContext: 'asyncContext'},callback); - -``` - -In this form of the calling syntax, the two optional parameters, *coercionType* and *asyncContext*, are defined as an anonymous JavaScript object inline enclosed in braces. - -The following example shows how to call to the `Document.setSelectedDataAsync` method by specifying optional parameters inline. +Here is an example of the [Document.setSelectedDataAsync](/javascript/api/office/office.document#office-office-document-setselecteddataasync-member(1)) method with optional parameters defined inline. The two optional parameters, *coercionType* and *asyncContext*, are defined as an anonymous JavaScript object. ```js Office.context.document.setSelectedDataAsync( @@ -263,14 +199,9 @@ function write(message){ } ``` -> [!NOTE] -> You can specify optional parameters in any order in the parameter object as long as their names are specified correctly. +### Pass optional parameters in a named object -### Pass optional parameters in an options object - -Alternatively, you can create an object named `options` that specifies the optional parameters separately from the method call, and then pass the `options` object as the *options* argument. - -The following example shows one way of creating the `options` object, where `parameter1`, `value1`, and so on, are placeholders for the actual parameter names and values. +Alternatively, you can create a named object that specifies the optional parameters separately from the method call and then pass the object as the *options* argument. The following example shows one way of creating an `options` object, where `parameter1`, `value1`, and so on, are placeholders for the actual parameter names and values. ```js const options = { @@ -308,9 +239,6 @@ options["ValueFormat"] = "unformatted"; options["FilterType"] = "all"; ``` -> [!NOTE] -> When using either method of creating the `options` object, you can specify optional parameters in any order as long as their names are specified correctly. - The following example shows how to call to the `Document.setSelectedDataAsync` method by specifying optional parameters in an `options` object. ```js @@ -335,9 +263,9 @@ function write(message){ In both optional parameter examples, the *callback* parameter is specified as the last parameter (following the inline optional parameters, or following the *options* argument object). Alternatively, you can specify the *callback* parameter inside either the inline JavaScript object, or in the `options` object. However, you can pass the *callback* parameter in only one location: either in the `options` object (inline or created externally), or as the last parameter, but not both. -## Wrap Common APIs in Promise-returning functions +## Wrap Common APIs in `Promise`-returning functions -The Common API (and Outlook API) methods do not return [Promises](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise). Therefore, you cannot use [await](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/await) to pause the execution until the asynchronous operation completes. If you need `await` behavior, you can wrap the method call in an explicitly created Promise. +The Common API (and Outlook API) methods do not return [Promises](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise). Therefore, you cannot use [await](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/await) to pause the execution until the asynchronous operation completes. If you need `await` behavior, wrap the method call in an explicitly created `Promise`. The basic pattern is to create an asynchronous method that returns a Promise object immediately and *resolves* that Promise object when the inner method completes, or *rejects* the object if the method fails. The following is a simple example. @@ -361,32 +289,6 @@ When this function needs to be awaited, it can be either called with the `await` > [!NOTE] > This technique is especially useful when you need to call a Common API inside a call of the `run` function in an application-specific object model. For an example of the `getDocumentFilePath` function being used in this way, see the file [Home.js in the sample Word-Add-in-JavaScript-MDConversion](https://github.com/OfficeDev/Word-Add-in-MarkdownConversion/blob/master/Word-Add-in-JavaScript-MDConversionWeb/Home.js). -The following is an example using TypeScript. - -```typescript -readDocumentFileAsync(): Promise<any> { - return new Promise((resolve, reject) => { - const chunkSize = 65536; - const self = this; - - Office.context.document.getFileAsync(Office.FileType.Compressed, { sliceSize: chunkSize }, (asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - reject(asyncResult.error); - } else { - // `getAllSlices` is a Promise-wrapped implementation of File.getSliceAsync. - self.getAllSlices(asyncResult.value).then(result => { - if (result.IsSuccess) { - resolve(result.Data); - } else { - reject(asyncResult.error); - } - }); - } - }); - }); -} -``` - ## See also - [Understanding the Office JavaScript API](understanding-the-javascript-api-for-office.md) diff --git a/docs/develop/auth-save-passwords.md b/docs/develop/auth-save-passwords.md new file mode 100644 index 0000000000..c047041487 --- /dev/null +++ b/docs/develop/auth-save-passwords.md @@ -0,0 +1,57 @@ +--- +title: Automatically save passwords in Microsoft Edge WebView2 +description: Learn how to enable WebView2 to save passwords when users sign in using your add-in. +ms.localizationpriority: medium +ms.date: 03/10/2025 +--- + +# Enable automatic password saving in Microsoft Edge WebView2 + +Most browsers can automatically save passwords on behalf of the user when they sign in. This helps users manage passwords in a secure environment. Microsoft Edge WebView2 also supports automatic password saving. When your add-in is loaded in Microsoft Office on Windows, Webview2 hosts your add-in. To enable automatic password saving, add HTML input controls for the username and password, as shown in the following HTML. + +```html +<div> + <label for="username">Username:</label><br/> + <input type="text" id="username" name="username" /><br/> + + <label for="password">Password:</label><br/> + <input type="password" id="password" name="password" /><br/> + + <button id="btn" type="button">Sign in</button> +</div> +``` + +In the button click event handler for the sign-in button, call the authentication library of your choice to sign in the user. Once the sign-in is complete, redirect to a new web page. When WebView2 sees the redirect, and the username and password, it prompts the user to offer to automatically save the credentials. The following code shows how to handle the sign-in button click event. + +```javascript +async function btnSignIn() { + // Get the username and password credentials entered by the user. + const username = document.getElementById("username").value; + const pwd = document.getElementById("password").value; + + try { + // Sign in the user. This is a placeholder for the actual sign-in logic. + await signInUser(username, pwd); + + // Redirect to a success page to trigger the password autosave. + window.location.href = "/home.html"; + } + catch (error) { + console.error("Sign in failed: " + error); + return; + } +} +``` + +## How the user manages passwords + +When the user enters a new password in your add-in, and your add-in redirects to a new web page, WebView2 asks the user if they want to save their username and password. The next time your add-in prompts for credentials, WebView2 automatically enters the user's account information. + +:::image type="content" source="../images/edge-webview2-automatic-save-passwords.png" alt-text="The dialog from WebView2 prompting the user if they want to save their username and password."::: + +Users remove saved passwords by deleting The WebView2 local cache folder at `%LOCALAPPDATA%\Microsoft\Office\16.0\Wef\webview2\`. If your add-in relies on automatically saving passwords, you should document this folder location so users can remove their passwords. + +## Related content + +- [Microsoft Edge WebView2](https://developer.microsoft.com/microsoft-edge/webview2) +- [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md) diff --git a/docs/develop/authorize-to-microsoft-graph.md b/docs/develop/authorize-to-microsoft-graph.md index 6e028d4699..e800982b18 100644 --- a/docs/develop/authorize-to-microsoft-graph.md +++ b/docs/develop/authorize-to-microsoft-graph.md @@ -1,7 +1,7 @@ ---- +--- title: Authorize to Microsoft Graph with SSO description: Learn how users of an Office Add-in can use single sign-on (SSO) to fetch data from Microsoft Graph. -ms.date: 01/22/2024 +ms.date: 08/13/2025 ms.localizationpriority: medium --- @@ -13,7 +13,7 @@ Users sign in to Office using either their personal Microsoft account or their M In addition to hosting the pages and JavaScript of the web application, the add-in must also host, at the same [fully qualified domain name](/windows/desktop/DNS/f-gly#_dns_fully_qualified_domain_name_fqdn__gly), one or more web APIs that will get an access token to Microsoft Graph and make requests to it. -The add-in manifest contains a **\<WebApplicationInfo\>** element that provides important Azure app registration information to Office, including the permissions to Microsoft Graph that the add-in requires. +The add-in manifest contains a `<WebApplicationInfo>` element that provides important Azure app registration information to Office, including the permissions to Microsoft Graph that the add-in requires. ### How it works at runtime @@ -54,18 +54,18 @@ For examples of detailed walkthroughs and scenarios, see: * [Create an ASP.NET Office Add-in that uses single sign-on](create-sso-office-add-ins-aspnet.md) * [Scenario: Implement single sign-on to your service in an Outlook add-in](../outlook/implement-sso-in-outlook-add-in.md) -## Distributing SSO-enabled add-ins in Microsoft AppSource +## Distributing SSO-enabled add-ins in Microsoft Marketplace -When a Microsoft 365 admin acquires an add-in from [AppSource](https://appsource.microsoft.com), the admin can redistribute it through [Integrated Apps](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps) and grant admin consent to the add-in to access Microsoft Graph scopes. It's also possible, however, for the end user to acquire the add-in directly from AppSource, in which case the user must grant consent to the add-in. This can create a potential performance problem for which we've provided a solution. +When a Microsoft 365 admin acquires an add-in from [Microsoft Marketplace](https://marketplace.microsoft.com), the admin can redistribute it through the [integrated apps portal](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps) and grant admin consent to the add-in to access Microsoft Graph scopes. It's also possible, however, for the end user to acquire the add-in directly from Microsoft Marketplace, in which case the user must grant consent to the add-in. This can create a potential performance problem for which we've provided a solution. If your code passes the `allowConsentPrompt` option in the call of `getAccessToken`, like `OfficeRuntime.auth.getAccessToken( { allowConsentPrompt: true } );`, then Office can prompt the user for consent if the Microsoft identity platform reports to Office that consent has not yet been granted to the add-in. However, for security reasons, Office can only prompt the user to consent to the Microsoft Graph `profile` scope. *Office cannot prompt for consent to other Microsoft Graph scopes*, not even `User.Read`. This means that if the user grants consent on the prompt, Office returns an access token. But the attempt to exchange the access token for a new access token with additional Microsoft Graph scopes fails with error AADSTS65001, which means consent (to Microsoft Graph scopes) has not been granted. > [!NOTE] -> The request for consent with `{ allowConsentPrompt: true }` could still fail even for the `profile` scope if the administrator has turned off end-user consent. For more information, see [Configure how end-users consent to applications using Azure Active Directory](/azure/active-directory/manage-apps/configure-user-consent). +> The request for consent with `{ allowConsentPrompt: true }` could still fail even for the `profile` scope if the administrator has turned off end-user consent. For more information, see [Configure how end-users consent to applications](/entra/identity/enterprise-apps/configure-user-consent). Your code can, and should, handle this error by falling back to an alternate system of authentication, which prompts the user for consent to Microsoft Graph scopes. For code examples, see [Create a Node.js Office Add-in that uses single sign-on](create-sso-office-add-ins-nodejs.md) and [Create an ASP.NET Office Add-in that uses single sign-on](create-sso-office-add-ins-aspnet.md) and the samples they link to. The entire process requires multiple round trips to the Microsoft identity platform. To avoid this performance penalty, include the `forMSGraphAccess` option in the call of `getAccessToken`; for example, `OfficeRuntime.auth.getAccessToken( { forMSGraphAccess: true } )`. This signals to Office that your add-in needs Microsoft Graph scopes. Office will ask the Microsoft identity platform to verify that consent to Microsoft Graph scopes has already been granted to the add-in. If it has, the access token is returned. If it hasn't, then the call of `getAccessToken` returns error 13012. Your code can handle this error by falling back to an alternate system of authentication immediately, without making a doomed attempt to exchange tokens with the Microsoft identity platform. -As a best practice, always pass `forMSGraphAccess` to `getAccessToken` when your add-in will be distributed in AppSource and needs Microsoft Graph scopes. +As a best practice, always pass `forMSGraphAccess` to `getAccessToken` when your add-in will be distributed in Microsoft Marketplace and needs Microsoft Graph scopes. ## Details on SSO with an Outlook add-in diff --git a/docs/develop/automatically-open-a-task-pane-with-a-document.md b/docs/develop/automatically-open-a-task-pane-with-a-document.md index 9424e8ee10..60180d248e 100644 --- a/docs/develop/automatically-open-a-task-pane-with-a-document.md +++ b/docs/develop/automatically-open-a-task-pane-with-a-document.md @@ -1,8 +1,8 @@ ---- +--- title: Automatically open a task pane with a document description: Learn how to configure an Office Add-in to open automatically when a document opens. ms.topic: how-to -ms.date: 05/05/2023 +ms.date: 09/22/2025 ms.localizationpriority: medium --- @@ -28,7 +28,7 @@ The autoopen feature is currently supported in the following products and platfo |Products|Platforms| |:-----------|:------------| -|<ul><li>Word</li><li>Excel</li><li>PowerPoint</li></ul>|Supported platforms for all supported products:<ul><li>Office on the web</li><li>Office on Windows (Build 16.0.8121.1000 or later)</li><li>Office on Mac (Build 15.34.17051500 or later)</li></ul>| +|<ul><li>Word</li><li>Excel</li><li>PowerPoint</li></ul>|Supported platforms for all supported products:<ul><li>Office on the web</li><li>Office on Windows (Version 1705 (Build 8121.1000) or later)</li><li>Office on Mac (Version 15.34 (17051500) or later)</li></ul>| ## Best practices @@ -42,7 +42,7 @@ Apply the following best practices when you use the autoopen feature. - Don't use the autoopen feature to artificially increase usage of your add-in. If it doesn't make sense for your add-in to open automatically with certain documents, this feature can annoy users. > [!NOTE] - > If Microsoft detects abuse of the autoopen feature, your add-in might be rejected from AppSource. + > If Microsoft detects abuse of the autoopen feature, your add-in might be rejected from Microsoft Marketplace. - Don't use this feature to pin multiple task panes. You can only set one pane of your add-in to open automatically with a document. @@ -56,9 +56,39 @@ Apply the following best practices when you use the autoopen feature. ### Step 1: Specify the task pane to open +Configure the manifest to specify the task pane page that should open automatically. The process depends on what type of manifest the add-in uses. + +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) + +[!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] + +To specify the task pane to open automatically, find the runtime object in the [`"runtimes"`](/microsoft-365/extensibility/schema/element-extensions#runtimes) array whose [`"code.page"`](/microsoft-365/extensibility/schema/extension-runtime-code#page) property is set to the URL of the page that you want to open automatically. Ensure that the [`"actions"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item) array in this same runtime object has at least one action whose `"type"` value is `"openPage"`. Add a `"view"` property to this action object and set it to `"Office.AutoShowTaskpaneWithDocument"`. You can only set this value on one action object and it must be an action of type `"openPage"`. If you set this value on multiple actions, the first occurrence of the value will be recognized and the others will be ignored. + +The following example shows a `"view"` value set to `"Office.AutoShowTaskpaneWithDocument"`. + +```json +"runtimes": [ + { + ... + "code": { + "page": "https://contoso.com/taskpane.html" + }, + "actions": [ + { + "id": "ShowTaskPane", + "type": "openPage", + "view": "Office.AutoShowTaskpaneWithDocument" + } + ] + } +] +``` + +# [Add-in only manifest](#tab/xmlmanifest) + To specify the task pane to open automatically, set the [TaskpaneId](/javascript/api/manifest/action#taskpaneid) value to **Office.AutoShowTaskpaneWithDocument**. You can only set this value on one task pane. If you set this value on multiple task panes, the first occurrence of the value will be recognized and the others will be ignored. -The following example shows the TaskPaneId value set to Office.AutoShowTaskpaneWithDocument. +The following example shows the `<TaskPaneId>` value set to **Office.AutoShowTaskpaneWithDocument**. ```xml <Action xsi:type="ShowTaskpane"> @@ -67,6 +97,8 @@ The following example shows the TaskPaneId value set to Office.AutoShowTaskpaneW </Action> ``` +--- + ### Step 2: Tag the document to automatically open the task pane You can tag the document to trigger the autoopen feature in one of two ways. Pick the alternative that works best for your scenario. @@ -95,7 +127,7 @@ The following example shows how to add the `webextension` part. ```xml <we:webextension xmlns:we="http://schemas.microsoft.com/office/webextensions/webextension/2010/11" id="[ADD-IN ID PER MANIFEST]"> - <we:reference id="[GUID or AppSource asset ID]" version="[your add-in version]" store="[Pointer to store or catalog]" storeType="[Store or catalog type]"/> + <we:reference id="[GUID or Microsoft Marketplace asset ID]" version="[your add-in version]" store="[Pointer to store or catalog]" storeType="[Store or catalog type]"/> <we:alternateReferences/> <we:properties> <we:property name="Office.AutoShowTaskpaneWithDocument" value="true"/> @@ -111,14 +143,14 @@ The `webextension` part also includes a reference to the store or catalog with a |`storeType` value|`id` value|`store` value|`version` value| |:---------------|:---------------|:---------------|:---------------| -|OMEX (AppSource)|The AppSource asset ID of the add-in (see Note).|The locale of AppSource; for example, "en-us".|The version in the AppSource catalog (see Note).| -|WOPICatalog (partner [WOPI](/microsoft-365/cloud-storage-partner-program/online/) hosts)| The AppSource asset ID of the add-in (see Note). | "wopicatalog". Use this value for add-ins that are published in App Source and are installed in WOPI hosts. For more information, see [Integrating with Office Online](/microsoft-365/cloud-storage-partner-program/online/overview). | The version in the add-in manifest.| +|OMEX (Microsoft Marketplace)|The Microsoft Marketplace asset ID of the add-in (see Note).|The locale of Microsoft Marketplace; for example, "en-us".|The version in the Microsoft Marketplace catalog (see Note).| +|WOPICatalog (partner [WOPI](/microsoft-365/cloud-storage-partner-program/online/) hosts)| The Microsoft Marketplace asset ID of the add-in (see Note). | `"wopicatalog"`. Use this value for add-ins that are published in App Source and are installed in WOPI hosts. For more information, see [Integrating with Office Online](/microsoft-365/cloud-storage-partner-program/online/overview). | The version in the add-in manifest.| |FileSystem (a network share)|The GUID of the add-in in the add-in manifest.|The path of the network share; for example, "\\\\MyComputer\\MySharedFolder".|The version in the add-in manifest.| -|EXCatalog (deployment via the Exchange server) |The GUID of the add-in in the add-in manifest.|"EXCatalog". EXCatalog row is the row to use with add-ins that use Centralized Deployment in the Microsoft 365 admin center.|The version in the add-in manifest.| -|Registry (System registry)|The GUID of the add-in in the add-in manifest.|"developer"|The version in the add-in manifest.| +|EXCatalog (deployment via the Exchange server) |The GUID of the add-in in the add-in manifest.|`"EXCatalog"`. EXCatalog row is the row to use with add-ins that use Centralized Deployment in the Microsoft 365 admin center.|The version in the add-in manifest.| +|Registry (System registry)|The GUID of the add-in in the add-in manifest.|`"developer"`|The version in the add-in manifest.| > [!NOTE] -> To find the asset ID and version of an add-in in AppSource, go to the AppSource landing page for the add-in. The asset ID appears in the address bar in the browser. The version is listed in the **Details** section of the page. +> To find the asset ID and version of an add-in in Microsoft Marketplace, go to the Microsoft Marketplace landing page for the add-in. The asset ID appears in the address bar in the browser. The version is listed in the **Details** section of the page. For more information about the webextension markup, see [[MS-OWEXML] 2.2.5. WebExtensionReference](/openspecs/office_standards/ms-owexml/d4081e0b-5711-45de-b708-1dfa1b943ad1). @@ -161,4 +193,5 @@ You can test the previous example by using your Microsoft 365 subscription to tr - For a sample that shows you how to use the autoopen feature, see [Auto-open a task pane with a document](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/office-add-in-commands/auto-open-task-pane). - [Automatically open a task pane when an add-in is installed](automatically-open-on-installation.md) -- [Learn about the Microsoft 365 Developer Program](https://aka.ms/m365devprogram) \ No newline at end of file +- [Learn about the Microsoft 365 Developer Program](https://aka.ms/m365devprogram) +- [Managing trust options for Office Add-ins](../publish/manage-trust-options.md) \ No newline at end of file diff --git a/docs/develop/automatically-open-on-installation.md b/docs/develop/automatically-open-on-installation.md index 3c013ae9c4..5966f21126 100644 --- a/docs/develop/automatically-open-on-installation.md +++ b/docs/develop/automatically-open-on-installation.md @@ -1,8 +1,8 @@ ---- +--- title: Automatically open a task pane when an add-in is installed description: Learn how to configure an Office Add-in to open automatically when it's installed. ms.topic: how-to -ms.date: 02/23/2024 +ms.date: 02/12/2025 ms.localizationpriority: medium --- @@ -24,15 +24,45 @@ By default, task pane add-ins that do *not* include any [add-in commands](../des The new behavior is as follows: - If the add-in has just one [task pane command](../design/add-in-commands.md#types-of-add-in-commands), then the add-in's ribbon tab is selected and the task pane opens automatically upon installation. You don't need to configure anything. -- If the add-in has multiple task pane commands, and one is configured to be the default (see [Configure default task pane](#configure-default-task-pane)), then the add-in's ribbon tab is selected and the default task pane opens automatically upon installation. +- If the add-in has multiple task pane commands, and one is configured to be the default (see [Configure default task pane](#configure-default-task-pane-in-the-manifest)), then the add-in's ribbon tab is selected and the default task pane opens automatically upon installation. - If the add-in has multiple task pane commands, but none is configured to be the default, then the add-in's ribbon tab is selected automatically upon installation and a callout appears near it notifying the user of the new add-in, but no task pane is opened. This is the same as the historic default behavior. > [!NOTE] > If for any reason, the add-in command that launches the task pane cannot be manually selected by a user at start up, such as when it's [configured to be disabled](../design/disable-add-in-commands.md) at start up, then it won't be automatically opened regardless of configuration. -## Configure default task pane +## Configure default task pane in the manifest + +The process for specifying the default task pane depends on the type of manifest the add-in uses. + +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) -To designate a task pane as the default, add a [TaskpaneId](/javascript/api/manifest/action#taskpaneid) element as the first child of the **\<Action\>** element and set its value to **Office.AutoShowTaskpaneWithDocument**. The following is an example. +[!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] + +To specify the default task pane, find the runtime object in the [`"runtimes"`](/microsoft-365/extensibility/schema/element-extensions#runtimes) array whose [`"code.page"`](/microsoft-365/extensibility/schema/extension-runtime-code#page) property is set to the URL of the page that you want to be the default. Ensure that the [`"actions"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item) array in this same runtime object has at least one action whose `"type"` value is `"openPage"`. Add a `"view"` property to this action object and set it to `"Office.AutoShowTaskpaneWithDocument"`. You can only set this value on one action object and it must be an action of type `"openPage"`. If you set this value on multiple actions, the first occurrence of the value will be recognized as the default and the others will be ignored. + +The following example shows a `"view"` value set to `"Office.AutoShowTaskpaneWithDocument"`. + +```json +"runtimes": [ + { + ... + "code": { + "page": "https://contoso.com/taskpane.html" + }, + "actions": [ + { + "id": "ShowTaskPane", + "type": "openPage", + "view": "Office.AutoShowTaskpaneWithDocument" + } + ] + } +] +``` + +# [Add-in only manifest](#tab/xmlmanifest) + +To designate a task pane as the default, add a [TaskpaneId](/javascript/api/manifest/action#taskpaneid) element as the first child of the `<Action>` element and set its value to **Office.AutoShowTaskpaneWithDocument**. The following is an example. ```xml <Action xsi:type="ShowTaskpane"> @@ -41,6 +71,8 @@ To designate a task pane as the default, add a [TaskpaneId](/javascript/api/mani </Action> ``` +--- + > [!TIP] > If you want your add-in to automatically launch whenever the user reopens the document, you need to take further configuration steps. For details and advice about when to use this feature, see [Automatically open a task pane with a document](automatically-open-a-task-pane-with-a-document.md). diff --git a/docs/develop/bind-to-regions-in-a-document-or-spreadsheet.md b/docs/develop/bind-to-regions-in-a-document-or-spreadsheet.md index 181efce825..2520cd1487 100644 --- a/docs/develop/bind-to-regions-in-a-document-or-spreadsheet.md +++ b/docs/develop/bind-to-regions-in-a-document-or-spreadsheet.md @@ -1,48 +1,59 @@ --- title: Bind to regions in a document or spreadsheet -description: Learn how to use binding to ensure consistent access a specific region or element of a document or spreadsheet through an identifier. -ms.date: 03/21/2023 +description: Learn how to use binding to ensure consistent access to a specific region or element of a document or spreadsheet through an identifier. +ms.date: 07/29/2025 ms.localizationpriority: medium --- - # Bind to regions in a document or spreadsheet -Binding-based data access enables content and task pane add-ins to consistently access a particular region of a document or spreadsheet through an identifier. The add-in first needs to establish the binding by calling one of the methods that associates a portion of the document with a unique identifier: [addFromPromptAsync], [addFromSelectionAsync], or [addFromNamedItemAsync]. After the binding is established, the add-in can use the provided identifier to access the data contained in the associated region of the document or spreadsheet. Creating bindings provides the following value to your add-in. +[!include[information about the common API](../includes/alert-common-api-info.md)] + +Bindings let your add-in consistently access specific regions of a document or spreadsheet. Think of a binding as a bookmark that remembers a specific location, even if users change their selection or navigate elsewhere in the document. Specifically, here are what bindings offer your add-in. + +- **Access common data structures** across supported Office applications, such as tables, ranges, or text. +- **Read and write data** without requiring users to make a selection first. +- **Create persistent relationships** between your add-in and document data. Bindings are saved with the document and work across sessions. + +To create a binding, call one of these [Bindings] object methods to associate a document region with a unique identifier: [addFromPromptAsync], [addFromSelectionAsync], or [addFromNamedItemAsync]. Once you've established the binding, use its identifier to read from or write to that region anytime. + +You can also subscribe to data and selection change events for specific bound regions. This means your add-in only gets notified about changes within the bound area, not the entire document. + +## Choose the right binding type -- Permits access to common data structures across supported Office applications, such as: tables, ranges, or text (a contiguous run of characters). -- Enables read/write operations without requiring the user to make a selection. -- Establishes a relationship between the add-in and the data in the document. Bindings are persisted in the document, and can be accessed at a later time. +Office supports [three different types of bindings][Office.BindingType]. You specify the type with the _bindingType_ parameter when creating a binding using [addFromSelectionAsync], [addFromPromptAsync], or [addFromNamedItemAsync]. -Establishing a binding also allows you to subscribe to data and selection change events that are scoped to that particular region of the document or spreadsheet. This means that the add-in is only notified of changes that happen within the bound region as opposed to general changes across the whole document or spreadsheet. +### Text Binding -The [Bindings] object exposes a [getAllAsync] method that gives access to the set of all bindings established on the document or spreadsheet. An individual binding can be accessed by its ID using either the Bindings.[getByIdAsync] method or [Office.select] function. You can establish new bindings as well as remove existing ones by using one of the following methods of the [Bindings] object: [addFromSelectionAsync], [addFromPromptAsync], [addFromNamedItemAsync], or [releaseByIdAsync]. +**[Text Binding][TextBinding]** - Binds to a document region that can be represented as text. -## Binding types +In Word, most contiguous selections work. In Excel, only single cell selections can use text binding. Excel supports only plain text, while Word supports three formats: plain text, HTML, and Open XML for Office. -There are [three different types of bindings][Office.BindingType] that you specify with the _bindingType_ parameter when you create a binding with the [addFromSelectionAsync], [addFromPromptAsync] or [addFromNamedItemAsync] methods. +### Matrix Binding -1. **[Text Binding][TextBinding]** - Binds to a region of the document that can be represented as text. +**[Matrix Binding][MatrixBinding]** - Binds to a fixed region containing tabular data without headers. - In Word, most contiguous selections are valid, while in Excel only single cell selections can be the target of a text binding. In Excel, only plain text is supported. In Word, three formats are supported: plain text, HTML, and Open XML for Office. +Data in a matrix binding is read or written as a two-dimensional **Array** (an array of arrays in JavaScript). For example, two rows of **string** values in two columns would look like `[['a', 'b'], ['c', 'd']]`, and a single column of three rows would be `[['a'], ['b'], ['c']]`. -1. **[Matrix Binding][MatrixBinding]** - Binds to a fixed region of a document that contains tabular data without headers.Data in a matrix binding is written or read as a two dimensional **Array**, which in JavaScript is implemented as an array of arrays. For example, two rows of **string** values in two columns can be written or read as `[['a', 'b'], ['c', 'd']]`, and a single column of three rows can be written or read as `[['a'], ['b'], ['c']]`. +In Excel, any contiguous selection of cells works for matrix binding. In Word, only tables support matrix binding. - In Excel, any contiguous selection of cells can be used to establish a matrix binding. In Word, only tables support matrix binding. +### Table Binding -1. **[Table Binding][TableBinding]** - Binds to a region of a document that contains a table with headers.Data in a table binding is written or read as a [TableData](/javascript/api/office/office.tabledata) object. The `TableData` object exposes the data through the `headers` and `rows` properties. +**[Table Binding][TableBinding]** - Binds to a document region containing a table with headers. - Any Excel or Word table can be the basis for a table binding. After you establish a table binding, each new row or column a user adds to the table is automatically included in the binding. +Data in a table binding is read or written as a [TableData](/javascript/api/office/office.tabledata) object. The `TableData` object exposes data through the `headers` and `rows` properties. -After a binding is created by using one of the three "addFrom" methods of the `Bindings` object, you can work with the binding's data and properties by using the methods of the corresponding object: [MatrixBinding], [TableBinding], or [TextBinding]. All three of these objects inherit the [getDataAsync] and [setDataAsync] methods of the `Binding` object that enable you to interact with the bound data. +Any Excel or Word table can be the basis for a table binding. After you establish a table binding, new rows or columns that users add to the table are automatically included in the binding. + +After creating a binding with one of the three "addFrom" methods, you can work with the binding's data and properties using the corresponding object: [MatrixBinding], [TableBinding], or [TextBinding]. All three objects inherit the [getDataAsync] and [setDataAsync] methods from the `Binding` object for interacting with bound data. > [!NOTE] -> **When should you use matrix versus table bindings?** -> When the tabular data you are working with contains a total row, you must use a matrix binding if your add-in's script needs to access values in the total row or detect that the user's selection is in the total row. If you establish a table binding for tabular data that contains a total row, the [TableBinding.rowCount] property and the `rowCount` and `startRow` properties of the [BindingSelectionChangedEventArgs] object in event handlers won't reflect the total row in their values. To work around this limitation, you must use establish a matrix binding to work with the total row. +> **Should you use matrix or table bindings?** +> When working with tabular data that includes a total row, use matrix binding if your add-in needs to access values in the total row or detect when a user selects the total row. Table bindings don't include total rows in their [TableBinding.rowCount] property or in the `rowCount` and `startRow` properties of [BindingSelectionChangedEventArgs] in event handlers. To work with total rows, you must use matrix binding. -## Add a binding to the user's current selection +## Create a binding from the current selection -The following example shows how to add a text binding called `myBinding` to the current selection in a document by using the [addFromSelectionAsync] method. +The following example adds a text binding called `myBinding` to the current selection using the [addFromSelectionAsync] method. ```js Office.context.document.bindings.addFromSelectionAsync(Office.BindingType.Text, { id: 'myBinding' }, function (asyncResult) { @@ -59,15 +70,15 @@ function write(message){ } ``` -In this example, the specified binding type is text. This means that a [TextBinding] will be created for the selection. Different binding types expose different data and operations. [Office.BindingType] is an enumeration of available binding type values. +In this example, the binding type is text, so a [TextBinding] is created for the selection. Different binding types expose different data and operations. [Office.BindingType] is an enumeration of available binding types. -The second optional parameter is an object that specifies the ID of the new binding being created. If an ID is not specified, one is generated automatically. +The second optional parameter specifies the ID of the new binding. If you don't specify an ID, one is generated automatically. -The anonymous function that is passed into the method as the final _callback_ parameter is executed when the creation of the binding is complete. The function is called with a single parameter, `asyncResult`, which provides access to an [AsyncResult] object that provides the status of the call. The `AsyncResult.value` property contains a reference to a [Binding] object of the type that is specified for the newly created binding. You can use this [Binding] object to get and set data. +The anonymous function passed as the final _callback_ parameter runs when the binding creation is complete. The function receives a single parameter, `asyncResult`, which provides access to an [AsyncResult] object with the call's status. The `AsyncResult.value` property contains a reference to a [Binding] object of the specified type for the newly created binding. You can use this [Binding] object to get and set data. -## Add a binding from a prompt +## Create a binding from a prompt -The following example shows how to add a text binding called `myBinding` by using the [addFromPromptAsync] method. This method lets the user specify the range for the binding by using the application's built-in range selection prompt. +The following function adds a text binding called `myBinding` using the [addFromPromptAsync] method. This method lets users specify the range for the binding using the application's built-in range selection prompt. ```js function bindFromPrompt() { @@ -86,21 +97,19 @@ function write(message){ } ``` -In this example, the specified binding type is text. This means that a [TextBinding] will be created for the selection that the user specifies in the prompt. - -The second parameter is an object that contains the ID of the new binding being created. If an ID is not specified, one is generated automatically. +In this example, the binding type is text, so a [TextBinding] is created for the user's selection in the prompt. -The anonymous function passed into the method as the third _callback_ parameter is executed when the creation of the binding is complete. When the callback function executes, the [AsyncResult] object contains the status of the call and the newly created binding. +The second parameter contains the ID of the new binding. If you don't specify an ID, one is generated automatically. -Figure 1 shows the built-in range selection prompt in Excel. +The anonymous function passed as the third _callback_ parameter runs when the binding creation is complete. When the callback function runs, the [AsyncResult] object contains the call's status and the newly created binding. -*Figure 1. Excel Select Data UI* +The following screenshot shows the built-in range selection prompt in Excel. ![The Select Data dialog.](../images/agave-api-overview-excel-selection-ui.png) ## Add a binding to a named item -The following example shows how to add a binding to the existing `myRange` named item as a "matrix" binding by using the [addFromNamedItemAsync] method, and assigns the binding's `id` as "myMatrix". +The following function adds a binding to the existing `myRange` named item as a "matrix" binding using the [addFromNamedItemAsync] method and assigns the binding's `id` as "myMatrix". ```js function bindNamedItem() { @@ -120,21 +129,20 @@ function write(message){ ``` -**For Excel**, the `itemName` parameter of the [addFromNamedItemAsync] method can refer to an existing named range, a range specified with the `A1` reference style `("A1:A3")`, or a table. By default, adding a table in Excel assigns the name "Table1" for the first table you add, "Table2" for the second table you add, and so on. To assign a meaningful name for a table in the Excel UI, use the `Table Name` property on the **Table Tools | Design** tab of the ribbon. +**For Excel**, the `itemName` parameter of [addFromNamedItemAsync] refers to an existing named range, a range specified with A1 reference style (`"A1:A3"`), or a table. By default, Excel assigns the names "Table1" for the first table, "Table2" for the second table, and so on. To assign a meaningful name to a table in the Excel UI, use the **Table Name** property on the **Table Tools | Design** tab. > [!NOTE] -> In Excel, when specifying a table as a named item, you must fully qualify the name to include the worksheet name in the name of the table in this format: `"Sheet1!Table1"` +> In Excel, when specifying a table as a named item, you must fully qualify the name to include the worksheet name in this format (e.g., `"Sheet1!Table1"`). -The following example creates a binding in Excel to the first three cells in column A ( `"A1:A3"`), assigns the id `"MyCities"`, and then writes three city names to that binding. +The following function creates a binding in Excel to the first three cells in column A (`"A1:A3"`), assigns the ID `"MyCities"`, and then writes three city names to that binding. ```js function bindingFromA1Range() { - Office.context.document.bindings.addFromNamedItemAsync("A1:A3", "matrix", {id: "MyCities" }, + Office.context.document.bindings.addFromNamedItemAsync("A1:A3", "matrix", { id: "MyCities" }, function (asyncResult) { if (asyncResult.status == "failed") { write('Error: ' + asyncResult.error.message); - } - else { + } else { // Write data to the new binding. Office.select("bindings#MyCities").setDataAsync([['Berlin'], ['Munich'], ['Duisburg']], { coercionType: "matrix" }, function (asyncResult) { @@ -151,11 +159,11 @@ function write(message){ } ``` -**For Word**, the `itemName` parameter of the [addFromNamedItemAsync] method refers to the `Title` property of a `Rich Text` content control. (You can't bind to content controls other than the `Rich Text` content control.) +**For Word**, the `itemName` parameter of [addFromNamedItemAsync] refers to the `Title` property of a `Rich Text` content control. (You can't bind to content controls other than the `Rich Text` content control.) -By default, a content control has no `Title*`value assigned. To assign a meaningful name in the Word UI, after inserting a **Rich Text** content control from the **Controls** group on the **Developer** tab of the ribbon, use the **Properties** command in the **Controls** group to display the **Content Control Properties** dialog box. Then set the `Title` property of the content control to the name you want to reference from your code. +By default, a content control has no `Title` value assigned. To assign a meaningful name in the Word UI, after inserting a **Rich Text** content control from the **Controls** group on the **Developer** tab, use the **Properties** command in the **Controls** group to display the **Content Control Properties** dialog. Then set the `Title` property of the content control to the name you want to reference from your code. -The following example creates a text binding in Word to a rich text content control named `"FirstName"`, assigns the **id** `"firstName"`, and then displays that information. +The following function creates a text binding in Word to a rich text content control named `"FirstName"`, assigns the **id** `"firstName"`, and then displays that information. ```js function bindContentControl() { @@ -178,7 +186,7 @@ function write(message){ ## Get all bindings -The following example shows how to get all bindings in a document by using the Bindings.[getAllAsync] method. +The following example gets all bindings in a document using the [getAllAsync] method. ```js Office.context.document.bindings.getAllAsync(function (asyncResult) { @@ -195,11 +203,11 @@ function write(message){ } ``` -The anonymous function that is passed into the method as the `callback` parameter is executed when the operation is complete. The function is called with a single parameter, `asyncResult`, which contains an array of the bindings in the document. The array is iterated to build a string that contains the IDs of the bindings. The string is then displayed in a message box. +The anonymous function passed as the `callback` parameter runs when the operation is complete. The function is called with a single parameter, `asyncResult`, which contains an array of the bindings in the document. The array is iterated to build a string that contains the IDs of the bindings. The string is then displayed in a message box. -## Get a binding by ID using the getByIdAsync method of the Bindings object +## Get a binding by ID using getByIdAsync -The following example shows how to use the [getByIdAsync] method to get a binding in a document by specifying its ID. This example assumes that a binding named `'myBinding'` was added to the document using one of the methods described earlier in this topic. +The following example uses the [getByIdAsync] method to get a binding in a document by specifying its ID. This example assumes that a binding named `'myBinding'` was added to the document using one of the methods described earlier in this article. ```js Office.context.document.bindings.getByIdAsync('myBinding', function (asyncResult) { @@ -217,13 +225,13 @@ function write(message){ } ``` -In the example, the first `id` parameter is the ID of the binding to retrieve. +In this example, the first `id` parameter is the ID of the binding to retrieve. -The anonymous function that is passed into the method as the second _callback_ parameter is executed when the operation is completed. The function is called with a single parameter, _asyncResult_, which contains the status of the call and the binding with the ID "myBinding". +The anonymous function passed as the second _callback_ parameter runs when the operation is completed. The function is called with a single parameter, _asyncResult_, which contains the call's status and the binding with the ID "myBinding". -## Get a binding by ID using the select function of the Office object +## Get a binding by ID using `Office.select` -The following example shows how to use the [Office.select] function to get a [Binding] object promise in a document by specifying its ID in a selector string. It then calls the Binding.[getDataAsync] method to get data from the specified binding. This example assumes that a binding named `'myBinding'` was added to the document using one of the methods described earlier in this topic. +The following example uses the [Office.select] function to get a [Binding] object promise in a document by specifying its ID in a selector string. It then calls the [getDataAsync] method to get data from the specified binding. This example assumes that a binding named `'myBinding'` was added to the document using one of the methods described earlier in this article. ```js Office.select("bindings#myBinding", function onError(){}).getDataAsync(function (asyncResult) { @@ -240,12 +248,11 @@ function write(message){ } ``` -> [!NOTE] -> If the `select` function promise successfully returns a [Binding] object, that object exposes only the following four methods of the object: [getDataAsync], [setDataAsync], [addHandlerAsync], and [removeHandlerAsync]. If the promise cannot return a Binding object, the `onError` callback can be used to access an [asyncResult].error object to get more information. If you need to call a member of the Binding object other than the four methods exposed by the [Binding] object promise returned by the `select` function, instead use the [getByIdAsync] method by using the [Document.bindings] property and Bindings.[getByIdAsync] method to retrieve the [Binding] object. +If the `select` function promise successfully returns a [Binding] object, that object exposes only the following four methods: [getDataAsync], [setDataAsync], [addHandlerAsync], and [removeHandlerAsync]. If the promise can't return a Binding object, the `onError` callback can be used to access an [asyncResult].error object to get more information. If you need to call a member of the Binding object other than the four methods exposed by the [Binding] object promise returned by the `select` function, instead use the [getByIdAsync] method by using the [Document.bindings] property and [getByIdAsync] method to retrieve the [Binding] object. ## Release a binding by ID -The following example shows how use the [releaseByIdAsync] method to release a binding in a document by specifying its ID. +The following example uses the [releaseByIdAsync] method to release a binding in a document by specifying its ID. ```js Office.context.document.bindings.releaseByIdAsync('myBinding', function (asyncResult) { @@ -258,13 +265,13 @@ function write(message){ } ``` -In the example, the first `id` parameter is the ID of the binding to release. +In this example, the first `id` parameter is the ID of the binding to release. -The anonymous function that is passed into the method as the second parameter is a callback that is executed when the operation is complete. The function is called with a single parameter, [asyncResult], which contains the status of the call. +The anonymous function passed as the second parameter is a callback that runs when the operation is complete. The function is called with a single parameter, [asyncResult], which contains the call's status. ## Read data from a binding -The following example shows how to use the [getDataAsync] method to get data from an existing binding. +The following example uses the [getDataAsync] method to get data from an existing binding. ```js myBinding.getDataAsync(function (asyncResult) { @@ -281,17 +288,17 @@ function write(message){ } ``` -`myBinding` is a variable that contains an existing text binding in the document. Alternatively, you could use the [Office.select] to access the binding by its ID, and start your call to the [getDataAsync] method, like this: +`myBinding` is a variable that contains an existing text binding in the document. Alternatively, you could use [Office.select] to access the binding by its ID, and start your call to the [getDataAsync] method, like this: ```js Office.select("bindings#myBindingID").getDataAsync ``` -The anonymous function that is passed into the method is a callback that is executed when the operation is complete. The [AsyncResult].value property contains the data within `myBinding`. The type of the value depends on the binding type. The binding in this example is a text binding. Therefore, the value will contain a string. For additional examples of working with matrix and table bindings, see the [getDataAsync] method topic. +The anonymous function passed into the method is a callback that runs when the operation is complete. The [AsyncResult].value property contains the data within `myBinding`. The type of the value depends on the binding type. The binding in this example is a text binding, so the value will contain a string. For additional examples of working with matrix and table bindings, see the [getDataAsync] method topic. ## Write data to a binding -The following example shows how to use the [setDataAsync] method to set data in an existing binding. +The following example uses the [setDataAsync] method to set data in an existing binding. ```js myBinding.setDataAsync('Hello World!', function (asyncResult) { }); @@ -299,13 +306,13 @@ myBinding.setDataAsync('Hello World!', function (asyncResult) { }); `myBinding` is a variable that contains an existing text binding in the document. -In the example, the first parameter is the value to set on `myBinding`. Because this is a text binding, the value is a `string`. Different binding types accept different types of data. +In this example, the first parameter is the value to set on `myBinding`. Because this is a text binding, the value is a `string`. Different binding types accept different types of data. -The anonymous function that is passed into the method is a callback that is executed when the operation is complete. The function is called with a single parameter, `asyncResult`, which contains the status of the result. +The anonymous function passed into the method is a callback that runs when the operation is complete. The function is called with a single parameter, `asyncResult`, which contains the result's status. -## Detect changes to data or the selection in a binding +## Detect changes to data or selection in a binding -The following example shows how to attach an event handler to the [DataChanged](/javascript/api/office/office.binding) event of a binding with an id of "MyBinding". +The following function attaches an event handler to the [DataChanged](/javascript/api/office/office.binding) event of a binding with an ID of "MyBinding". ```js function addHandler() { @@ -323,17 +330,17 @@ function write(message){ The `myBinding` is a variable that contains an existing text binding in the document. -The first _eventType_ parameter of the [addHandlerAsync] method specifies the name of the event to subscribe to. [Office.EventType] is an enumeration of available event type values. `Office.EventType.BindingDataChanged` evaluates to the string "bindingDataChanged". +The first _eventType_ parameter of [addHandlerAsync] specifies the name of the event to subscribe to. [Office.EventType] is an enumeration of available event type values. `Office.EventType.BindingDataChanged` evaluates to the string "bindingDataChanged". -The `dataChanged` function that is passed into the method as the second _handler_ parameter is an event handler that is executed when the data in the binding is changed. The function is called with a single parameter, _eventArgs_, which contains a reference to the binding. This binding can be used to retrieve the updated data. +The `dataChanged` function passed as the second _handler_ parameter is an event handler that runs when the data in the binding is changed. The function is called with a single parameter, _eventArgs_, which contains a reference to the binding. This binding can be used to retrieve the updated data. -Similarly, you can detect when a user changes selection in a binding by attaching an event handler to the [SelectionChanged] event of a binding. To do that, specify the `eventType` parameter of the [addHandlerAsync] method as `Office.EventType.BindingSelectionChanged` or `"bindingSelectionChanged"`. +Similarly, you can detect when a user changes selection in a binding by attaching an event handler to the [SelectionChanged] event of a binding. To do that, specify the `eventType` parameter of [addHandlerAsync] as `Office.EventType.BindingSelectionChanged` or `"bindingSelectionChanged"`. -You can add multiple event handlers for a given event by calling the [addHandlerAsync] method again and passing in an additional event handler function for the `handler` parameter. This will work correctly as long as the name of each event handler function is unique. +You can add multiple event handlers for a given event by calling [addHandlerAsync] again and passing in an additional event handler function for the `handler` parameter. The name of each event handler function must be unique. ### Remove an event handler -To remove an event handler for an event, call the [removeHandlerAsync] method passing in the event type as the first _eventType_ parameter, and the name of the event handler function to remove as the second _handler_ parameter. For example, the following function will remove the `dataChanged` event handler function added in the previous section's example. +To remove an event handler for an event, call [removeHandlerAsync] passing in the event type as the first _eventType_ parameter, and the name of the event handler function to remove as the second _handler_ parameter. For example, the following function removes the `dataChanged` event handler function added in the previous section's example. ```js function removeEventHandlerFromBinding() { @@ -343,7 +350,7 @@ function removeEventHandlerFromBinding() { ``` > [!IMPORTANT] -> If the optional _handler_ parameter is omitted when the [removeHandlerAsync] method is called, all event handlers for the specified `eventType` will be removed. +> If the optional _handler_ parameter is omitted when [removeHandlerAsync] is called, all event handlers for the specified `eventType` will be removed. ## See also @@ -351,29 +358,29 @@ function removeEventHandlerFromBinding() { - [Asynchronous programming in Office Add-ins](asynchronous-programming-in-office-add-ins.md) - [Read and write data to the active selection in a document or spreadsheet](read-and-write-data-to-the-active-selection-in-a-document-or-spreadsheet.md) -[Binding]: /javascript/api/office/office.binding -[MatrixBinding]: /javascript/api/office/office.matrixbinding -[TableBinding]: /javascript/api/office/office.tablebinding -[TextBinding]: /javascript/api/office/office.textbinding -[getDataAsync]: /javascript/api/office/office.binding#getDataAsync_options__callback_ -[setDataAsync]: /javascript/api/office/office.binding#setDataAsync_data__options__callback_ -[SelectionChanged]: /javascript/api/office/office.bindingselectionchangedeventargs -[addHandlerAsync]: /javascript/api/office/office.binding#addHandlerAsync_eventType__handler__options__callback_ -[removeHandlerAsync]: /javascript/api/office/office.binding#removeHandlerAsync_eventType__options__callback_ - -[Bindings]: /javascript/api/office/office.bindings -[getByIdAsync]: /javascript/api/office/office.bindings#getByIdAsync_id__options__callback_ -[getAllAsync]: /javascript/api/office/office.bindings#getAllAsync_options__callback_ +[Binding]: /javascript/api/office/office.binding +[MatrixBinding]: /javascript/api/office/office.matrixbinding +[TableBinding]: /javascript/api/office/office.tablebinding +[TextBinding]: /javascript/api/office/office.textbinding +[getDataAsync]: /javascript/api/office/office.binding#getDataAsync_options__callback_ +[setDataAsync]: /javascript/api/office/office.binding#setDataAsync_data__options__callback_ +[SelectionChanged]: /javascript/api/office/office.bindingselectionchangedeventargs +[addHandlerAsync]: /javascript/api/office/office.binding#addHandlerAsync_eventType__handler__options__callback_ +[removeHandlerAsync]: /javascript/api/office/office.binding#removeHandlerAsync_eventType__options__callback_ + +[Bindings]: /javascript/api/office/office.bindings +[getByIdAsync]: /javascript/api/office/office.bindings#getByIdAsync_id__options__callback_ +[getAllAsync]: /javascript/api/office/office.bindings#getAllAsync_options__callback_ [addFromNamedItemAsync]: /javascript/api/office/office.bindings#addFromNamedItemAsync_itemName__bindingType__options__callback_ [addFromSelectionAsync]: /javascript/api/office/office.bindings#addFromSelectionAsync_bindingType__options__callback_ -[addFromPromptAsync]: /javascript/api/office/office.bindings#addFromPromptAsync_bindingType__options__callback_ -[releaseByIdAsync]: /javascript/api/office/office.bindings#releaseByIdAsync_id__options__callback_ +[addFromPromptAsync]: /javascript/api/office/office.bindings#addFromPromptAsync_bindingType__options__callback_ +[releaseByIdAsync]: /javascript/api/office/office.bindings#releaseByIdAsync_id__options__callback_ -[AsyncResult]: /javascript/api/office/office.asyncresult -[Office.BindingType]: /javascript/api/office/office.bindingtype -[Office.select]: /javascript/api/office -[Office.EventType]: /javascript/api/office/office.eventtype -[Document.bindings]: /javascript/api/office/office.document +[AsyncResult]: /javascript/api/office/office.asyncresult +[Office.BindingType]: /javascript/api/office/office.bindingtype +[Office.select]: /javascript/api/office +[Office.EventType]: /javascript/api/office/office.eventtype +[Document.bindings]: /javascript/api/office/office.document [TableBinding.rowCount]: /javascript/api/office/office.tablebinding -[BindingSelectionChangedEventArgs]: /javascript/api/office/office.bindingselectionchangedeventargs \ No newline at end of file +[BindingSelectionChangedEventArgs]: /javascript/api/office/office.bindingselectionchangedeventargs diff --git a/docs/develop/configure-your-add-in-to-use-a-shared-runtime.md b/docs/develop/configure-your-add-in-to-use-a-shared-runtime.md index ca10a64cfd..aed58bb40f 100644 --- a/docs/develop/configure-your-add-in-to-use-a-shared-runtime.md +++ b/docs/develop/configure-your-add-in-to-use-a-shared-runtime.md @@ -1,8 +1,8 @@ ---- +--- title: Configure your Office Add-in to use a shared runtime description: Configure your Office Add-in to use a shared runtime to support additional ribbon, task pane, and custom function features. ms.topic: how-to -ms.date: 09/05/2024 +ms.date: 03/12/2025 ms.localizationpriority: high --- @@ -10,64 +10,101 @@ ms.localizationpriority: high [!include[Shared runtime requirements](../includes/shared-runtime-requirements-note.md)] -You can configure your Office Add-in to run all of its code in a single [shared runtime](../testing/runtimes.md#shared-runtime). This enables better coordination across your add-in and access to the DOM and CORS from all parts of your add-in. It also enables additional features such as running code when the document opens, or enabling or disabling ribbon buttons. To configure your add-in to use a shared runtime, follow the instructions in this article. +You can configure your Office Add-in to run all of its code in a single [shared runtime](../testing/runtimes.md#shared-runtime). With a shared runtime, you'll have better coordination across your add-in and access to the DOM and CORS from all parts of your add-in. You'll also have access to additional features, such as running code when the document opens or activating ribbon buttons in certain contexts. To configure your add-in to use a shared runtime, follow the instructions in this article. ## Create the add-in project -If you are starting a new project, use the [Yeoman generator for Office Add-ins](yeoman-generator-overview.md) to create an Excel, PowerPoint, or Word add-in project. +If you're starting a new project, use the [Yeoman generator for Office Add-ins](yeoman-generator-overview.md) to create an Excel, PowerPoint, or Word add-in project. -Run the command `yo office --projectType taskpane --name "my office add in" --host <host> --js true`, where `<host>` is one of the following values. +> [!TIP] +> If you're using the Yeoman generator to create custom functions in Excel, select the following options: +> +> - **Project type**: `Excel Custom Functions using a Shared Runtime` +> - **Script type**: `JavaScript` -- excel -- powerpoint -- word +If your add-in uses an add-in only manifest, you can also use the steps in this article to update a Visual Studio project to use the shared runtime. However, you may need to update the XML schemas for the manifest. For more information, see [Troubleshoot development errors with Office Add-ins](../testing/troubleshoot-development-errors.md#add-in-only-manifest-schema-validation-errors-in-visual-studio-projects). -> [!IMPORTANT] -> The `--name` argument value must be in double quotation marks, even if it has no spaces. +## Configure the manifest -You can use different options for the **--projecttype**, **--name**, and **--js** command-line options. For the full list of options, see [Yeoman generator for Office Add-ins](https://github.com/OfficeDev/generator-office). +Follow these steps to configure a new or existing project to use a shared runtime. These steps assume you have generated your project using the [Yeoman generator for Office Add-ins](yeoman-generator-overview.md). Select the tab for the type of manifest your add-in is using. -The generator will create the project and install supporting Node components. You can also use the steps in this article to update a Visual Studio project to use the shared runtime. However, you may need to update the XML schemas for the manifest. For more information, see [Troubleshoot development errors with Office Add-ins](../testing/troubleshoot-development-errors.md#manifest-schema-validation-errors-in-visual-studio-projects). +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) -## Configure the manifest +> [!NOTE] +> Implementing a shared runtime with the unified manifest for Microsoft 365 is in public developer preview. This shouldn't be used in production add-ins. We invite you to try it out in test or development environments. For more information, see the [Microsoft 365 app manifest schema reference](/microsoft-365/extensibility/schema). + +1. Open your add-in project in Visual Studio Code. +1. Open the **manifest.json** file. +1. Add the following object to the [`"extensions.runtimes"`](/microsoft-365/extensibility/schema/extension-runtimes-array?view=m365-app-prev&preserve-view=true) array. Note the following about this markup. + - The [SharedRuntime 1.1 requirement set](/javascript/api/requirement-sets/common/shared-runtime-requirement-sets#sharedruntime-api-11) is specified in the [`"requirements.capabilities"`](/microsoft-365/extensibility/schema/requirements-extension-element-capabilities) object. This configures your add-in to run in a shared runtime on supported clients. For a list of clients that support the SharedRuntime 1.1 requirement set, see [Shared runtime requirement sets](/javascript/api/requirement-sets/common/shared-runtime-requirement-sets). + - The `"id"` of the runtime is set to the descriptive name `"SharedRuntime"`. + - The `"lifetime"` property is set to `"long"`, so that your add-in can take advantage of features, such as starting your add-in when the document opens, continuing to run code after the task pane is closed, or using CORS and DOM from custom functions. If you set the property to `"short"` in this example, your add-in will start when one of your ribbon buttons is pressed, but it may shut down after your ribbon handler is done running. Similarly, your add-in will start when the task pane is opened, but it may shut down when the task pane is closed. + + ```json + "runtimes": [ + "requirements": { + "capabilities": [ + { + "name": "SharedRuntime", + "minVersion": "1.1" + } + ] + }, + "id": "SharedRuntime", + "type": "general", + "code": { + "page": "https://localhost:3000/taskpane.html" + }, + "lifetime": "long", + "actions": [ + ... + ] + ] + ``` + +1. Save your changes. -Follow these steps for a new or existing project to configure it to use a shared runtime. These steps assume you have generated your project using the [Yeoman generator for Office Add-ins](yeoman-generator-overview.md). +# [Add-in only manifest](#tab/xmlmanifest) -1. Start Visual Studio Code and open your add-in project. +1. Open your add-in project in Visual Studio Code. 1. Open the **manifest.xml** file. -1. For an Excel or PowerPoint add-in, update the requirements section to include the [shared runtime](/javascript/api/requirement-sets/common/shared-runtime-requirement-sets). Be sure to remove the `CustomFunctionsRuntime` requirement if it is present. The XML should appear as follows. +1. Update the requirements section to include the [shared runtime](/javascript/api/requirement-sets/common/shared-runtime-requirement-sets) as follows. ```xml <Hosts> - <Host Name="Workbook"/> + <Host ...> </Hosts> <Requirements> <Sets DefaultMinVersion="1.1"> <Set Name="SharedRuntime" MinVersion="1.1"/> </Sets> </Requirements> - <DefaultSettings> ``` -1. Find the **\<VersionOverrides\>** section and add the following **\<Runtimes\>** section. The lifetime needs to be **long** so that your add-in code can run even when the task pane is closed. The `resid` value is **Taskpane.Url**, which references the **taskpane.html** file location specified in the `<bt:Urls>` section near the bottom of the **manifest.xml** file. +1. Find the `<VersionOverrides>` section and add the following `<Runtimes>` section. Note the following about this markup. + - The lifetime needs to be **long** so that your add-in can take advantage of features, such as starting your add-in when the document opens, continuing to run code after the task pane is closed, or using CORS and DOM from custom functions. If you set the lifetime to **short** in this example, your add-in will start when one of your ribbon buttons is pressed, but it may shut down after your ribbon handler is done running. Similarly, your add-in will start when the task pane is opened, but it may shut down when the task pane is closed. + - The `resid` value is **Taskpane.Url**, which references the **taskpane.html** file location specified in the `<bt:Urls>` section near the bottom of the **manifest.xml** file. - > [!IMPORTANT] - > The shared runtime won't load if the `resid` uses different values in the manifest. If you change the value to something other than **Taskpane.Url**, be sure to also change the value in all locations shown in the following steps in this article. - > - > Also, the **\<Runtimes\>** section must be entered after the **\<Host\>** element in the exact order shown in the following XML. + > [!IMPORTANT] + > The shared runtime won't load if the `resid` uses different values in the manifest. If you change the value to something other than **Taskpane.Url**, be sure to also change the value in all locations shown in the following steps in this article. - ```xml - <VersionOverrides ...> - <Hosts> - <Host ...> - <Runtimes> - <Runtime resid="Taskpane.Url" lifetime="long" /> - </Runtimes> - ... - </Host> - ``` + - The `<Runtimes>` section must be entered after the `<Host>` element in the exact order shown in the following XML. + + > [!NOTE] + > If your add-in includes the `<Runtimes>` element in the manifest (required for a shared runtime) and the conditions for using WebView2 (Microsoft Edge Chromium-based) are met, it uses that control. If the conditions are not met, then it uses the Trident (Internet Explorer 11) webview control regardless of the Windows or Microsoft 365 version. For more information, see [Runtimes](/javascript/api/manifest/runtimes) and [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). + + ```xml + <VersionOverrides ...> + <Hosts> + <Host ...> + <Runtimes> + <Runtime resid="Taskpane.Url" lifetime="long" /> + </Runtimes> + ... + </Host> + ``` -1. If you generated an Excel add-in with custom functions, find the **\<Page\>** element. Then change the source location from **Functions.Page.Url** to **Taskpane.Url**. +1. If you generated an Excel add-in with custom functions, find the `<Page>` element. Then change the source location from **Functions.Page.Url** to **Taskpane.Url**. ```xml <AllFormFactors> @@ -78,7 +115,7 @@ Follow these steps for a new or existing project to configure it to use a shared ... ``` -1. Find the **\<FunctionFile\>** tag and change the `resid` from **Commands.Url** to **Taskpane.Url**. Note that if you don't have action commands, you won't have a **\<FunctionFile\>** entry, and can skip this step. +1. Find the `<FunctionFile>` tag and change the `resid` from **Commands.Url** to **Taskpane.Url**. Note that if you don't have action commands, you won't have a `<FunctionFile>` entry, and can skip this step. ```xml </GetStarted> @@ -87,7 +124,9 @@ Follow these steps for a new or existing project to configure it to use a shared ... ``` -1. Save the **manifest.xml** file. +1. Save your changes. + +--- ## Configure the webpack.config.js file @@ -136,10 +175,10 @@ The **webpack.config.js** will build multiple runtime loaders. You need to modif ## Test your Office Add-in changes -You can confirm that you are using the shared runtime correctly by using the following instructions. +Confirm that you're using the shared runtime correctly by using the following instructions. 1. Open the **taskpane.js** file. -1. Replace the entire contents of the file with the following code. This will display a count of how many times the task pane has been opened. Adding the onVisibilityModeChanged event is only supported in a shared runtime. +1. Replace the entire contents of the file with the following code. This will display a count of how many times the task pane has been opened. Adding the `onVisibilityModeChanged` event is only supported in a shared runtime. ```javascript /*global document, Office*/ @@ -151,8 +190,8 @@ You can confirm that you are using the shared runtime correctly by using the fol document.getElementById("app-body").style.display = "flex"; updateCount(); // Update count on first open. - Office.addin.onVisibilityModeChanged(function (args) { - if (args.visibilityMode === "Taskpane") { + Office.addin.onVisibilityModeChanged((args) => { + if (args.visibilityMode === Office.VisibilityMode.taskpane) { updateCount(); // Update count on subsequent opens. } }); @@ -170,7 +209,7 @@ You can confirm that you are using the shared runtime correctly by using the fol npm start ``` -Each time you open the task pane, the count of how many times it has been opened will be incremented. The value of **_count** will not be lost because the shared runtime keeps your code running even when the task pane is closed. +Each time you open the task pane, the count of how many times it has been opened will be incremented. The value of **_count** won't be lost because the shared runtime keeps your code running even when the task pane is closed. When you're ready to stop the dev server and uninstall the add-in, run the following command. @@ -178,37 +217,21 @@ When you're ready to stop the dev server and uninstall the add-in, run the follo npm stop ``` -## Runtime lifetime - -When you add the **\<Runtime\>** element, you also specify a lifetime with a value of `long` or `short`. Set this value to `long` to take advantage of features such as starting your add-in when the document opens, continuing to run code after the task pane is closed, or using CORS and DOM from custom functions. - -> [!NOTE] -> The default lifetime value is `short`, but we recommend using `long` in Excel, PowerPoint, and Word add-ins. If you set your runtime to `short` in this example, your add-in will start when one of your ribbon buttons is pressed, but it may shut down after your ribbon handler is done running. Similarly, your add-in will start when the task pane is opened, but it may shut down when the task pane is closed. - -```xml -<Runtimes> - <Runtime resid="Taskpane.Url" lifetime="long" /> -</Runtimes> -``` - -> [!NOTE] -> If your add-in includes the **\<Runtimes\>** element in the manifest (required for a shared runtime) and the conditions for using WebView2 (Microsoft Edge Chromium-based) are met, it uses that control. If the conditions are not met, then it uses the Trident (Internet Explorer 11) webview control regardless of the Windows or Microsoft 365 version. For more information, see [Runtimes](/javascript/api/manifest/runtimes) and [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). - ## About the shared runtime -On Windows or on Mac, your add-in will run code for ribbon buttons, custom functions, and the task pane in separate runtime environments. This creates limitations such as not being able to easily share global data, and not being able to access all CORS functionality from a custom function. +On Windows or on Mac, your add-in will run code for ribbon buttons, custom functions, and the task pane in separate runtime environments. This creates limitations, such as not being able to easily share global data, and not being able to access all CORS functionality from a custom function. However, you can configure your Office Add-in to share code in the same runtime (also referred to as a shared runtime). This enables better coordination across your add-in and access to the task pane DOM and CORS from all parts of your add-in. Configuring a shared runtime enables the following scenarios. - Your Office Add-in can use additional UI features. - - [Enable and Disable Add-in Commands](../design/disable-add-in-commands.md) + - [Change the availability of add-in commands](../design/disable-add-in-commands.md) - [Run code in your Office Add-in when the document opens](run-code-on-document-open.md) - [Show or hide the task pane of your Office Add-in](show-hide-add-in.md) + - [Add custom keyboard shortcuts to your Office Add-ins](../design/keyboard-shortcuts.md) (supported in Excel and Word add-ins only) - The following are available for Excel add-ins only. - - [Add Custom keyboard shortcuts to your Office Add-ins (preview)](../design/keyboard-shortcuts.md) - - [Create custom contextual tabs in Office Add-ins (preview)](../design/contextual-tabs.md) + - [Create custom contextual tabs in Office Add-ins](../design/contextual-tabs.md) - Custom functions will have full CORS support. - Custom functions can call Office.js APIs to read spreadsheet document data. @@ -223,9 +246,9 @@ Don't design your add-in to use multiple task panes if you are planning to use a ## See also - [Call Excel APIs from a custom function](../excel/call-excel-apis-from-custom-function.md) -- [Add custom keyboard shortcuts to your Office Add-ins (preview)](../design/keyboard-shortcuts.md) -- [Create custom contextual tabs in Office Add-ins (preview)](../design/contextual-tabs.md) -- [Enable and Disable Add-in Commands](../design/disable-add-in-commands.md) +- [Add custom keyboard shortcuts to your Office Add-ins](../design/keyboard-shortcuts.md) +- [Create custom contextual tabs in Office Add-ins](../design/contextual-tabs.md) +- [Change the availability of add-in commands](../design/disable-add-in-commands.md) - [Run code in your Office Add-in when the document opens](run-code-on-document-open.md) - [Show or hide the task pane of your Office Add-in](show-hide-add-in.md) - [Tutorial: Share data and events between Excel custom functions and the task pane](../tutorials/share-data-and-events-between-custom-functions-and-the-task-pane-tutorial.md) diff --git a/docs/develop/convert-javascript-to-typescript.md b/docs/develop/convert-javascript-to-typescript.md index 966d7d7874..c1e04935f4 100644 --- a/docs/develop/convert-javascript-to-typescript.md +++ b/docs/develop/convert-javascript-to-typescript.md @@ -2,7 +2,7 @@ title: Convert an Office Add-in project in Visual Studio to TypeScript description: Learn how to convert an Office Add-in project in Visual Studio to use TypeScript. ms.topic: how-to -ms.date: 08/06/2024 +ms.date: 05/12/2025 ms.localizationpriority: medium --- @@ -24,7 +24,7 @@ You can use the Office Add-in template in Visual Studio to create an add-in that > [!NOTE] > [Skip this section](#convert-the-add-in-project-to-typescript) if you already have an existing project. -1. In Visual Studio, choose **Create a new project**. If the Visual Studio development environment is already open, you can create a new project by choosing **File > New > Project** on the menu bar. +1. In Visual Studio, choose **Create a new project**. If the Visual Studio development environment is already open, you can create a new project by choosing **File** > **New** > **Project** on the menu bar. 1. Using the search box, enter **add-in**. Choose **Excel Web Add-in**, then select **Next**. @@ -57,7 +57,11 @@ You can use the Office Add-in template in Visual Studio to create an add-in that "noEmitOnError": true, "removeComments": false, "sourceMap": true, - "target": "es5" + "target": "es5", + "lib": [ + "es2015", + "dom" + ] }, "exclude": [ "node_modules", @@ -90,7 +94,7 @@ You can use the Office Add-in template in Visual Studio to create an add-in that ``` 1. Save the file. -1. Select the ASP.NET web project that has your project name with the text `Web` appended to the end. Under the **npm** section, set both **Restore On Project Open** and **Restore On Save** to "True". +1. Open the npm project properties by going to **Tools** > **Options**, then **Projects and Solutions** > **Web Package Management** > **Package Restore**. Set both **Restore On Project Open** and **Restore On Save** to "True". Select **OK** to save the settings. ### Update the JavaScript files @@ -102,15 +106,6 @@ Change your JavaScript files (**.js**) to TypeScript files (**.ts**). Then, make 1. Find the **./Scripts/MessageBanner.js** file and rename it to **MessageBanner.ts**. -1. In **Home.ts**, find the line `Office.initialize = function (reason) {` and add a line immediately after it to polyfill the global `window.Promise`, as shown here. - - ```TypeScript - Office.initialize = function (reason) { - // Add the following line. - (window as any).Promise = OfficeExtension.Promise; - ... - ``` - 1. In **./Scripts/MessageBanner.ts**, find the line `_onResize(null);` and replace it with the following: ```TypeScript @@ -130,7 +125,7 @@ The JavaScript files generated by Visual Studio do not contain any TypeScript sy ## Run the converted add-in project -1. In Visual Studio, press **F5** or choose the **Start** button to launch Excel with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. +1. In Visual Studio, press <kbd>F5</kbd> or choose the **Start** button to launch Excel with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. 1. In Excel, choose the **Home** tab, and then choose the **Show Taskpane** button on the ribbon to open the add-in task pane. diff --git a/docs/develop/convert-xml-to-json-manifest.md b/docs/develop/convert-xml-to-json-manifest.md index d6f0cbeb8b..6342f6f6fa 100644 --- a/docs/develop/convert-xml-to-json-manifest.md +++ b/docs/develop/convert-xml-to-json-manifest.md @@ -1,36 +1,50 @@ ---- +--- title: Convert an add-in to use the unified manifest for Microsoft 365 description: Learn the various methods for converting an add-in with an add-in only manifest to the unified manifest for Microsoft 365 and sideload the add-in. ms.topic: how-to -ms.date: 04/12/2024 +ms.date: 11/06/2025 ms.localizationpriority: medium --- # Convert an add-in to use the unified manifest for Microsoft 365 -To add Teams capabilities to an add-in that uses the add-in only manifest, or to just future proof the add-in, you need to convert it to use the unified manifest for Microsoft 365. +To upgrade an add-in that uses the add-in only manifest to a full App for Microsoft 365 to which you can add Teams capabilities or a Copilot extension, you need to convert it to use the unified manifest for Microsoft 365. + + [!INCLUDE [Unified manifest support note for Office applications](../includes/unified-manifest-support-note.md)] -There are three basic tasks to converting an add-in project from the add-in only manifest to the unified manifest. +There are four basic tasks to converting an add-in project from the add-in only manifest to the unified manifest. -- Ensure that your add-in is ready to convert. +- Ensure that your manifest is ready to convert. - Convert the XML-formatted add-in only manifest itself to the JSON format of the unified manifest. -- Package the new manifest and the two icon image files into a zip file for sideloading or deployment. +- Edit the newly created unified manifest. +- Package the new manifest and two icon image files (described later) into an app package (zip) file for sideloading or deployment. *Depending on how you sideload the converted add-in, this task may be done for you automatically.* [!INCLUDE [non-unified manifest clients note](../includes/non-unified-manifest-clients.md)] > [!NOTE] -> +> > - Add-ins that use the unified manifest can be sideloaded only on Office Version 2304 (Build 16320.20000) or later. -> - Projects created in Visual Studio, as distinct from Visual Studio Code, can't be converted at this time. -> - If you [created the project with Teams Toolkit](teams-toolkit-overview.md) or with the "unified manifest" option in the [Office Yeoman Generator](yeoman-generator-overview.md), it already uses the unified manifest. +> - Visual Studio doesn't support the unified manifest for Office Add-ins. Projects that were created in Visual Studio shouldn't be converted. +> - If you [created the project with Teams Toolkit or Microsoft 365 Agents Toolkit](agents-toolkit-overview.md) or with the "unified manifest" option in the [Office Yeoman Generator](yeoman-generator-overview.md), it already uses the unified manifest. -## Ensure that your add-in is ready to convert +## Ensure that your manifest is ready to convert The following sections describe conditions that must be met before you convert the manifest. -### Ensure that you have the two image files +### Uninstall the existing version of the add-in + +To avoid conflicts with UI control names and other problems, be sure the existing add-in isn't installed on the computer where you do the conversion. If you experience any difficulties uninstalling the add-in, see [Remove a ghost add-in](../testing/uninstall-add-in.md#remove-a-ghost-add-in). + +### Ensure that you have two special image files -When you've added the files to the project, add **\<IconUrl\>** and **\<HighResolutionIconUrl\>** (in that order) to the add-in only manifest just below the **\<Description\>** element. The following is an example. +If your add-in only manifest doesn't already have both `<IconUrl>` and `<HighResolutionIconUrl>` (in that order) elements, then add them just below the `<Description>` element. The values of the **DefaultValue** attribute should be the full URLs of image files. The images must be a specified size as shown in the following table. + +|Office application|\<IconUrl\>|\<HighResolutionIconUrl\>| +|:---------------|:---------------|:---------------| +|Outlook|64x64 pixels|128x128 pixels| +|All other Office</br>applications|32x32 pixels|64x64 pixels| + +The following markup is an example. ```xml <OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="MailApp"> @@ -46,127 +60,104 @@ When you've added the files to the project, add **\<IconUrl\>** and **\<HighReso <!-- Other markup omitted --> ``` -### Ensure that your function command names are short enough +### Reduce the number of add-in commands as needed -If your manifest has any **\<FunctionName\>** elements, make sure their values have fewer than 65 characters. The value of this element must exactly match the name of a function in a JavaScript or TypeScript file. If you change it in the manifest, be sure to change it in the code file too. +An add-in that uses the unified manifest may not have more than 20 [add-in commands](../design/add-in-commands.md). If the total number of [`<Action>` elements](/javascript/api/manifest/action) in the add-in only manifest is greater than 20, you must redesign the add-in to have no more than 20. -### Ensure that your SSO add-in requests permissions +### Update the add-in ID, version, domain, and function names in the manifest -If your add-in uses Microsoft single sign-on with the on-behalf-of (OBO) flow, your add-in has a **\<Scopes\>** element that specifies the Microsoft Graph or other API permissions that the add-in needs. With the unified manifest, permissions must be requested at runtime in the code. Update your code as needed to request these permissions. The exact code depends on the architecture and authorization code libraries you are using. Typically, code requests permissions in a function that requests an access token. +1. Change the value of the `<ID>` element to a new random GUID. +1. Update the value of the `<Version>` element and ensure that it conforms to the [semver standard](https://semver.org/) (MAJOR.MINOR.PATCH). Each segment can have no more than five digits. For example, change the value `1.0.0.0` to `1.0.1`. The semver standard's prerelease and metadata version string extensions aren't supported. -## Conversion tools and options +1. Be sure that the domain segment of the add-in's URLs in the manifest are pointing to `https://localhost:3000`. -There are several ways to carry out the remaining tasks, depending on the IDE and other tools you want to use for your project, and on the tool you used to create the project. +1. If your manifest has any `<FunctionName>` elements, make sure their values have fewer than 65 characters. -- [Convert the project with Teams Toolkit](#convert-the-project-with-teams-toolkit) -- [Projects created with the Office Yeoman Generator (aka "Yo Office")](#projects-created-with-the-office-yeoman-generator-aka-yo-office) -- [NodeJS and npm projects that aren't created with Yeoman Generator](#nodejs-and-npm-projects-that-arent-created-with-yeoman-generator) + > [!IMPORTANT] + > The value of this element must exactly match the name of an action that's mapped to a function in a JavaScript or TypeScript file with the [Office.actions.associate](/javascript/api/office/office.actions#office-office-actions-associate-member(1)) function. If you change it in the manifest, be sure to change it in the `actionId` parameter passed to `associate()` too. -### Convert the project with Teams Toolkit +### Shorten string values as needed -The easiest way to convert is to use Teams Toolkit. +Review and change, as needed, manifest values in light of the following effects of the conversion. -#### Prerequisites +- The first 30 characters of `<DisplayName>` becomes the value of [`"name.short"`](/microsoft-365/extensibility/schema/root-name#short) in the unified manifest. +- The first 100 characters of `<DisplayName>` becomes the value of [`"name.full"`](/microsoft-365/extensibility/schema/root-name#full) in the unified manifest. +- The first 250 characters of `<Description>` becomes the value of [`"description.short"`](/microsoft-365/extensibility/schema/root-description#short) in the unified manifest. +- The first 4000 characters of `<Description>` becomes the value of [`"description.full"`](/microsoft-365/extensibility/schema/root-description#full) in the unified manifest. +- The first 32 characters of the `<ProviderName>` becomes the value of [`"developer.name"`](/microsoft-365/extensibility/schema/root-developer#name) in the unified manifest. -- Install [Visual Studio Code](https://code.visualstudio.com/) -- Install [Teams Toolkit](/microsoftteams/platform/toolkit/install-teams-toolkit?tabs=vscode#install-teams-toolkit-for-visual-studio-code) - -#### Import the add-in project to Teams Toolkit - -1. Open Visual Studio Code and select the Teams Toolkit icon on the **Activity Bar**. - - :::image type="content" source="../images/teams-toolkit-icon.png" alt-text="Teams Toolkit icon."::: +> [!NOTE] +> If any of these elements have child `<Override>` elements, be sure to adjust the localized strings as needed. -1. Select **Create a new app**. -1. In the **New Project** drop down, select **Outlook Add-in**. +### Ensure conformity of custom functions configuration - :::image type="content" source="../images/teams-toolkit-create-outlook-add-in.png" alt-text="The four options in New Project drop down. The fourth option is called 'Outlook add-in'."::: +If your add-in has custom functions, then it includes a JSON configuration file. Some requirements for this file weren't always enforced by Office or Microsoft Marketplace in the past, but they are all enforced when the add-in has a unified manifest. Before you convert the manifest, ensure that this JSON file conforms to all requirements. For more information, see [Custom functions naming and localization](../excel/custom-functions-naming.md) and [Manually create JSON metadata for custom functions](../excel/custom-functions-json.md). -1. In the **App Features Using an Outlook Add-in** drop down, select **Import an Existing Outlook Add-in**. +In particular, note that [all function names and function ids must have at least 3 characters](../excel/custom-functions-naming.md#custom-functions-naming-guidelines) and that [each function object must have a "result" property](../excel/custom-functions-json.md#metadata-reference). - :::image type="content" source="../images/teams-toolkit-create-outlook-task-pane-capability.png" alt-text="The two options in the App Features Using an Outlook Add-in drop down. The second option is called 'Import an Existing Outlook add-in'."::: +### Verify that the modified add-in only manifest works -1. In the **Existing add-in project folder** drop down, browse to the root folder of the add-in project. -1. In the **Select import project manifest file** drop down, browse to the add-in only manifest file, typically named **manifest.xml**. -1. In the **Workspace folder** dialog, select the folder where you want to put the converted project. -1. In the **Application name** dialog, give a name to the project (with no spaces). Teams Toolkit creates the project with your source files and scaffolding. It then opens the project *in a second Visual Studio Code window*. Close the original Visual Studio Code window. +1. Validate the modified add-in only manifest. See [Validate an Office Add-in's manifest](../testing/troubleshoot-manifest.md). -#### Sideload the add-in in Visual Studio Code +1. Verify that the add-in can be sideloaded and run. See [Sideload an Office Add-in for testing](../testing/test-debug-office-add-ins.md#sideload-an-office-add-in-for-testing). -You can sideload the add-in using the Teams Toolkit or in a command prompt, bash shell, or terminal. +Resolve any problems before you attempt to convert the project. -##### Sideload with the Teams Toolkit +## Conversion tools and options -1. First, *make sure Outlook desktop is closed.* -1. In Visual Studio Code, open the Teams Toolkit. -1. In the **ACCOUNTS** section, verify that you're signed into Microsoft 365. -1. Select **View** | **Run** in Visual Studio Code. In the **RUN AND DEBUG** drop down menu, select the option, **Outlook Desktop (Edge Chromium)**, and then press **F5**. The project builds and a Node dev-server window opens. This process may take a couple of minutes and then Outlook desktop opens. -1. You can now work with your add-in. Be sure you're working in the **Inbox** of *your Microsoft 365 account identity*. +There are several ways to carry out the remaining tasks, depending on the IDE and other tools you want to use for your project, and on the tool you used to create the project. -##### Sideload with a system prompt, bash shell, or terminal +- [Convert projects created with the Yeoman generator for Office Add-ins (aka "Yo Office")](#convert-projects-created-with-the-yeoman-generator-for-office-add-ins-aka-yo-office) +- [Convert NodeJS and npm projects that weren't created with the Yeoman generator for Office Add-ins (Yo Office)](#convert-nodejs-and-npm-projects-that-werent-created-with-the-yeoman-generator-for-office-add-ins-yo-office) -1. First, *make sure Outlook desktop is closed.* -1. Open a system prompt, bash shell, or the Visual Studio Code **TERMINAL**, and navigate to the root of the project. -1. Run the command `npm run start:desktop`. The project builds and a Node dev-server window opens. This process may take a couple of minutes then Outlook desktop opens. -1. You can now work with your add-in. -1. When you're done working with your add-in, make sure to run the command `npm run stop`. +> [!NOTE] +> Conversion of the manifest is one of the effects of importing the add-in project into Agents Toolkit if you do so using the toolkit's importation feature. For details, see [Import an add-in project to Agents Toolkit](import-teams-toolkit.md). -### Projects created with the Office Yeoman Generator (aka "Yo Office") +### Convert projects created with the Yeoman generator for Office Add-ins (aka "Yo Office") -If the project was created with the Office Yeoman Generator and you don't want to use the Teams Toolkit, convert it using the following steps. +If the project was created with the Yeoman generator for Office Add-ins, convert it using the following steps. 1. In the root of the project, open a command prompt or bash shell and run the following command. This converts the manifest and updates the package.json to specify current tooling packages. The new unified manifest is in the root of the project and the old add-in only manifest is in a backup.zip file. For details about this command, see [Office-Addin-Project](https://www.npmjs.com/package/office-addin-project). ```command line npx office-addin-project convert -m <relative-path-to-XML-manifest> ``` +1. Carry out the steps in [Edit the new unified manifest](#edit-the-new-unified-manifest). -1. Run `npm install`. -1. To sideload the add-in, run `npm run start:desktop`. This command puts the unified manifest and the two image files into a zip file and sideloads it to the Office application. It also starts the server in a separate NodeJS window to host the add-in files on localhost. - -When you're ready to stop the dev server and uninstall the add-in, run the command `npm run stop`. - -### NodeJS and npm projects that aren't created with Yeoman Generator - -If you don't want to use the Teams Toolkit and your project wasn't created with the Office Yeoman generator, use the office-addin-manifest-converter tool. - -In the root of the project, open a command prompt or bash shell and run the following command. This command puts the unified manifest in a subfolder with the same name as the filename stem of the original add-in only manifest. For example, if the manifest is named **MyManifest.xml**, the unified manifest is created at **.\MyManifest\MyManifest.json**. For more details about this command, see [Office-Addin-Manifest-Converter](https://www.npmjs.com/package/office-addin-manifest-converter). - -```command line -npx office-addin-manifest-converter convert <relative-path-to-XML-manifest> -``` +### Convert NodeJS and npm projects that weren't created with the Yeoman generator for Office Add-ins (Yo Office) -Once you have the unified manifest created, there are two ways to create the zip file and sideload it. They are described in the next two subsections. +If your project wasn't created with Yo Office, use the office-addin-manifest-converter tool. -#### Sideload with the Office-Addin-Debugging tool +1. In the root of the project, open a command prompt or bash shell and run the following command. This command puts the unified manifest in a subfolder with the same name as the filename stem of the original add-in only manifest. For example, if the manifest is named **MyManifest.xml**, the unified manifest is created at **.\MyManifest\MyManifest.json**. For more details about this command, see [Office-Addin-Manifest-Converter](https://www.npmjs.com/package/office-addin-manifest-converter). -1. To sideload the add-in, run the following command. This command puts the unified manifest and two default icon image files into a zip file and sideloads it to the Office application. It also starts a server in a separate NodeJS window to host the add-in files on localhost. Note that you pass the path to the *unified manifest* that you created in the previous step. For more details about this command, see [Office-Addin-Debugging](https://www.npmjs.com/package/office-addin-debugging). + ```command line + npx office-addin-manifest-converter convert <relative-path-to-XML-manifest> + ``` +1. Carry out the steps in [Edit the new unified manifest](#edit-the-new-unified-manifest). - ```command line - npx office-addin-debugging start <relative-path-to-unified-manifest> desktop - ``` +## Edit the new unified manifest -1. When you use office-addin-debugging to start an add-in, *always stop the session with the following command*. Closing the server window doesn't reliably stop the server and closing the Office application doesn't reliably cause Office to unacquire the add-in. +1. Open the unified manifest file. +1. Navigate to the [`"developer"`](/microsoft-365/extensibility/schema/root-developer) property and ensure there are child `"privacyUrl"` and `"termsOfUseUrl"` properties. These properties must have appropriate values with a localhost domain. +1. You can now [sideload the add-in](#sideload-the-add-in). - ```command line - npx office-addin-debugging stop <relative-path-to-unified-manifest> - ``` +## Sideload the add-in -#### Sideload with the Teams Toolkit CLI (command-line interface) +The sideloading process depends on how the project was created. -1. Manually create the zip package using the following steps. +### Sideload an add-in that was created with the Yeoman generator for Office Add-ins - 1. Open the unified manifest and scroll to the "icons" property. Note the relative path of the two image files. - 1. Use any zip utility to create a zip file that contains the unified manifest and the two image files. *The image files must have the same relative path in the zip file as they do in the project.* For example, if the relative path is "assets/icon-64.png" and "assets/icon-128.png", then you must include the "assets" folder with the two files in the zip package. - 1. If the folder contains other files, such as image files used in the Office ribbon, remove these from the zip package. It should have only the two image files specified in the "icons" property (in addition to the manifest in the root of the zip package). +1. Run `npm install`. +1. To sideload the add-in, see [Sideload add-ins created with the Yeoman generator for Office Add-ins (Yo Office)](../testing/sideload-add-in-with-unified-manifest.md#sideload-add-ins-created-with-the-yeoman-generator-for-office-add-ins-yo-office). The app package zip file is created for you as part of this process. -1. In the root of the project, open a command prompt or bash shell and run the following commands. +### Sideload NodeJS and npm projects that weren't created with the Yeoman generator for Office Add-ins - ```command line - npm install -g @microsoft/teamsfx-cli +Once you have the unified manifest created, there are two ways to create the zip file and sideload it. For more information, see [Sideload other NodeJS and npm projects](../testing/sideload-add-in-with-unified-manifest.md#sideload-other-nodejs-and-npm-projects). - teamsfx m365 sideloading --file-path <relative-path-to-zip-file> - ``` +> [!NOTE] +> If the original add-in only manifest used any `<Override>` elements to localize strings in the manifest, then the conversion process produces JSON string files for each localized language. These files must also be included in the app package zip file, and they must be at the relative path indicated in the [`"localizationInfo.additionalLanguages.file"`](/microsoft-365/extensibility/schema/root-localization-info-additional-languages#file) property. +## Next steps +Consider whether to maintain both the old and new versions of the add-in. See [Manage both a unified manifest and an add-in only manifest version of your Office Add-in](../concepts/duplicate-legacy-metaos-add-ins.md). diff --git a/docs/develop/create-addin-commands-unified-manifest.md b/docs/develop/create-addin-commands-unified-manifest.md index c386417963..c37439cde5 100644 --- a/docs/develop/create-addin-commands-unified-manifest.md +++ b/docs/develop/create-addin-commands-unified-manifest.md @@ -1,7 +1,7 @@ --- title: Create add-in commands with the unified manifest for Microsoft 365 description: Configure the unified manifest for Microsoft 365 to define add-in commands for Excel, Outlook, PowerPoint, and Word. Use add-in commands to create UI elements, add buttons or lists, and perform actions. -ms.date: 07/18/2024 +ms.date: 05/19/2025 ms.localizationpriority: medium --- @@ -11,6 +11,8 @@ Add-in commands provide an easy way to customize the default Office user interfa This article describes how to configure the [Unified manifest for Microsoft 365](unified-manifest-overview.md) to define add-in commands and how to create the code for [function commands](../design/add-in-commands.md#types-of-add-in-commands). +[!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] + > [!TIP] > Instructions for creating add-in commands with the add-in only manifest are in [Create add-in commands with the add-in only manifest](create-addin-commands.md). @@ -18,7 +20,7 @@ This article describes how to configure the [Unified manifest for Microsoft 365] ## Starting point and major steps -Both of the tools that create add-in projects with a unified manifest — the [Office Yeoman generator](yeoman-generator-overview.md) and [Teams Toolkit](teams-toolkit-overview.md) — create projects with one or more add-in commands. The only time you won't already have an add-in command is if you are updating an add-in which previously didn't have one. +Both of the tools that create add-in projects with a unified manifest — the [Office Yeoman generator](yeoman-generator-overview.md) and [Microsoft 365 Agents Toolkit](agents-toolkit-overview.md) — create projects with one or more add-in commands. The only time you won't already have an add-in command is if you are updating an add-in which previously didn't have one. ## Two decisions @@ -31,18 +33,15 @@ The following subsections explain how to include a [task pane command](../design ### Configure the runtime for the task pane command -1. Open the unified manifest and find the "extensions.runtimes" array. -1. Ensure that there is a runtime object that has an "actions.type" property with the value "openPage". This type of runtime opens a task pane. -1. Ensure that the "requirements.capabilities" array contains an object that specifies a [Requirement Set](office-versions-and-requirement-sets.md) that supports add-in commands. For Outlook the minimum requirement set for add-in commands is [Mailbox 1.3](/javascript/api/requirement-sets/outlook/requirement-set-1.3/outlook-requirement-set-1.3). - - > [!NOTE] - > When support for the unified manifest is extended to other Office host applications, the minimum requirement set for add-in commands in those other hosts will be [AddinCommands 1.1](/javascript/api/requirement-sets/common/add-in-commands-requirement-sets). +1. Open the unified manifest and find the [`"extensions.runtimes"`](/microsoft-365/extensibility/schema/extension-runtimes-array?view=m365-app-prev&preserve-view=true) array. +1. Ensure that there is a runtime object that has an [`"actions.type"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item#type) property with the value `"openPage"`. This type of runtime opens a task pane. +1. Ensure that the [`"requirements.capabilities"`](/microsoft-365/extensibility/schema/requirements-extension-element-capabilities) array contains an object that specifies a [Requirement Set](office-versions-and-requirement-sets.md) that supports add-in commands. For Outlook the minimum requirement set for add-in commands is [Mailbox 1.3](/javascript/api/requirement-sets/outlook/requirement-set-1.3/outlook-requirement-set-1.3). For other Office host applications, the minimum requirement set for add-in commands is [AddinCommands 1.1](/javascript/api/requirement-sets/common/add-in-commands-requirement-sets). -1. Ensure that the "id" of the runtime object has a descriptive name such as "TaskPaneRuntime". -1. Ensure that the "code.page" property of the runtime object is set to the URL of the page that should open in the task pane, such as `"https://localhost:3000/taskpane.html"`. -1. Ensure that the "actions.view" of the runtime object has a name that describes the content of the page that you set in the preceding step, such as "homepage" or "dashboard". -1. Ensure that the "actions.id" of the runtime object has a descriptive name such as "ShowTaskPane" that indicates what happens when the user selects the add-in command button or menu item. -1. Set the other properties and subproperties of the runtime object as shown in the following completed example of a runtime object. The "type" and "lifetime" properties are required and in Outlook Add-ins (which is the only host that currently supports the unified manifest) they always have the values shown in this example. +1. Ensure that the `"id"` of the runtime object has a descriptive name such as `"TaskPaneRuntime"`. +1. Ensure that the [`"code.page"`](/microsoft-365/extensibility/schema/extension-runtime-code#page) property of the runtime object is set to the URL of the page that should open in the task pane, such as `"https://localhost:3000/taskpane.html"`. +1. Ensure that the [`"actions.view"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item#view) of the runtime object has a name that describes the content of the page that you set in the preceding step, such as `"homepage"` or `"dashboard"`. +1. Ensure that the [`"actions.id"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item#id) of the runtime object has a descriptive name such as `"ShowTaskPane"` that indicates what happens when the user selects the add-in command button or menu item. +1. Set the other properties and subproperties of the runtime object as shown in the following completed example of a runtime object. The `"type"` and `"lifetime"` properties are required and in Outlook Add-ins. They always have the values shown in this example. ```json "runtimes": [ @@ -74,8 +73,8 @@ The following subsections explain how to include a [task pane command](../design ### Configure the UI for the task pane command -1. Ensure that the extension object for which you configured a runtime has a "ribbons" array property as a peer to the "runtimes" array. There is typically only one extension object in the "extensions" array. -1. Ensure that the array has an object with array properties named "contexts" and "tabs", as shown in the following example. +1. Ensure that the extension object for which you configured a runtime has a [`"ribbons"`](/microsoft-365/extensibility/schema/element-extensions#ribbons) array property as a peer to the [`"runtimes"`](/microsoft-365/extensibility/schema/element-extensions#runtimes) array. There is typically only one extension object in the [`"extensions"`](/microsoft-365/extensibility/schema/root#extensions) array. +1. Ensure that the array has an object with array properties named `"contexts"` and `"tabs"`, as shown in the following example. ```json "ribbons": [ @@ -90,12 +89,12 @@ The following subsections explain how to include a [task pane command](../design ] ``` -1. Ensure that the "contexts" array has strings that specify the windows or panes in which the UI for the task pane command should appear. For example, "mailRead" means that it will appear in the reading pane or message window when an email message is open, but "mailCompose" means it will appear when a new message or a reply is being composed. The following are the allowable values: +1. Ensure that the `"contexts"` array has strings that specify the windows or panes in which the UI for the task pane command should appear. For example, `"mailRead"` means that it will appear in the reading pane or message window when an email message is open, but `"mailCompose"` means it will appear when a new message or a reply is being composed. The following are the allowable values: - - "mailRead" - - "mailCompose" - - "meetingDetailsOrganizer" - - "meetingDetailsAttendee" + - `"mailRead"` + - `"mailCompose"` + - `"meetingDetailsOrganizer"` + - `"meetingDetailsAttendee"` The following is an example. @@ -105,7 +104,7 @@ The following subsections explain how to include a [task pane command](../design ], ``` -1. Ensure that the "tabs" array has an object with a "builtInTabId" string property that is set to the ID of ribbon tab in which you want your task pane command to appear. Also, ensure that there is a "groups" array with at least one object in it. The following is an example. +1. Ensure that the `"tabs"` array has an object with a `"builtInTabId"` string property that is set to the ID of ribbon tab in which you want your task pane command to appear. Also, ensure that there is a `"groups"` array with at least one object in it. The following is an example. ```json "tabs": [ @@ -121,13 +120,13 @@ The following subsections explain how to include a [task pane command](../design ``` > [!NOTE] - > The only allowed value for the "builtInTabID" property is "TabDefault", which in Outlook is either the **Home**, **Message**, or **Meeting** tab. When support for the unified manifest is added to other Office host applications, there will be other possible values. + > For a list of the possible values of the `"builtInTabID"` property, see [Find the IDs of built-in Office ribbon tabs](built-in-ui-ids.md). -1. Ensure that the "groups" array has an object to define the custom control group that will hold your add-in command UI controls. The following is an example. Note the following about this JSON: +1. Ensure that the `"groups"` array has an object to define the custom control group that will hold your add-in command UI controls. The following is an example. Note the following about this JSON: - - The "id" must be unique across all groups in all ribbon objects in the manifest. Maximum length is 64 characters. - - The "label" appears on the group on the ribbon. Although its maximum length is 64 characters, to ensure that the control group fits correctly in the ribbon, we recommend that you limit the "label" to 16 characters. - - One of the "icons" appears on the group only if the Office application window, and hence the ribbon, has been sized by the user too small for any of the controls in the group to appear. Office decides when to use one of these icons and which one to use based on the size of the window and the resolution of the device. You cannot control this. You must provide image files for 16, 32, and 80 pixels, while five other sizes are also supported (20, 24, 40, 48, and 64 pixels). You must use Secure Sockets Layer (SSL) for all URLs. + - The `"id"` must be unique across all groups in all ribbon objects in the manifest. Maximum length is 64 characters. + - The `"label"` appears on the group on the ribbon. Although its maximum length is 64 characters, to ensure that the control group fits correctly in the ribbon, we recommend that you limit the `"label"` to 16 characters. + - One of the `"icons"` appears on the group only if the Office application window, and hence the ribbon, has been sized by the user too small for any of the controls in the group to appear. Office decides when to use one of these icons and which one to use based on the size of the window and the resolution of the device. You cannot control this. You must provide image files for 16, 32, and 80 pixels, while five other sizes are also supported (20, 24, 40, 48, and 64 pixels). You must use Secure Sockets Layer (SSL) for all URLs. ```json "groups": [ @@ -157,12 +156,12 @@ The following subsections explain how to include a [task pane command](../design ] ``` -1. Ensure that there is a control object in the "controls" array for each button or custom menu you want. The following is an example. Note the following about this JSON: +1. Ensure that there is a control object in the `"controls"` array for each button or custom menu you want. The following is an example. Note the following about this JSON: - - The "id", "label", and "icons" properties have the same purpose and the same restrictions as the corresponding properties of a group object, except that they apply to a specific button or menu within the group. - - The "type" property is set to "button" which means that the control will be a ribbon button. You can also configure a task pane command to be run from a menu item. See [Menu and menu items](#menu-and-menu-items). - - The "supertip.title" (maximum length: 64 characters) and "supertip.description" (maximum length: 128 characters) appear when the cursor is hovering over the button or menu. - - The "actionId" must be an exact match for the "runtimes.actions.id" that you set in [Configure the runtime for the task pane command](#configure-the-runtime-for-the-task-pane-command). + - The `"id"`, `"label"`, and `"icons"` properties have the same purpose and the same restrictions as the corresponding properties of a group object, except that they apply to a specific button or menu within the group. + - The `"type"` property is set to `"button"` which means that the control will be a ribbon button. You can also configure a task pane command to be run from a menu item. See [Menu and menu items](#menu-and-menu-items). + - The `"supertip.title"` (maximum length: 64 characters) and `"supertip.description"` (maximum length: 128 characters) appear when the cursor is hovering over the button or menu. + - The `"actionId"` must be an exact match for the [`"runtimes.actions.id"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item#id) that you set in [Configure the runtime for the task pane command](#configure-the-runtime-for-the-task-pane-command). ```json { @@ -248,7 +247,7 @@ The following subsections explain how to include a [function command](../design/ <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <!-- Office JavaScript Library --> - <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script> + <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script> <!-- Function command file --> <script src="http://github.com/commands.js" type="text/javascript"></script> </head> @@ -259,21 +258,18 @@ The following subsections explain how to include a [function command](../design/ ### Configure the runtime for the function command -1. Open the unified manifest and find the "extensions.runtimes" array. -1. Ensure that there is a runtime object that has a "actions.type" property with the value "executeFunction". -1. Ensure that the "requirements.capabilities" array contains objects that specify any [Requirement Sets](office-versions-and-requirement-sets.md) that are needed to support the APIs add-in commands. For Outlook, the minimum requirement set for add-in commands is [Mailbox 1.3](/javascript/api/requirement-sets/outlook/requirement-set-1.3/outlook-requirement-set-1.3). But if your function command calls that API that is part of later **Mailbox** requirement set, such as **Mailbox 1.5**, then you need to specify the later version (e.g., "1.5") as the "minVersion" value. - - > [!NOTE] - > When support for the unified manifest is extended to other Office host applications, the minimum requirement set for add-in commands in those other hosts will be [AddinCommands 1.1](/javascript/api/requirement-sets/common/add-in-commands-requirement-sets). +1. Open the unified manifest and find the `"extensions.runtimes"` array. +1. Ensure that there is a runtime object that has a `"actions.type"` property with the value `"executeFunction"`. +1. Ensure that the `"requirements.capabilities"` array contains objects that specify any [Requirement Sets](office-versions-and-requirement-sets.md) that are needed to support the APIs add-in commands. For Outlook, the minimum requirement set for add-in commands is [Mailbox 1.3](/javascript/api/requirement-sets/outlook/requirement-set-1.3/outlook-requirement-set-1.3). But if your function command calls that API that is part of later **Mailbox** requirement set, such as **Mailbox 1.5**, then you need to specify the later version (e.g., "1.5") as the `"minVersion"` value. For other Office host applications, the minimum requirement set for add-in commands is [AddinCommands 1.1](/javascript/api/requirement-sets/common/add-in-commands-requirement-sets). -1. Ensure that the "id" of the runtime object has a descriptive name such as "CommandsRuntime". -1. Ensure that the "code.page" property of the runtime object is set to the URL of the UI-less HTML page that loads your function file, such as `"https://localhost:3000/commands.html"`. -1. Ensure that the "actions.id" of the runtime object has a descriptive name such as "SetNotification" that indicates what happens when the user selects the add-in command button or menu item. +1. Ensure that the `"id"` of the runtime object has a descriptive name such as "CommandsRuntime". +1. Ensure that the [`"code.page"`](/microsoft-365/extensibility/schema/extension-runtime-code#page) property of the runtime object is set to the URL of the UI-less HTML page that loads your function file, such as `"https://localhost:3000/commands.html"`. +1. Ensure that the `"actions.id"` of the runtime object has a descriptive name such as "SetNotification" that indicates what happens when the user selects the add-in command button or menu item. > [!IMPORTANT] - > The value of "actions.id" must exactly match the first parameter of the call to `Office.actions.associate` in the function file. + > The value of `"actions.id"` must exactly match the first parameter of the call to `Office.actions.associate` in the function file. -1. Set the other properties and subproperties of the runtime object as shown in the following completed example of a runtime object. The "type" and "lifetime" properties are required and they always have the values shown in Outlook add-ins, which is the only host that currently supports the unified manifest. +1. Set the other properties and subproperties of the runtime object as shown in the following completed example of a runtime object. ```json "runtimes": [ @@ -296,8 +292,8 @@ The following subsections explain how to include a [function command](../design/ ### Configure the UI for the function command -1. Ensure that the extension object for which you configured a runtime has a "ribbons" array property as a peer to the "runtimes" array. There is typically only one extension object in the "extensions" array. -1. Ensure that the array has an object with array properties named "contexts" and "tabs", as shown in the following example. +1. Ensure that the extension object for which you configured a runtime has a `"ribbons"` array property as a peer to the `"runtimes"` array. There is typically only one extension object in the `"extensions"` array. +1. Ensure that the array has an object with array properties named `"contexts"` and `"tabs"`, as shown in the following example. ```json "ribbons": [ @@ -312,12 +308,12 @@ The following subsections explain how to include a [function command](../design/ ] ``` -1. Ensure that the "contexts" array has strings that specify the windows or panes in which the UI for the function command should appear. For example, "mailRead" means that it will appear in the reading pane or message window when an email message is open, but "mailCompose" means it will appear when a new message or a reply is being composed. The following are the allowable values: +1. Ensure that the `"contexts"` array has strings that specify the windows or panes in which the UI for the function command should appear. For example, `"mailRead"` means that it will appear in the reading pane or message window when an email message is open, but `"mailCompose"` means it will appear when a new message or a reply is being composed. The following are the allowable values: - - mailRead - - mailCompose - - meetingDetailsOrganizer - - meetingDetailsAttendee + - `"mailRead"` + - `"mailCompose"` + - `"meetingDetailsOrganizer"` + - `"meetingDetailsAttendee"` The following is an example. @@ -327,7 +323,7 @@ The following subsections explain how to include a [function command](../design/ ], ``` -1. Ensure that the "tabs" array has an object with a "builtInTabId" string property that is set to the ID of ribbon tab in which you want your function command to appear and a "groups" array with at least one object in it. The following is an example. +1. Ensure that the `"tabs"` array has an object with a `"builtInTabId"` string property that is set to the ID of ribbon tab in which you want your function command to appear and a `"groups"` array with at least one object in it. The following is an example. ```json "tabs": [ @@ -343,13 +339,13 @@ The following subsections explain how to include a [function command](../design/ ``` > [!NOTE] - > The only allowed value for the "builtInTabID" property is "TabDefault", which in Outlook is either the **Home**, **Message**, or **Meeting** tab. When support for the unified manifest is added to other Office host applications, there will be other possible values. + > For a list of the possible values of the `"builtInTabID"` property, see [Find the IDs of built-in Office ribbon tabs](built-in-ui-ids.md). -1. Ensure that the "groups" array has an object to define the custom control group that will hold your add-in command UI controls. The following is an example. Note the following about this JSON: +1. Ensure that the `"groups"` array has an object to define the custom control group that will hold your add-in command UI controls. The following is an example. Note the following about this JSON: - - The "id" must be unique across all groups in all ribbon objects in the manifest. Maximum length is 64 characters. - - The "label" appears on the group on the ribbon. Although its maximum length is 64 characters, to ensure that the control group fits correctly in the ribbon, we recommend that you limit the "label" to 16 characters. - - One of the "icons" appears on the group only if the Office application window, and hence the ribbon, has been sized by the user too small for any of the controls in the group to appear. Office decides when to use one of these icons and which one to use based on the size of the window and the resolution of the device. You cannot control this. You must provide image files for 16, 32, and 80 pixels, while five other sizes are also supported (20, 24, 40, 48, and 64 pixels). You must use Secure Sockets Layer (SSL) for all URLs. + - The `"id"` must be unique across all groups in all ribbon objects in the manifest. Maximum length is 64 characters. + - The `"label"` appears on the group on the ribbon. Although its maximum length is 64 characters, to ensure that the control group fits correctly in the ribbon, we recommend that you limit the `"label"` to 16 characters. + - One of the `"icons"` appears on the group only if the Office application window, and hence the ribbon, has been sized by the user too small for any of the controls in the group to appear. Office decides when to use one of these icons and which one to use based on the size of the window and the resolution of the device. You cannot control this. You must provide image files for 16, 32, and 80 pixels, while five other sizes are also supported (20, 24, 40, 48, and 64 pixels). You must use Secure Sockets Layer (SSL) for all URLs. ```json "groups": [ @@ -379,12 +375,12 @@ The following subsections explain how to include a [function command](../design/ ] ``` -1. Ensure that there is a control object in the "controls" array for each button or custom menu you want. The following is an example. Note the following about this JSON: +1. Ensure that there is a control object in the `"controls"` array for each button or custom menu you want. The following is an example. Note the following about this JSON: - - The "id", "label", and "icons" properties have the same purpose and the same restrictions as the corresponding properties of a group object, except that they apply to a specific button or menu within the group. - - The "type" property is set to "button" which means that the control will be a ribbon button. You can also configure a function command to be run from a menu item. See [Menu and menu items](#menu-and-menu-items). - - The "supertip.title" (maximum length: 64 characters) and "supertip.description" (maximum length: 128 characters) appear when the cursor is hovering over the button or menu. - - The "actionId" must be an exact match for the "runtime.actions.id" that you set in [Configure the runtime for the function command](#configure-the-runtime-for-the-function-command). + - The `"id"`, `"label"`, and `"icons"` properties have the same purpose and the same restrictions as the corresponding properties of a group object, except that they apply to a specific button or menu within the group. + - The `"type"` property is set to `"button"` which means that the control will be a ribbon button. You can also configure a function command to be run from a menu item. See [Menu and menu items](#menu-and-menu-items). + - The `"supertip.title"` (maximum length: 64 characters) and `"supertip.description"` (maximum length: 128 characters) appear when the cursor is hovering over the button or menu. + - The `"actionId"` must be an exact match for the `"runtime.actions.id"` that you set in [Configure the runtime for the function command](#configure-the-runtime-for-the-function-command). ```json { @@ -429,8 +425,8 @@ Carry out the steps of the following sections: ### Configure the UI for the menu -1. Ensure that the extension object for which you configured a runtime has a "ribbons" array property as a peer to the "runtimes" array. There is typically only one extension object in the "extensions" array. -1. Ensure that the array has an object with array properties named "contexts" and "tabs", as shown in the following example. +1. Ensure that the extension object for which you configured a runtime has a `"ribbons"` array property as a peer to the `"runtimes"` array. There is typically only one extension object in the `"extensions"` array. +1. Ensure that the array has an object with array properties named `"contexts"` and `"tabs"`, as shown in the following example. ```json "ribbons": [ @@ -445,12 +441,12 @@ Carry out the steps of the following sections: ] ``` -1. Ensure that the "contexts" array has strings that specify the windows or panes in which the menu should appear on the ribbon. For example, "mailRead" means that it will appear in the reading pane or message window when an email message is open, but "mailCompose" means it will appear when a new message or a reply is being composed. The following are the allowable values: +1. Ensure that the `"contexts"` array has strings that specify the windows or panes in which the menu should appear on the ribbon. For example, `"mailRead"` means that it will appear in the reading pane or message window when an email message is open, but `"mailCompose"` means it will appear when a new message or a reply is being composed. The following are the allowable values: - - mailRead - - mailCompose - - meetingDetailsOrganizer - - meetingDetailsAttendee + - `"mailRead"` + - `"mailCompose"` + - `"meetingDetailsOrganizer"` + - `"meetingDetailsAttendee"` The following is an example. @@ -460,7 +456,7 @@ Carry out the steps of the following sections: ], ``` -1. Ensure that the "tabs" array has an object with a "builtInTabId" string property that is set to the ID of ribbon tab in which you want your task pane command to appear and a "groups" array with at least one object in it. The following is an example. +1. Ensure that the `"tabs"` array has an object with a `"builtInTabId"` string property that is set to the ID of ribbon tab in which you want your task pane command to appear and a `"groups"` array with at least one object in it. The following is an example. ```json "tabs": [ @@ -476,13 +472,13 @@ Carry out the steps of the following sections: ``` > [!NOTE] - > The only allowed value for the "builtInTabID" property is "TabDefault", which in Outlook is either the **Home**, **Message**, or **Meeting** tab. When support for the unified manifest is added to other Office host applications, there will be other possible values. + > For a list of the possible values of the `"builtInTabID"` property, see [Find the IDs of built-in Office ribbon tabs](built-in-ui-ids.md). -1. Ensure that the "groups" array has an object to define the custom control group that will hold your drop down menu control. The following is an example. Note the following about this JSON: +1. Ensure that the `"groups"` array has an object to define the custom control group that will hold your drop down menu control. The following is an example. Note the following about this JSON: - - The "id" must be unique across all groups in all ribbon objects in the manifest. Maximum length is 64 characters. - - The "label" appears on the group on the ribbon. Although its maximum length is 64 characters, to ensure that the control group fits correctly in the ribbon, we recommend that you limit the "label" to 16 characters. - - One of the "icons" appears on the group only if the Office application window, and hence the ribbon, has been sized by the user too small for any of the controls in the group to appear. Office decides when to use one of these icons and which one to use based on the size of the window and the resolution of the device. You cannot control this. You must provide image files for 16, 32, and 80 pixels, while five other sizes are also supported (20, 24, 40, 48, and 64 pixels). You must use Secure Sockets Layer (SSL) for all URLs. + - The `"id"` must be unique across all groups in all ribbon objects in the manifest. Maximum length is 64 characters. + - The `"label"` appears on the group on the ribbon. Although its maximum length is 64 characters, to ensure that the control group fits correctly in the ribbon, we recommend that you limit the `"label"` to 16 characters. + - One of the `"icons"` appears on the group only if the Office application window, and hence the ribbon, has been sized by the user too small for any of the controls in the group to appear. Office decides when to use one of these icons and which one to use based on the size of the window and the resolution of the device. You cannot control this. You must provide image files for 16, 32, and 80 pixels, while five other sizes are also supported (20, 24, 40, 48, and 64 pixels). You must use Secure Sockets Layer (SSL) for all URLs. ```json "groups": [ @@ -512,12 +508,12 @@ Carry out the steps of the following sections: ] ``` -1. Ensure that there is a control object in the "controls" array. The following is an example. Note the following about this JSON: +1. Ensure that there is a control object in the `"controls"` array. The following is an example. Note the following about this JSON: - - The "id", "label", and "icons" properties have the same purpose and the same restrictions as the corresponding properties of a group object, except that they apply to the drop down menu within the group. - - The "type" property is set to "menu" which means that the control will be a drop down menu. - - The "supertip.title" (maximum length: 64 characters) and "supertip.description" (maximum length: 128 characters) appear when the cursor is hovering over the menu. - - The "items" property contains the JSON for the two menu options. The values are added in later steps. + - The `"id"`, `"label"`, and `"icons"` properties have the same purpose and the same restrictions as the corresponding properties of a group object, except that they apply to the drop down menu within the group. + - The `"type"` property is set to `"menu"` which means that the control will be a drop down menu. + - The `"supertip.title"` (maximum length: 64 characters) and `"supertip.description"` (maximum length: 128 characters) appear when the cursor is hovering over the menu. + - The `"items"` property contains the JSON for the two menu options. The values are added in later steps. ```json { @@ -563,10 +559,10 @@ Carry out the steps of the following sections: 1. The first item shows a task pane. The following is an example. Note the following about this code: - - The "id", "label", and "supertip" properties have the same purpose and the same restrictions as the corresponding properties of the parent menu object, except that they apply to just this menu option. - - The "icons" property is optional for menu items and there isn't one in this example. If you include one, it has the same purposes and restrictions as the "icons" property of the parent menu, except that the icon appears on the menu item beside the label. - - The "type" property is set to "menuItem". - - The "actionId" must be an exact match for the "runtimes.actions.id" that you set in [Configure the runtime for the task pane command](#configure-the-runtime-for-the-task-pane-command). + - The `"id"`, `"label"`, and `"supertip"` properties have the same purpose and the same restrictions as the corresponding properties of the parent menu object, except that they apply to just this menu option. + - The `"icons"` property is optional for menu items and there isn't one in this example. If you include one, it has the same purposes and restrictions as the `"icons"` property of the parent menu, except that the icon appears on the menu item beside the label. + - The `"type"` property is set to `"menuItem"`. + - The `"actionId"` must be an exact match for the `"runtimes.actions.id"` that you set in [Configure the runtime for the task pane command](#configure-the-runtime-for-the-task-pane-command). ```json { @@ -583,7 +579,7 @@ Carry out the steps of the following sections: 1. The second item runs a function command. The following is an example. Note the following about this code: - - The "actionId" must be an exact match for the "runtimes.actions.id" that you set in [Configure the runtime for the function command](#configure-the-runtime-for-the-function-command). + - The `"actionId"` must be an exact match for the `"runtimes.actions.id"` that you set in [Configure the runtime for the function command](#configure-the-runtime-for-the-function-command). ```json { @@ -603,4 +599,4 @@ You've now completed adding a menu to your add-in. [Sideload and test it](../tes ## See also - [Add-in commands](../design/add-in-commands.md) -- [Unified manifest for Microsoft 365](json-manifest-overview.md). +- [Unified manifest for Microsoft 365](unified-manifest-overview.md) diff --git a/docs/develop/create-addin-commands.md b/docs/develop/create-addin-commands.md index 2cb95ee146..0edfd3557c 100644 --- a/docs/develop/create-addin-commands.md +++ b/docs/develop/create-addin-commands.md @@ -1,7 +1,7 @@ ---- +--- title: Create add-in commands with the add-in only manifest description: Configure an add-in only manifest to define add-in commands for Excel, Outlook, PowerPoint, and Word. Use add-in commands to create UI elements, add buttons or menus, and perform actions. -ms.date: 09/05/2024 +ms.date: 02/28/2025 ms.localizationpriority: medium --- @@ -28,24 +28,24 @@ The following steps explain how to add add-in commands to an existing add-in. ### Step 1: Add VersionOverrides element -The [**\<VersionOverrides\>** element](/javascript/api/manifest/versionoverrides) is the root element that contains the definition of your add-in command. Details on the valid attributes and implications are found in [Version overrides in the manifest](xml-manifest-overview.md?tabs=tabid-1#version-overrides-in-the-manifest). +The [`<VersionOverrides>` element](/javascript/api/manifest/versionoverrides) is the root element that contains the definition of your add-in command. Details on the valid attributes and implications are found in [Version overrides in the manifest](xml-manifest-overview.md?tabs=tabid-1#version-overrides-in-the-manifest). -The following example shows the **\<VersionOverrides\>** element and its child elements. +The following example shows the `<VersionOverrides>` element and its child elements. ```xml <OfficeApp> ... <VersionOverrides xmlns="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="VersionOverridesV1_0"> <Requirements> - <!-- add information about requirement sets --> + <!-- Add information about requirement sets. --> </Requirements> <Hosts> <Host xsi:type="Workbook"> - <!-- add information about form factors --> + <!-- Add information about form factors. --> </Host> </Hosts> <Resources> - <!-- add information about resources --> + <!-- Add information about resources. --> </Resources> </VersionOverrides> ... @@ -54,11 +54,11 @@ The following example shows the **\<VersionOverrides\>** element and its child e ### Step 2: Add Hosts, Host, and DesktopFormFactor elements -The [**\<Hosts\>** element](/javascript/api/manifest/hosts) contains one or more [**\<Host\>** elements](/javascript/api/manifest/host). A **\<Host\>** element specifies a particular Office application. The **\<Host\>** element contains child elements that specify the add-in commands to display after your add-in is installed in that Office application. To show the same add-in commands in two or more different Office applications, you must duplicate the child elements in each **\<Host\>**. +The [`<Hosts>` element](/javascript/api/manifest/hosts) contains one or more [`<Host>` elements](/javascript/api/manifest/host). A `<Host>` element specifies a particular Office application. The `<Host>` element contains child elements that specify the add-in commands to display after your add-in is installed in that Office application. To show the same add-in commands in two or more different Office applications, you must duplicate the child elements in each `<Host>`. -The [**\<DesktopFormFactor\>**](/javascript/api/manifest/desktopformfactor) element specifies the settings for an add-in that runs in Office on the web, Windows, and Mac. +The [`<DesktopFormFactor>`](/javascript/api/manifest/desktopformfactor) element specifies the settings for an add-in that runs in Office on the web, Windows, and Mac. -The following example shows the **\<Hosts\>**, **\<Host\>**, and **\<DesktopFormFactor\>** elements. +The following example shows the `<Hosts>`, `<Host>`, and `<DesktopFormFactor>` elements. ```xml <OfficeApp> @@ -69,7 +69,7 @@ The following example shows the **\<Hosts\>**, **\<Host\>**, and **\<DesktopForm <Host xsi:type="Workbook"> <DesktopFormFactor> - <!-- information about FunctionFile and ExtensionPoint --> + <!-- Information about FunctionFile and ExtensionPoint. --> </DesktopFormFactor> </Host> @@ -82,21 +82,21 @@ The following example shows the **\<Hosts\>**, **\<Host\>**, and **\<DesktopForm ### Step 3: Add the FunctionFile element -The [**\<FunctionFile\>** element](/javascript/api/manifest/functionfile) specifies a file that contains JavaScript code to run when an add-in command uses the **ExecuteFunction** action. The **\<FunctionFile\>** element's **resid** attribute is set to a HTML file that includes all the JavaScript files your add-in commands require. You can't link directly to a JavaScript file. You can only link to an HTML file. The file name is specified as a [**\<Url\>** element](/javascript/api/manifest/url) in the [**\<Resources\>** element](/javascript/api/manifest/resources). +The [`<FunctionFile>` element](/javascript/api/manifest/functionfile) specifies a file that contains JavaScript or TypeScript code to run when an add-in command uses the **ExecuteFunction** action. The `<FunctionFile>` element's **resid** attribute is set to a HTML file that includes all the JavaScript or TypeScript files your add-in commands require. You can't link directly to a JavaScript or TypeScript file. You can only link to an HTML file. The file name is specified as a [`<Url>` element](/javascript/api/manifest/url) in the [`<Resources>` element](/javascript/api/manifest/resources). > [!NOTE] -> The Yo Office projects use [webpack](https://webpack.js.org/concepts/) to avoid manually adding the JavaScript to the HTML. +> The Yo Office projects use [webpack](https://webpack.js.org/concepts/) to avoid manually adding the JavaScript or TypeScript to the HTML. -The following is an example of the **\<FunctionFile\>** element. +The following is an example of the `<FunctionFile>` element. ```xml <DesktopFormFactor> <FunctionFile resid="Commands.Url" /> <ExtensionPoint xsi:type="PrimaryCommandSurface"> - <!-- information about this extension point --> + <!-- Information about this extension point. --> </ExtensionPoint> - <!-- You can define more than one ExtensionPoint element as needed --> + <!-- You can define more than one ExtensionPoint element as needed. --> </DesktopFormFactor> ``` @@ -109,9 +109,9 @@ When an add-in needs to provide status updates, such as progress indicators or e ### Step 4: Add ExtensionPoint elements -The [**\<ExtensionPoint\>** element](/javascript/api/manifest/extensionpoint) defines where add-in commands should appear in the Office UI. +The [`<ExtensionPoint>` element](/javascript/api/manifest/extensionpoint) defines where add-in commands should appear in the Office UI. -The following examples show how to use the **\<ExtensionPoint\>** element with **PrimaryCommandSurface** and **ContextMenu** attribute values, and the child elements that should be used with each. +The following examples show how to use the `<ExtensionPoint>` element with **PrimaryCommandSurface** and **ContextMenu** attribute values, and the child elements that should be used with each. > [!IMPORTANT] > For elements that contain an ID attribute, make sure you provide a unique ID. We recommend that you use your company's name along with your ID. For example, use the following format: `<CustomTab id="mycompanyname.mygroupname">`. @@ -119,7 +119,7 @@ The following examples show how to use the **\<ExtensionPoint\>** element with * ```xml <ExtensionPoint xsi:type="PrimaryCommandSurface"> <CustomTab id="Contoso Tab"> - <!-- If you want to use a default tab that comes with Office, remove the above CustomTab element, and then uncomment the following OfficeTab element --> + <!-- If you want to use a default tab that comes with Office, remove the above CustomTab element, and then uncomment the following OfficeTab element. --> <!-- <OfficeTab id="TabData"> --> <Label resid="residLabel4" /> <Group id="Group1Id12"> @@ -131,32 +131,33 @@ The following examples show how to use the **\<ExtensionPoint\>** element with * </Icon> <Control xsi:type="Button" id="Button1Id1"> - <!-- information about the control --> + <!-- Information about the control. --> </Control> - <!-- other controls, as needed --> + <!-- Other controls, as needed. --> </Group> </CustomTab> </ExtensionPoint> <ExtensionPoint xsi:type="ContextMenu"> <OfficeMenu id="ContextMenuCell"> <Control xsi:type="Menu" id="ContextMenu2"> - <!-- information about the control --> + <!-- Information about the control. --> </Control> - <!-- other controls, as needed --> + <!-- Other controls, as needed. --> </OfficeMenu> </ExtensionPoint> ``` ### Step 5: Add Control elements -The [**\<Control\>** element](/javascript/api/manifest/control) defines the usable surface of command (button, menu, etc) and the action associated with it. +The [`<Control>` element](/javascript/api/manifest/control) defines the usable surface of command, such as a button or menu, and the action associated with it. #### Button controls -A [button control](/javascript/api/manifest/control-button) performs a single action when the user selects it. It can either execute a JavaScript function or show a task pane. The following example shows how to define two buttons. The first button runs a JavaScript function without showing a UI, and the second button shows a task pane. In the **\<Control\>** element: +A [button control](/javascript/api/manifest/control-button) performs a single action when the user selects it. It can either run a JavaScript or TypeScript function or show a task pane. The following example shows how to define two buttons. The first button runs a JavaScript function without showing a UI, and the second button shows a task pane. In the `<Control>` element: - The **type** attribute is required, and must be set to **Button**. -- The **id** attribute of the **\<Control\>** element is a string with a maximum of 125 characters. +- The **id** attribute of the `<Control>` element is a string with a maximum of 125 characters. +- The **xsi:type** attribute of the child [`<Action>` element](/javascript/api/manifest/action) must be set to **ExecuteFunction** to run a function or **ShowTaskpane** to display a task pane. ```xml <!-- Define a control that calls a JavaScript function. --> @@ -194,38 +195,6 @@ A [button control](/javascript/api/manifest/control-button) performs a single ac </Control> ``` -The following code shows an example function used by **\<FunctionName\>**. Note the call to [`event.completed`](/javascript/api/office/office.addincommands.event#office-office-addincommands-event-completed-member(1)). This signals that you've successfully handled the event. When a function is called multiple times, such as multiple clicks on the same add-in command, all events are automatically queued. The first event runs automatically, while the other events remain on the queue. When your function calls `event.completed`, the next queued call to that function runs. You must implement `event.completed`, otherwise your function won't run. - -```js -// Initialize the Office Add-in. -Office.onReady(() => { - // If needed, Office.js is ready to be called -}); - -// The command function. -async function highlightSelection(event) { - - // Implement your custom code here. The following code is a simple Excel example. - try { - await Excel.run(async (context) => { - const range = context.workbook.getSelectedRange(); - range.format.fill.color = "yellow"; - await context.sync(); - }); - } catch (error) { - // Note: In a production add-in, notify the user through your add-in's UI. - console.error(error); - } - - // Calling event.completed is required. event.completed lets the platform know that processing has completed. - event.completed(); -} - -// You must register the function with the following line. -Office.actions.associate("highlightSelection", highlightSelection); - -``` - #### Menu controls A [menu control](/javascript/api/manifest/control-menu) can be used with either **PrimaryCommandSurface** or **ContextMenu**, and defines: @@ -233,9 +202,9 @@ A [menu control](/javascript/api/manifest/control-menu) can be used with either - A root-level menu item. - A list of submenu items. -When used with **PrimaryCommandSurface**, the root menu item displays as a button on the ribbon. When the button is selected, the submenu displays as a drop-down list. When used with **ContextMenu**, a menu item with a submenu is inserted on the context menu. In both cases, individual submenu items can either execute a JavaScript function or show a task pane. Only one level of submenus is supported at this time. +When used with **PrimaryCommandSurface**, the root menu item displays as a button on the ribbon. When the button is selected, the submenu displays as a drop-down list. When used with **ContextMenu**, a menu item with a submenu is inserted on the context menu. In both cases, individual submenu items can either run a JavaScript or TypeScript function or show a task pane. Only one level of submenus is supported at this time. -The following example shows how to define a menu item with two submenu items. The first submenu item shows a task pane, and the second submenu item runs a JavaScript function. In the **\<Control\>** element: +The following example shows how to define a menu item with two submenu items. The first submenu item shows a task pane, and the second submenu item runs a JavaScript function. In the `<Control>` element: - The **xsi:type** attribute is required, and must be set to **Menu**. - The **id** attribute is a string with a maximum of 125 characters. @@ -288,11 +257,48 @@ The following example shows how to define a menu item with two submenu items. Th </Control> ``` +#### Sample code for function commands + +The following code shows a function that's invoked by a button or menu item control whose `<Action>` element's **xsi:type** is set to **ExecuteFunction**. Note the following about the code. + +- The [Office.actions.associate](/javascript/api/office/office.actions#office-office-actions-associate-member(1)) call tells Office which function to run when a button or menu item is selected. The value passed to its **actionId** parameter must match the value specified in the [`<FunctionName>` element](/javascript/api/manifest/action#functionname) of the manifest. You must have an `Office.actions.associate` call for every function command defined in the manifest. +- The [event.completed](/javascript/api/office/office.addincommands.event#office-office-addincommands-event-completed-member(1)) call signals that you've successfully handled the event. When a function is called multiple times, such as multiple clicks on the same add-in command, all events are automatically queued. The first event runs automatically, while the other events remain on the queue. When your function calls `event.completed`, the next queued call to that function runs. You must implement `event.completed`, otherwise your function won't run. + +```js +// Initialize the Office Add-in. +Office.onReady(() => { + // If needed, Office.js is ready to be called. +}); + +// The command function. +async function highlightSelection(event) { + + // Implement your custom code here. The following code is a simple Excel example. + try { + await Excel.run(async (context) => { + const range = context.workbook.getSelectedRange(); + range.format.fill.color = "yellow"; + await context.sync(); + }); + } catch (error) { + // Note: In a production add-in, notify the user through your add-in's UI. + console.error(error); + } + + // Calling event.completed is required. The event.completed call lets the platform know that processing has completed. + event.completed(); +} + +// This maps the function to the action ID specified in the manifest. +Office.actions.associate("highlightSelection", highlightSelection); + +``` + ### Step 6: Add the Resources element -The [**\<Resources\>** element](/javascript/api/manifest/resources) contains resources used by the different child elements of the **\<VersionOverrides\>** element. Resources include icons, strings, and URLs. An element in the manifest can use a resource by referencing the **id** of the resource. Using the **id** helps organize the manifest, especially when there are different versions of the resource for different locales. An **id** has a maximum of 32 characters. +The [`<Resources>` element](/javascript/api/manifest/resources) contains resources used by the different child elements of the `<VersionOverrides>` element. Resources include icons, strings, and URLs. An element in the manifest can use a resource by referencing the **id** of the resource. Using the **id** helps organize the manifest, especially when there are different versions of the resource for different locales. An **id** has a maximum of 32 characters. -The following shows an example of how to use the **\<Resources\>** element. Each resource can have one or more [**\<Override\>** child elements](/javascript/api/manifest/override) to define a different resource for a specific locale. +The following shows an example of how to use the `<Resources>` element. Each resource can have one or more [`<Override>` child elements](/javascript/api/manifest/override) to define a different resource for a specific locale. ```xml <Resources> @@ -326,7 +332,7 @@ The following shows an example of how to use the **\<Resources\>** element. Each ``` > [!NOTE] -> You must use Secure Sockets Layer (SSL) for all URLs in the **\<Image\>** and **\<Url\>** elements. +> You must use Secure Sockets Layer (SSL) for all URLs in the `<Image>` and `<Url>` elements. ## Outlook support notes diff --git a/docs/develop/create-sso-office-add-ins-aspnet.md b/docs/develop/create-sso-office-add-ins-aspnet.md index ec081139b9..430ab01237 100644 --- a/docs/develop/create-sso-office-add-ins-aspnet.md +++ b/docs/develop/create-sso-office-add-ins-aspnet.md @@ -1,4 +1,4 @@ ---- +--- title: Create an ASP.NET Office Add-in that uses single sign-on (SSO) description: A step-by-step guide for how to create (or convert) an Office Add-in with an ASP.NET backend to use single sign-on (SSO). ms.date: 05/20/2023 @@ -69,7 +69,7 @@ Use the following values for placeholders for the subsequent app registration st 1. Replace the placeholder "Enter_client_ID_here" _in both places_ in the markup with the **Application ID** that you copied when you created the **Office-Add-in-ASPNET-SSO** app registration. This is the same ID you used for the application ID in the appsettings.json file. > [!NOTE] - > The **\<Resource\>** value is the **Application ID URI** you set when you registered the add-in. The **\<Scopes\>** section is used only to generate a consent dialog box if the add-in is sold through AppSource. + > The `<Resource>` value is the **Application ID URI** you set when you registered the add-in. The `<Scopes>` section is used only to generate a consent dialog box if the add-in is sold through Microsoft Marketplace. 1. Save and close the manifest file. @@ -372,7 +372,7 @@ The server-side code is an ASP.NET Core server that provides REST APIs for the c :::image type="content" source="../images/select-host.png" alt-text="Choose the desired Office client application: Excel, PowerPoint, or Word."::: -1. Press F5. Or select **Debug > Start Debugging**. +1. Press <kbd>F5</kbd>. Or select **Debug** > **Start Debugging**. 1. In the Office application, select the **Show Add-in** in the **SSO ASP.NET** group to open the task pane add-in. 1. Select **Get OneDrive File Names**. If you're logged into Office with either a Microsoft 365 Education or work account, or a Microsoft account, and SSO is working as expected, the first 10 file and folder names in your OneDrive for Business are displayed on the task pane. If you are not logged in, or you are in a scenario that does not support SSO, or SSO is not working for any reason, you will be prompted to sign in. After you sign in, the file and folder names appear. diff --git a/docs/develop/create-sso-office-add-ins-nodejs.md b/docs/develop/create-sso-office-add-ins-nodejs.md index b75a8f0200..a7e5ef528e 100644 --- a/docs/develop/create-sso-office-add-ins-nodejs.md +++ b/docs/develop/create-sso-office-add-ins-nodejs.md @@ -1,4 +1,4 @@ ---- +--- title: Create a Node.js Office Add-in that uses single sign-on description: Learn how to create a Node.js-based add-in that uses Office Single Sign-on. ms.date: 05/20/2023 @@ -88,7 +88,7 @@ Use the following values for placeholders for the subsequent app registration st 1. Replace the placeholder "$app-id-guid$" _in both places_ in the markup with the **Application ID** that you copied when you created the **Office-Add-in-NodeJS-SSO** app registration. The "$" symbols are not part of the ID, so don't include them. This is the same ID you used for the CLIENT_ID in the .ENV file. > [!NOTE] - > The **\<Resource\>** value is the **Application ID URI** you set when you registered the add-in. The **\<Scopes\>** section is used only to generate a consent dialog box if the add-in is sold through AppSource. + > The `<Resource>` value is the **Application ID URI** you set when you registered the add-in. The `<Scopes>` section is used only to generate a consent dialog box if the add-in is sold through Microsoft Marketplace. 1. Open the `\public\javascripts\fallback-msal\authConfig.js` file. Replace the placeholder "$app-id-guid$" with the application ID that you saved from the **Office-Add-in-NodeJS-SSO** app registration you created previously. diff --git a/docs/develop/debug-office-add-ins-in-visual-studio.md b/docs/develop/debug-office-add-ins-in-visual-studio.md index 0ebbb55a50..a9a31e258f 100644 --- a/docs/develop/debug-office-add-ins-in-visual-studio.md +++ b/docs/develop/debug-office-add-ins-in-visual-studio.md @@ -1,7 +1,7 @@ --- title: Debug Office Add-ins in Visual Studio description: Use Visual Studio to debug Office Add-ins in the Office desktop client on Windows. -ms.date: 03/28/2024 +ms.date: 02/19/2025 ms.localizationpriority: medium --- @@ -14,7 +14,7 @@ This article describes how to debug client-side code in Office Add-ins that are ## Review the build and debug properties -Before you start debugging, review the properties of each project to confirm that Visual Studio will open the desired Office application and that other build and debug properties are set appropriately. +Before you start debugging, review the properties of each project in the solution to confirm that Visual Studio will open the desired Office application and that other build and debug properties are set appropriately. ### Add-in project properties @@ -69,7 +69,7 @@ This section describes how to start and debug an add-in in desktop Office on Win ### Start the add-in project -Start the project by choosing **Debug** > **Start Debugging** from the menu bar or press the F5 button. Visual Studio automatically builds the solution and starts the Office host application. +Start the project by choosing **Debug** > **Start Debugging** from the menu bar or press the <kbd>F5</kbd> button. Visual Studio automatically builds the solution and starts the Office host application. When Visual Studio builds the project, it performs the following tasks: @@ -84,6 +84,9 @@ When Visual Studio builds the project, it performs the following tasks: > [!NOTE] > If Office uses the Edge Legacy webview control (EdgeHTML) to run add-ins on your Windows computer, Visual Studio may prompt you to add a local network loopback exemption. This is required for the webview control to be able to access the website deployed to the local IIS web server. You can also change this setting anytime in Visual Studio under **Tools** > **Options** > **Office Tools (Web)** > **Web Add-In Debugging**. To find out what webview control is used on your Windows computer, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). +> [!TIP] +> [!INCLUDE[Identify the webview through the add-in UI](../includes/identify-webview-in-ui.md)] + Next, Visual Studio does the following: 1. Modifies the [SourceLocation](/javascript/api/manifest/sourcelocation) element of the add-in only manifest file (that was copied to the `_ProjectName_\bin\Debug\OfficeAppManifests` directory) by replacing the `~remoteAppUrl` token with the fully qualified address of the start page (for example, `https://localhost:44302/Home.html`). @@ -93,13 +96,16 @@ Next, Visual Studio does the following: 1. Validates the manifest. > [!IMPORTANT] - > If you get validation errors for the manifest, it may be that Visual Studio's manifest schema files haven't been updated to support the latest features. Your first troubleshooting step should be to replace one or more of these files with the latest versions. For detailed instructions, see [Manifest schema validation errors in Visual Studio projects](../testing/troubleshoot-development-errors.md#manifest-schema-validation-errors-in-visual-studio-projects). + > If you get validation errors for the manifest, it may be that Visual Studio's manifest schema files haven't been updated to support the latest features. Your first troubleshooting step should be to replace one or more of these files with the latest versions. For detailed instructions, see [Manifest schema validation errors in Visual Studio projects](../testing/troubleshoot-development-errors.md#add-in-only-manifest-schema-validation-errors-in-visual-studio-projects). 1. Opens the Office application and sideloads your add-in. ### Debug the add-in -The best method for debugging an add-in in Visual Studio 2022 depends on whether the add-in is running in WebView2, which is the webview control that is associated with Microsoft Edge (Chromium), or an older webview control. To determine which webview control is being used, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). If your computer is using WebView2, see [Use the built-in Visual Studio debugger to debug on the desktop](#use-the-built-in-visual-studio-debugger-to-debug-on-the-desktop). For any other webview control, see [Use the browser developer tools to debug on the desktop](#use-the-browser-developer-tools-to-debug-on-the-desktop). +The best method for debugging an add-in in Visual Studio 2022 depends on whether the add-in is running in WebView2, which is the webview control that is associated with Microsoft Edge (Chromium), or an older webview control. If your computer is using WebView2, see [Use the built-in Visual Studio debugger to debug on the desktop](#use-the-built-in-visual-studio-debugger-to-debug-on-the-desktop). For any other webview control, see [Use the browser developer tools to debug on the desktop](#use-the-browser-developer-tools-to-debug-on-the-desktop). To determine which webview control is being used, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). + +> [!TIP] +> [!INCLUDE[Identify the webview through the add-in UI](../includes/identify-webview-in-ui.md)] #### Use the built-in Visual Studio debugger to debug on the desktop @@ -117,15 +123,7 @@ The best method for debugging an add-in in Visual Studio 2022 depends on whether 1. Follow the steps in the earlier section [Start the add-in project](#start-the-add-in-project). -1. Launch the add-in in the Office application if it isn't already open. For example, if it's a task pane add-in, it'll have added a button to the **Home** ribbon (for example, a **Show Taskpane** button). Select the button on the ribbon. - - > [!NOTE] - > If your add-in isn't sideloaded by Visual Studio, you can sideload it manually. Follow the instructions to [Sideload an Office Add-in for testing](../testing/test-debug-office-add-ins.md#sideload-an-office-add-in-for-testing) for your platform. - > - > In the list of available add-ins, find the **Developer Add-ins** section and select the your add-in to register it. - - > [!TIP] - > The task pane may appear blank when it first opens. If so, it should render correctly when you launch the debugging tools in a later step. +1. Launch the add-in in the Office application if it isn't already open. For example, if it's a task pane add-in, it'll have added a button (for example, a **Show Taskpane** button) to the **Home** ribbon or to a custom ribbon tab that's installed with the add-in. Select the button on the ribbon. 1. Open the [personality menu](../design/task-pane-add-ins.md#personality-menu) and then choose **Attach a debugger**. This action opens the debugging tools for the webview control that Office is using to run add-ins on your Windows computer. You can set breakpoints and step through code as described in one of the following articles: @@ -141,10 +139,10 @@ This section describes how to start and debug an add-in in desktop Office on the ### Start the add-in project on the web -Start the project by choosing **Debug** > **Start Debugging** from the menu bar or press the F5 button. Visual Studio automatically builds the solution and launches the Office application host page of your Microsoft 365 tenancy. +Start the project by choosing **Debug** > **Start Debugging** from the menu bar or press the <kbd>F5</kbd> button. Visual Studio automatically builds the solution and launches the Office application host page of your Microsoft 365 tenancy. > [!NOTE] -> When you're debugging an add-in on the web, you may get an AADSTS50011 error similar to the following: +> When you're debugging an add-in on the web, you may get an AADSTS50011 error similar to the following: > > "The redirect URI `{Full absolute URL to add-in home page}` specified in the request doesn't match the redirect URIs configured for the application ... " > @@ -163,7 +161,7 @@ Start the project by choosing **Debug** > **Start Debugging** from the menu bar > ``` > > 1. Run the script in PowerShell. -> 1. Restart the project by choosing **Debug** > **Start Debugging** from the menu bar or press the F5 button. +> 1. Restart the project by choosing **Debug** > **Start Debugging** from the menu bar or press the <kbd>F5</kbd> button. When Visual Studio builds the project it performs the following tasks. @@ -182,13 +180,19 @@ Next, Visual Studio does the following: 1. Validates the manifest. > [!IMPORTANT] - > If you get validation errors for the manifest, it may be that Visual Studio's manifest schema files haven't been updated to support the latest features. Your first troubleshooting step should be to replace one or more of these files with the latest versions. For detailed instructions, see [Manifest schema validation errors in Visual Studio projects](../testing/troubleshoot-development-errors.md#manifest-schema-validation-errors-in-visual-studio-projects). + > If you get validation errors for the manifest, it may be that Visual Studio's manifest schema files haven't been updated to support the latest features. Your first troubleshooting step should be to replace one or more of these files with the latest versions. For detailed instructions, see [Manifest schema validation errors in Visual Studio projects](../testing/troubleshoot-development-errors.md#add-in-only-manifest-schema-validation-errors-in-visual-studio-projects). 1. Opens the Office application host page of your Microsoft 365 tenancy in Microsoft Edge. +> [!TIP] +> If for any reason, Visual Studio doesn't fully sideload the add-in and none of the fixes earlier works, you can manually sideload it. Follow the steps in [Sideload an add-in to Microsoft 365](../testing/sideload-office-add-ins-for-testing.md#sideload-an-add-in-to-microsoft-365). When you're instructed to browse to the manifest, navigate to the XML file in the folder `_ProjectName_\bin\Debug\OfficeAppManifests` directory. + ### Debug the add-in on the web -The best method for debugging an add-in in Visual Studio 2022 depends on whether the add-in is running in WebView2, which is the webview control that is associated with Microsoft Edge (Chromium), or an older webview control. To determine which webview control is being used, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). If your computer is using WebView2, see [Use the built-in Visual Studio debugger to debug on the web](#use-the-built-in-visual-studio-debugger-to-debug-on-the-web). For any other webview control, see [Use the browser developer tools to debug on the web](#use-the-browser-developer-tools-to-debug-on-the-web). +The best method for debugging an add-in in Visual Studio 2022 depends on whether the add-in is running in WebView2, which is the webview control that is associated with Microsoft Edge (Chromium), or an older webview control. If your computer is using WebView2, see [Use the built-in Visual Studio debugger to debug on the web](#use-the-built-in-visual-studio-debugger-to-debug-on-the-web). For any other webview control, see [Use the browser developer tools to debug on the web](#use-the-browser-developer-tools-to-debug-on-the-web). To determine which webview control is being used, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). + +> [!TIP] +> [!INCLUDE[Identify the webview through the add-in UI](../includes/identify-webview-in-ui.md)] #### Use the built-in Visual Studio debugger to debug on the web @@ -203,9 +207,9 @@ The best method for debugging an add-in in Visual Studio 2022 depends on whether #### Use the browser developer tools to debug on the web -1. For an add-in in any host except Outlook, in the Office host application page, press F12 to open the debugging tool. +1. For an add-in in any host except Outlook, in the Office host application page, press <kbd>F12</kbd> to open the debugging tool. -1. For an Outlook add-in, if the add-in's manifest is configured for a read surface, select an email message or appointment item to open it in its own window. If the add-in is configured for only a compose surface, open a new message, reply to message, or new appointment window. Ensure that the appropriate window has focus and press F12 to pen the debugging tool. +1. For an Outlook add-in, if the add-in's manifest is configured for a read surface, select an email message or appointment item to open it in its own window. If the add-in is configured for only a compose surface, open a new message, reply to message, or new appointment window. Ensure that the appropriate window has focus and press <kbd>F12</kbd> to pen the debugging tool. 1. After the tool is open, launch the add-in. The exact steps vary depending on the design of your add-in. Typically, you press a button to open a task pane. In Outlook, in the toolbar at the top of the window, select the **More apps** button, and then select your add-in from the callout that opens. @@ -219,7 +223,7 @@ The best method for debugging an add-in in Visual Studio 2022 depends on whether > [!TIP] > To debug code that runs in the `Office.initialize` function or an `Office.onReady` function that runs when the add-in opens, set your breakpoints, and then close and reopen the add-in. For more information about these functions, see [Initialize your Office Add-in](../develop/initialize-add-in.md). -1. To make changes to your code, first stop the debugging session in Visual Studio and close the Outlook pages. Make your changes, and start a new debugging session. +1. To make changes to your code, first stop the debugging session in Visual Studio and close the Office on the web page. Make your changes, and start a new debugging session. ## Use an existing document to debug the add-in diff --git a/docs/develop/develop-add-ins-vscode.md b/docs/develop/develop-add-ins-vscode.md index 48c81dcd4f..fad4d4ceed 100644 --- a/docs/develop/develop-add-ins-vscode.md +++ b/docs/develop/develop-add-ins-vscode.md @@ -2,7 +2,7 @@ title: Develop Office Add-ins with Visual Studio Code description: How to develop Office Add-ins with Visual Studio Code. ms.topic: overview -ms.date: 08/15/2024 +ms.date: 10/08/2025 ms.localizationpriority: high --- @@ -33,7 +33,7 @@ When the Yeoman generator finishes creating the add-in project, open the root fo The Yeoman generator creates a basic add-in with limited functionality. You can customize the add-in by editing the [manifest](add-in-manifests.md), HTML, JavaScript or TypeScript, and CSS files in VS Code. For a high-level description of the project structure and files in the add-in project that the Yeoman generator creates, see the Yeoman generator guidance within the [5-minute quick start](../index.yml) that corresponds to the type of add-in you've created. -### Create the add-in project using the Office Add-ins Development Kit (preview) +### Create the add-in project using the Office Add-ins Development Kit The [Office Add-ins Development Kit](https://marketplace.visualstudio.com/items?itemName=msoffice.microsoft-office-add-in-debugger) is a Visual Studio Code extension that allows you to create new projects directly from VS Code. For information on installing the extension and creating projects from templates and samples, see [Create Office Add-in projects using Office Add-ins Development Kit for Visual Studio Code](development-kit-overview.md). diff --git a/docs/develop/develop-office-add-ins-for-the-ipad.md b/docs/develop/develop-office-add-ins-for-the-ipad.md index 29331b2564..975fc7c8f3 100644 --- a/docs/develop/develop-office-add-ins-for-the-ipad.md +++ b/docs/develop/develop-office-add-ins-for-the-ipad.md @@ -1,47 +1,72 @@ ---- +--- title: Special requirements for add-ins on the iPad description: Learn some requirements for creating an Office Add-in that runs on an iPad. ms.topic: best-practice -ms.date: 08/15/2024 +ms.date: 07/29/2025 ms.localizationpriority: medium --- # Special requirements for add-ins on the iPad -If your add-in uses only Office APIs that are supported on the iPad, then customers can install it on iPads (see [Specify Office applications and API requirements](specify-office-hosts-and-api-requirements.md) for more information.) If the add-in is published in [AppSource](https://appsource.microsoft.com), then there are some requirements for add-ins that can be installed on iPads, in addition to [the best practices that apply to all Office Add-ins](../concepts/add-in-development-best-practices.md). +You'll need to make additional considerations if you want to make your add-in available on iPad. If your add-in uses only Office APIs that are supported on iPad, customers can install it on their devices. However, if you're publishing to [Microsoft Marketplace](https://marketplace.microsoft.com), there are some additional requirements you'll need to meet. + +For details on API compatibility, see [Specify Office applications and API requirements](../develop/specify-office-hosts-and-api-requirements.md). -The following table lists the tasks to perform. +## iPad Microsoft Marketplace requirements + +Here's what you need to know when submitting your add-in to Microsoft Marketplace for iPad users. |Task|Description|Resources| |:-----|:-----|:-----| -|Apply iOS design best practices.|Integrate your add-in UI seamlessly with the iOS experience.| See note following this table. | -|Optimize your add-in for touch.|Make your UI responsive to touch inputs in addition to mouse and keyboard.|[Apply UX design principles](../concepts/add-in-development-best-practices.md#apply-ux-design-principles)| -|Make your add-in free.|Office on iPad is a channel through which you can reach more users and promote your services. These new users have the potential to become your customers.|[Certification policy 1120.2](/legal/marketplace/certification-policies#11202-mobile-requirements)| -|Make your add-in commerce free on the iPad.|When it's running on the iPad, your add-in must be free of in-app purchases, trial offers, UI that aims to upsell to a non-free version, or links to any online stores where users can purchase or acquire other content, apps, or add-ins. Your Privacy Policy and Terms of Use pages must also be free of any commerce UI or AppSource links.|[Certification policy 1100.3](/legal/marketplace/certification-policies#11003-selling-additional-features)<br><br>Your add-in can still have commerce on other platforms. To do so, test the [Office.context.commerceAllowed](/javascript/api/office/office.context#office-office-context-commerceallowed-member) property and suppress all commerce when it returns `false`.| -|Submit your add-in to AppSource.|In Partner Center, on the **Product setup** page, select the **Make my product available on iOS and Android (if applicable)** check box, and provide your Apple developer ID in Account settings. Review the [Application Provider Agreement](https://go.microsoft.com/fwlink/?linkid=715691) to make sure you understand the terms.|[Make your solutions available in AppSource and within Office](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center)| +|Apply iOS design best practices.|Make your add-in UI feel native to iOS by following Apple's design guidelines.|[Designing for iOS](https://developer.apple.com/design/human-interface-guidelines/designing-for-ios)| +|Make your add-in free.|Your add-in must be free on iPad. Office on iPad is a great way to reach new users who might become customers on other platforms.|[Certification policy 1120.2](/legal/marketplace/certification-policies#11202-mobile-requirements)| +|Remove commerce features on iPad.|When running on iPad, your add-in can't include in-app purchases, trial offers, upselling UI, or links to online stores. Your Privacy Policy and Terms of Use pages must also be commerce-free. You can still have commerce on other platforms. Check the [Office.context.commerceAllowed](/javascript/api/office/office.context#office-office-context-commerceallowed-member) property and hide commerce features when it returns `false`.|[Certification policy 1100.3](/legal/marketplace/certification-policies#11003-selling-additional-features)| +|Submit to Microsoft Marketplace correctly.|In Partner Center, go to the **Product setup** page and select **Make my product available on iOS and Android (if applicable)**. You'll also need to provide your Apple developer ID in Account settings. Don't forget to review the [Application Provider Agreement](https://go.microsoft.com/fwlink/?linkid=715691).|[Make your solutions available in Microsoft Marketplace and within Office](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center)| -> [!NOTE] -> Your add-in can serve an alternate UI based on the device that it's running on. To detect whether your add-in is running on an iPad, you can use the following APIs. -> -> - const isTouchEnabled = [Office.context.touchEnabled](/javascript/api/office/office.context#office-office-context-touchenabled-member) -> - const allowCommerce = [Office.context.commerceAllowed](/javascript/api/office/office.context#office-office-context-commerceallowed-member) -> -> On an iPad, `touchEnabled` returns `true` and `commerceAllowed` returns `false`. -> -> For information on the best UI design practices for iPad, see [Designing for iOS](https://developer.apple.com/design/human-interface-guidelines/designing-for-ios). +## Detecting iPad devices + +Want to provide a different experience for iPad users? Your add-in can detect what device it's running on and adjust accordingly. Use the [Office.context.touchEnabled](/javascript/api/office/office.context#office-office-context-touchenabled-member) and [Office.context.commerceAllowed](/javascript/api/office/office.context#office-office-context-commerceallowed-member) properties to detect iPad devices. + +```javascript +const isTouchEnabled = Office.context.touchEnabled; +const allowCommerce = Office.context.commerceAllowed; + +// On iPad, touchEnabled returns true and commerceAllowed returns false. +if (isTouchEnabled && !allowCommerce) { + // Likely running on iPad - implement the iPad-specific UI. + enableIPadInterface(); + hideCommerceFeatures(); +} +``` -## Best practices for developing Office Add-ins that can run on iPad +## iPad development best practices -Apply the following best practices for developing add-ins that run on iPad. +Ready to start building for iPad? Here are the key practices that'll help you succeed. -- **Develop and debug the add-in on Windows or Mac and sideload it to an iPad.** +### Develop and debug on Windows or Mac, then test on iPad - You can't develop the add-in directly on an iPad, but you can develop and debug it on a Windows or Mac computer and sideload it to an iPad for testing. Because an add-in that runs in Office on iOS or Mac supports the same APIs as an add-in running in Office on Windows, your add-in's code should run the same way on these platforms. For details, see [Test and debug Office Add-ins](../testing/test-debug-office-add-ins.md) and [Sideload Office Add-ins on iPad for testing](../testing/sideload-an-office-add-in-on-ipad.md). +You can't develop directly on an iPad. Develop and debug your add-in on a Windows or Mac computer, then sideload it to an iPad for testing. Since Office add-ins use the same APIs across platforms (Windows, Mac, and iOS), your code should work consistently everywhere. -- **Specify API requirements in your add-in's manifest or with runtime checks.** +For step-by-step guidance, see: - When you specify API requirements in your add-in's manifest, Office will determine if the Office client application supports those API members. If the API members are available in the application, then your add-in will be available. Alternatively, you can perform a runtime check to determine if a method is available in the application before using it in your add-in. Runtime checks ensure that your add-in is always available in the application, and provides additional functionality if the methods are available. For more information, see [Specify Office applications and API requirements](specify-office-hosts-and-api-requirements.md). +- [Test and debug Office Add-ins](../testing/test-debug-office-add-ins.md) +- [Sideload Office Add-ins on iPad for testing](../testing/sideload-an-office-add-in-on-ipad.md) + +### Handle API compatibility with manifest requirements or runtime checks + +You have two ways to ensure your add-in works properly across different Office versions. + +**Option 1: Specify requirements in your manifest.** +When you declare API requirements in your add-in's manifest, Office automatically checks if the client app supports those APIs. If they're available, your add-in will be available too. + +**Option 2: Use runtime checks.** +Alternatively, you can check if specific methods are available before using them in your code. This approach ensures your add-in is always available and provides additional functionality when supported APIs are present. + +For detailed guidance on both approaches, see [Specify Office applications and API requirements](../develop/specify-office-hosts-and-api-requirements.md). ## Outlook add-ins on iPad For information about designing Outlook add-ins that look good and work well in Outlook on mobile devices, see [Add-ins for Outlook on mobile devices](../outlook/outlook-mobile-addins.md). + +> [!NOTE] +> If you're using [Fluent UI React](../quickstarts/fluent-react-quickstart.md) for your design elements, many of these elements are built into the design system. diff --git a/docs/develop/develop-overview.md b/docs/develop/develop-overview.md index 33d37dc812..041822130b 100644 --- a/docs/develop/develop-overview.md +++ b/docs/develop/develop-overview.md @@ -1,8 +1,8 @@ ---- +--- title: Develop Office Add-ins description: An introduction to developing Office Add-ins. ms.topic: overview -ms.date: 08/15/2024 +ms.date: 10/08/2025 ms.localizationpriority: high --- @@ -15,7 +15,7 @@ All Office Add-ins are built upon the Office Add-ins platform. For any add-in yo ## Create an Office Add-in -You can create an Office Add-in by using the [Yeoman generator for Office Add-ins](yeoman-generator-overview.md), Visual Studio, Teams Toolkit, or the [Office Add-ins Development Kit (preview)](development-kit-overview.md). +You can create an Office Add-in by using the [Yeoman generator for Office Add-ins](yeoman-generator-overview.md), Visual Studio, Microsoft 365 Agents Toolkit, or the [Office Add-ins Development Kit](development-kit-overview.md). ### Yeoman generator @@ -35,11 +35,11 @@ Create your project using HTML, CSS and JavaScript (or TypeScript), or using Rea Visual Studio can be used to create Office Add-ins for Excel, Outlook, Word, and PowerPoint. An Office Add-in project gets created as part of a Visual Studio solution and uses HTML, CSS, and JavaScript. For more information about creating add-ins with Visual Studio, see [Develop Office Add-ins with Visual Studio](../develop/develop-add-ins-visual-studio.md). -### Teams Toolkit +### Agents Toolkit -The Teams Toolkit can be used to create almost any kind of Teams App, a term which includes all extensions of Microsoft 365, including those that don't extend the Teams application. For details about creating an add-in, see [Create Office Add-in projects with Teams Toolkit](teams-toolkit-overview.md). +The Agents Toolkit can be used to create almost any kind of Microsoft 365 extension. For details about creating an add-in, see [Create Office Add-in projects with Microsoft 365 Agents Toolkit](agents-toolkit-overview.md). -### Office Add-ins Development Kit (preview) +### Office Add-ins Development Kit The Office Add-ins Development Kit is an extension for Visual Studio Code. It lets you create new add-in projects and load samples directly from the IDE. Download the extension from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=msoffice.microsoft-office-add-in-debugger) or learn more in the article [Create Office Add-in projects using Office Add-ins Development Kit for Visual Studio Code](development-kit-overview.md). @@ -64,7 +64,7 @@ An Office Add-in's manifest defines the settings and capabilities of the add-in. - Location of images that the add-in uses for branding and command iconography. - Dimensions of the add-in (for example, dimensions for content add-ins, requested height for Outlook add-ins). - Rules that specify when the add-in activates in the context of a message or appointment (for Outlook add-ins only). -- Keyboard shortcuts (for Excel only). +- Keyboard shortcuts (for Excel and Word add-ins only). For detailed information about the manifest, see [Office Add-ins manifest](add-in-manifests.md). @@ -86,7 +86,7 @@ An Office Add-in can use the Office JavaScript APIs to interact with content in #### Explore APIs with Script Lab -Script Lab is an add-in that enables you to explore the Office JavaScript API and run code snippets while you're working in an Office program such as Excel or Word. It's available for free via AppSource and is a useful tool to include in your development toolkit as you prototype and verify the functionality you want in your add-in. In Script Lab, you can access a library of built-in samples to quickly try out APIs or even use a sample as the starting point for your own code. +Script Lab is an add-in that enables you to explore the Office JavaScript API and run code snippets while you're working in an Office program such as Excel or Word. It's available for free via Microsoft Marketplace and is a useful tool to include in your development toolkit as you prototype and verify the functionality you want in your add-in. In Script Lab, you can access a library of built-in samples to quickly try out APIs or even use a sample as the starting point for your own code. The following one-minute video shows Script Lab in action. diff --git a/docs/develop/development-kit-overview.md b/docs/develop/development-kit-overview.md index 93e4a5de44..aa59b6644e 100644 --- a/docs/develop/development-kit-overview.md +++ b/docs/develop/development-kit-overview.md @@ -1,21 +1,17 @@ --- -title: Create Office Add-in projects using Office Add-ins Development Kit for Visual Studio Code (preview) +title: Create Office Add-in projects using Office Add-ins Development Kit for Visual Studio Code description: Learn how to create Office Add-in projects using Office Add-ins Development Kit extension. -ms.date: 09/09/2024 +ms.date: 10/08/2025 ms.localizationpriority: high --- -# Create Office Add-in projects using Office Add-ins Development Kit for Visual Studio Code (preview) +# Create Office Add-in projects using Office Add-ins Development Kit for Visual Studio Code The Office Add-ins Development Kit helps set up your environment, create Office Add-ins, and debug your code in a streamlined experience. [!INCLUDE [Information about the preview status of the dev kit.](../includes/dev-kit-preview-note.md)] -## Prerequisites - -- Download and install [Visual Studio Code](https://visualstudio.microsoft.com/downloads/). -- Node.js (the latest LTS version). Visit the [Node.js site](https://nodejs.org/) to download and install the right version for your operating system. To verify if you've already installed these tools, run the commands `node -v` and `npm -v` in your terminal. -- Office connected to a Microsoft 365 subscription. You might qualify for a Microsoft 365 E5 developer subscription through the [Microsoft 365 Developer Program](https://developer.microsoft.com/microsoft-365/dev-program), see [FAQ](/office/developer-program/microsoft-365-developer-program-faq#who-qualifies-for-a-microsoft-365-e5-developer-subscription-) for details. Alternatively, you can [sign up for a 1-month free trial](https://www.microsoft.com/microsoft-365/try?rtc=1) or [purchase a Microsoft 365 plan](https://www.microsoft.com/microsoft-365/buy/compare-all-microsoft-365-products). +[!include[Dev_kit prerequisites](../includes/dev-kit-prerequisites.md)] ## Install the development kit @@ -67,29 +63,8 @@ To understand how the add-in will work in an Office application, use the Office > [!NOTE] > These steps are the same as the ones listed in Visual Studio Code by the extension when you create a new project. -1. Open the extension by selecting the Office Add-ins Development Kit icon in the **Activity Bar**. -1. Select **Preview Your Office Add-in (F5)** -1. In the Quick Pick menu, select the option **{Office Host} Desktop (Edge Chromium)**. This will launch the add-in and debug the code. - -The development kit checks that the prerequisites are met before debugging starts. Check the terminal for detailed information if there are issues with your environment. After this process, the Office desktop application launches and sideloads the add-in. Please note that the first time you run a project, it may make take a few minutes to install the dependencies. You will need to install the certificate when prompted. - -## Stop testing your Office Add-in - -Once you are finished testing and debugging the add-in, close the add-in by following these steps. - -1. Open the extension by selecting the Office Add-ins Development Kit icon in the **Activity Bar**. -1. Select **Stop Previewing Your Office Add-in**. This closes the web server and removes the add-in from the registry and cache. -1. Close the Office application window at your convenience. - -## Troubleshooting - -If you have problems running the add-in, take these steps. - -- Close any open instances of Office. -- Close the previous web server started for the add-in with the **Stop Previewing Your Office Add-in** Office Add-ins Development Kit extension option. - -The article [Troubleshoot development errors with Office Add-ins](../testing/troubleshoot-development-errors.md) contains solutions to common problems. If you're still having issues, [create a GitHub issue](https://aka.ms/officedevkitnewissue) and we'll help you. +[!include[Dev_kit_start_debugging](../includes/dev-kit-start-debugging.md)] -For information on running the add-in on Office on the web, see [Sideload Office Add-ins to Office on the web](../testing/sideload-office-add-ins-for-testing.md). +[!include[Dev_kit_stop_debugging](../includes/dev-kit-stop-debugging.md)] -For information on debugging on older versions of Office, see [Debug add-ins using developer tools in Microsoft Edge Legacy](../testing/debug-add-ins-using-devtools-edge-legacy.md). +[!include[Dev_kit_troubleshooting](../includes/dev-kit-troubleshooting.md)] diff --git a/docs/develop/dialog-api-in-office-add-ins.md b/docs/develop/dialog-api-in-office-add-ins.md index 0ecf31fcac..74d9989e31 100644 --- a/docs/develop/dialog-api-in-office-add-ins.md +++ b/docs/develop/dialog-api-in-office-add-ins.md @@ -1,7 +1,7 @@ ---- +--- title: Use the Office dialog API in your Office Add-ins description: Learn the basics of creating a dialog box in an Office Add-in. -ms.date: 05/16/2024 +ms.date: 06/25/2025 ms.topic: how-to ms.localizationpriority: medium --- @@ -12,10 +12,16 @@ Use the [Office dialog API](/javascript/api/office/office.ui) to open dialog box - Sign in a user with a resource such as Google, Facebook, or Microsoft identity. For more information, see [Authenticate with the Office dialog API](auth-with-office-dialog-api.md). - Provide more screen space, or even a full screen, for some tasks in your add-in. -- Host a video that would be too small if confined to a task pane. +- [Host a video that would be too small if confined to a task pane](dialog-video.md). +- Show an error, progress, or input screen. > [!TIP] -> Because overlapping UI elements are discouraged, avoid opening a dialog box from a task pane unless your scenario requires it. When you consider how to use the surface area of a task pane, note that task panes can be tabbed. For an example of a tabbed task pane, see the [Excel Add-in JavaScript SalesTracker](https://github.com/OfficeDev/Excel-Add-in-JavaScript-SalesTracker) sample. +> +> - We recommend that you don't use a dialog box to interact with a document. Use a task pane instead. For guidance, see [Task panes in Office Add-ins](../design/task-pane-add-ins.md). +> +> - Because overlapping UI elements are discouraged, avoid opening a dialog box from a task pane unless your scenario requires it. When you consider how to use the surface area of a task pane, note that task panes can be tabbed. For an example of a tabbed task pane, see the [Excel Add-in JavaScript SalesTracker](https://github.com/OfficeDev/Excel-Add-in-JavaScript-SalesTracker) sample. +> +> To learn more about best practices for implementing a dialog, see [Best practices and rules for the Office dialog API](dialog-best-practices.md). The following image shows an example of a dialog box. @@ -32,10 +38,10 @@ The Office JavaScript APIs include a [Dialog](/javascript/api/office/office.dial To open a dialog box, your code, typically a page in a task pane, calls the [displayDialogAsync](/javascript/api/office/office.ui#office-office-ui-displaydialogasync-member(1)) method and passes to it the URL of the resource that you want to open. The page on which this method is called is known as the "host page". For example, if you call this method in script on index.html in a task pane, then index.html is the host page of the dialog box that the method opens. -The resource that is opened in the dialog box is usually a page, but it can be a controller method in an MVC application, a route, a web service method, or any other resource. In this article, 'page' or 'website' refers to the resource in the dialog box. The following code is a simple example. +The resource that is opened in the dialog box is usually a page, but it can be a controller method in an MVC application, a route, a web service method, or any other resource. In this article, "page" or "website" refers to the resource in the dialog box. The following code is a simple example. -```js -Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html'); +```javascript +Office.context.ui.displayDialogAsync("https://www.contoso.com/myDialog.html"); ``` - The URL uses the HTTP**S** protocol. This is mandatory for all pages loaded in a dialog box, not just the first page loaded. @@ -48,22 +54,25 @@ After the first page (or other resource) is loaded, a user can use links or othe By default, the dialog box will occupy 80% of the height and width of the device screen, but you can set different percentages by passing a configuration object to the method, as shown in the following example. -```js -Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html', {height: 30, width: 20}); +```javascript +Office.context.ui.displayDialogAsync("https://www.contoso.com/myDialog.html", { height: 30, width: 20 }); ``` -For a sample add-in that does this, see [Build Office Add-ins for Excel](https://github.com/OfficeDev/TrainingContent/tree/master/OfficeAddin/02%20Building%20Add-ins%20for%20Microsoft%20Excel). For more samples that use `displayDialogAsync`, see [Code samples](#code-samples). +For a sample add-in that does this, see [Excel Tutorial - Completed](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/excel-tutorial). For more samples that use `displayDialogAsync`, see [Code samples](#code-samples). Set both values to 100% to get what is effectively a full screen experience. The effective maximum is 99.5%, and the window is still moveable and resizable. You can open only one dialog box from a host window. An attempt to open another dialog box generates an error. For example, if a user opens a dialog box from a task pane, they can't open a second dialog box from a different page in the task pane. However, when a dialog box is opened from an [add-in command](../design/add-in-commands.md), the command opens a new (but unseen) HTML file each time it is selected. This creates a new (unseen) host window, so each such window can launch its own dialog box. For more information, see [Errors from displayDialogAsync](dialog-handle-errors-events.md#errors-from-displaydialogasync). +> [!NOTE] +> In Outlook on the web and new Outlook on Windows, don't set the [window.name](https://developer.mozilla.org/docs/Web/API/Window/name) property when configuring a dialog in your add-in. The `window.name` property is used by these Outlook clients to maintain functionality across page redirects. + ### Take advantage of a performance option in Office on the web The `displayInIframe` property is an additional property in the configuration object that you can pass to `displayDialogAsync`. When this property is set to `true`, and the add-in is running in a document opened in Office on the web, the dialog box will open as a floating iframe rather than an independent window, which makes it open faster. The following is an example. -```js -Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html', {height: 30, width: 20, displayInIframe: true}); +```javascript +Office.context.ui.displayDialogAsync("https://www.contoso.com/myDialog.html", { height: 30, width: 20, displayInIframe: true }); ``` The default value is `false`, which is the same as omitting the property entirely. If the add-in isn't running in Office on the web, the `displayInIframe` is ignored. @@ -80,8 +89,8 @@ Code in the dialog box uses the [messageParent](/javascript/api/office/office.ui The following example shows how to initialize Office JS and send a message to the host page. -```js -Office.onReady(function() { +```javascript +Office.onReady(() => { // Add any initialization code for your dialog here. }); @@ -93,7 +102,7 @@ function userSignedIn() { The next example shows how to return a JSON string containing profile information. -```js +```javascript function userProfileSignedIn(profile) { const profileMessage = { "name": profile.name, @@ -107,10 +116,10 @@ The `messageParent` function is one of *only* two Office JS APIs that can be cal The host page must be configured to receive the message. You do this by adding a callback parameter to the original call of `displayDialogAsync`. The callback assigns a handler to the `DialogMessageReceived` event. The following is an example. -```js +```javascript let dialog; // Declare dialog as global for use in later functions. -Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html', {height: 30, width: 20}, - function (asyncResult) { +Office.context.ui.displayDialogAsync("https://www.contoso.com/myDialog.html", { height: 30, width: 20 }, + (asyncResult) => { dialog = asyncResult.value; dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage); } @@ -125,7 +134,7 @@ Office passes an [AsyncResult](/javascript/api/office/office.asyncresult) object The following is a simple example of a handler for the `DialogMessageReceived` event. -```js +```javascript function processMessage(arg) { const messageFromDialog = JSON.parse(arg.message); showUserName(messageFromDialog.name); @@ -136,18 +145,18 @@ Office passes the `arg` object to the handler. Its `message` property is the str When the user interaction with the dialog box is completed, your message handler should close the dialog box, as shown in this example. -```js +```javascript function processMessage(arg) { dialog.close(); - // message processing code goes here; + // Add code to process the message here. } ``` The `dialog` object must be the same one that is returned by the call of `displayDialogAsync`. You need to declare the `dialog` object as a global variable. Or you can scope the `dialog` object to the `displayDialogAsync` call with an anonymous callback function as shown in the following example. In the example, `processMessage` doesn't need to close the dialog since the `close` method is called in the anonymous callback function. -```js -Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html', {height: 30, width: 20}, - function (asyncResult) { +```javascript +Office.context.ui.displayDialogAsync("https://www.contoso.com/myDialog.html", { height: 30, width: 20 }, + (asyncResult) => { const dialog = asyncResult.value; dialog.addEventHandler(Office.EventType.DialogMessageReceived, (arg) => { dialog.close(); @@ -159,11 +168,11 @@ Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html', {h If the add-in needs to open a different page of the task pane after receiving the message, you can use the `window.location.replace` method (or `window.location.href`) as the last line of the handler. The following is an example. -```js +```javascript function processMessage(arg) { - // message processing code goes here; + // Add code to process the message here. window.location.replace("/newPage.html"); - // Alternatively ... + // Alternatively, use the following: // window.location.href = "/newPage.html"; } ``` @@ -174,15 +183,15 @@ For an example of an add-in that does this, see the [Insert Excel charts using M Because you can send multiple `messageParent` calls from the dialog box, but you have only one handler in the host page for the `DialogMessageReceived` event, the handler must use conditional logic to distinguish different messages. For example, if the dialog box prompts a user to sign in to an identity provider such as Microsoft account or Google, it sends the user's profile as a message. If authentication fails, the dialog box sends error information to the host page, as in the following example. -```js +```javascript if (loginSuccess) { const userProfile = getProfile(); - const messageObject = {messageType: "signinSuccess", profile: userProfile}; + const messageObject = { messageType: "signinSuccess", profile: userProfile }; const jsonMessage = JSON.stringify(messageObject); Office.context.ui.messageParent(jsonMessage); } else { const errorDetails = getError(); - const messageObject = {messageType: "signinFailure", error: errorDetails}; + const messageObject = { messageType: "signinFailure", error: errorDetails }; const jsonMessage = JSON.stringify(messageObject); Office.context.ui.messageParent(jsonMessage); } @@ -196,7 +205,7 @@ About the previous example, note: The handler code in the host page uses the value of the `messageType` property to branch as shown in the following example. Note that the `showUserName` function is the same as in the previous example and `showNotification` function displays the error in the host page's UI. -```js +```javascript function processMessage(arg) { const messageFromDialog = JSON.parse(arg.message); if (messageFromDialog.messageType === "signinSuccess") { @@ -221,13 +230,13 @@ After the dialog opens, either the dialog or the parent runtime may navigate awa The following is an example of using `messageParent` to send a cross-domain message. -```js +```javascript Office.context.ui.messageParent("Some message", { targetOrigin: "https://resource.contoso.com/" }); ``` If the message doesn't include sensitive data, you can set the `targetOrigin` to "\*" which allows it to be sent to any domain. The following is an example. -```js +```javascript Office.context.ui.messageParent("Some message", { targetOrigin: "*" }); ``` @@ -254,34 +263,39 @@ Your add-in can send messages from the [host page](dialog-api-in-office-add-ins. When you call the Office dialog API to open a dialog box, a [Dialog](/javascript/api/office/office.dialog) object is returned. It should be assigned to a variable that has global scope so that you can reference it from other functions. The following is an example. ```javascript -let dialog; // Declare as global variable. -Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html', - function (asyncResult) { -     dialog = asyncResult.value; -     dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage); -   } +let dialog; // Declare as global variable. +Office.context.ui.displayDialogAsync("https://www.contoso.com/myDialog.html", + (asyncResult) => { + dialog = asyncResult.value; + dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage); + } ); -function processMessage(arg) { +function processMessage(arg) { dialog.close(); -  // message processing code goes here; + // Add code to process the message here. } ``` This `Dialog` object has a [messageChild](/javascript/api/office/office.dialog#office-office-dialog-messagechild-member(1)) method that sends any string, including stringified data, to the dialog box. This raises a `DialogParentMessageReceived` event in the dialog box. Your code should handle this event, as shown in the next section. -Consider a scenario in which the UI of the dialog is related to the currently active worksheet and that worksheet's position relative to the other worksheets. In the following example, `sheetPropertiesChanged` sends Excel worksheet properties to the dialog box. In this case, the current worksheet is named "My Sheet" and it's the second sheet in the workbook. The data is encapsulated in an object and stringified so that it can be passed to `messageChild`. +Consider a scenario in which the UI of the dialog is related to the currently active Excel worksheet and that worksheet's position relative to the other worksheets. In the following example, `worksheetPropertiesChanged` sends the properties of the active worksheet to the dialog box. The data is stringified so that it can be passed to `messageChild`. ```javascript -function sheetPropertiesChanged() { - const messageToDialog = JSON.stringify({ -       name: "My Sheet", -      position: 2 - }); +await Excel.run(async (context) => { + const worksheet = context.workbook.worksheets.getActiveWorksheet(); + worksheet.load(); + await context.sync(); + worksheetPropertiesChanged(worksheet); +}); + +... -    dialog.messageChild(messageToDialog); +function worksheetPropertiesChanged(currentWorksheet) { + const messageToDialog = JSON.stringify(currentWorksheet); + dialog.messageChild(messageToDialog); } ``` @@ -290,35 +304,35 @@ function sheetPropertiesChanged() { In the dialog box's JavaScript, register a handler for the `DialogParentMessageReceived` event with the [UI.addHandlerAsync](/javascript/api/office/office.ui#office-office-ui-addhandlerasync-member(1)) method. This is typically done in the [Office.onReady or Office.initialize function](initialize-add-in.md), as shown in the following. (A more robust example is included later in this article.) ```javascript -Office.onReady(function () { - Office.context.ui.addHandlerAsync(Office.EventType.DialogParentMessageReceived, - onMessageFromParent); +Office.onReady(() => { + Office.context.ui.addHandlerAsync(Office.EventType.DialogParentMessageReceived,onMessageFromParent); }); ``` Then, define the `onMessageFromParent` handler. The following code continues the example from the preceding section. Note that Office passes an argument to the handler and that the `message` property of the argument object contains the string from the host page. In this example, the message is reconverted to an object and jQuery is used to set the top heading of the dialog to match the new worksheet name. ```javascript -function onMessageFromParent(arg) { -  const messageFromParent = JSON.parse(arg.message); - document.querySelector('h1').textContent = messageFromParent.name; +function onMessageFromParent(arg) { + const messageFromParent = JSON.parse(arg.message); + document.querySelector('h1').textContent = messageFromParent.name; } ``` It's best practice to verify that your handler is properly registered. You can do this by passing a callback to the `addHandlerAsync` method. This runs when the attempt to register the handler completes. Use the handler to log or show an error if the handler wasn't successfully registered. The following is an example. Note that `reportError` is a function, not defined here, that logs or displays the error. ```javascript -Office.onReady(function () { - Office.context.ui.addHandlerAsync( -   Office.EventType.DialogParentMessageReceived, -     onMessageFromParent, - onRegisterMessageComplete); +Office.onReady(() => { + Office.context.ui.addHandlerAsync( + Office.EventType.DialogParentMessageReceived, + onMessageFromParent, + onRegisterMessageComplete + ); }); -function onRegisterMessageComplete(asyncResult) { - if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { -   reportError(asyncResult.error.message); -  } +function onRegisterMessageComplete(asyncResult) { + if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { + reportError(asyncResult.error.message); + } } ``` @@ -330,7 +344,7 @@ Because you can make multiple `messageChild` calls from the host page, but you h > In some situations, the `messageChild` API, which is a part of the [DialogApi 1.2 requirement set](/javascript/api/requirement-sets/common/dialog-api-requirement-sets), may not be supported. For example, `messageChild` isn't supported in volume-licensed perpetual Outlook 2016 and volume-licensed perpetual Outlook 2019. Some alternative ways for parent-to-dialog-box messaging are described in [Alternative ways of passing messages to a dialog box from its host page](parent-to-dialog.md). > [!IMPORTANT] -> The [DialogApi 1.2 requirement set](/javascript/api/requirement-sets/common/dialog-api-requirement-sets) can't be specified in the **\<Requirements\>** section of an add-in manifest. You will have to check for support for DialogApi 1.2 at runtime using the `isSetSupported` method as described in [Runtime checks for method and requirement set support](../develop/specify-office-hosts-and-api-requirements.md#runtime-checks-for-method-and-requirement-set-support). Support for manifest requirements is under development. +> The [DialogApi 1.2 requirement set](/javascript/api/requirement-sets/common/dialog-api-requirement-sets) can't be specified in the add-in manifest. You'll have to check for support for DialogApi 1.2 at runtime using the `isSetSupported` method as described in [Check for API availability at runtime](specify-api-requirements-runtime.md). Support for manifest requirements is under development. ### Cross-domain messaging to the dialog runtime @@ -341,25 +355,30 @@ After the dialog opens, either the dialog or the parent runtime may navigate awa The following is an example of using `messageChild` to send a cross-domain message. -```js +```javascript dialog.messageChild(messageToDialog, { targetOrigin: "https://resource.contoso.com/" }); ``` If the message doesn't include sensitive data, you can set the `targetOrigin` to "\*" which allows it to be *sent* to any domain. The following is an example. -```js +```javascript dialog.messageChild(messageToDialog, { targetOrigin: "*" }); ``` -Because the runtime that is hosting the dialog can't access the **\<AppDomains\>** section of the manifest and thereby determine whether the domain *from which the message comes* is trusted, you must use the `DialogParentMessageReceived` handler to determine this. The object that is passed to the handler contains the domain that is currently hosted in the parent as its `origin` property. The following is an example of how to use the property. +The add-in's manifest specifies trusted domains. In the unified manifest for Microsoft 365, this is specified in the "validDomains" property. In the add-in only manifest, this is specified in the `<AppDomains>` element. + +[!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] + +But the runtime that's hosting the dialog can't access the manifest and thereby determine whether the domain *from which the message comes* is trusted, you must use the `DialogParentMessageReceived` handler to determine this. The object that's passed to the handler contains the domain that's currently hosted in the parent as its `origin` property. The following is an example of how to use the property. ```javascript -function onMessageFromParent(arg) { +function onMessageFromParent(arg) { if (arg.origin === "https://addin.fabrikam.com/") { - // process message + // Process the message. } else { - dialog.close(); - showNotification("Messages from " + arg.origin + " aren't accepted."); + // Signal the parent page to close the dialog. + const messageObject = { messageType: "untrustedDomain" }; + Office.context.ui.messageParent(messageObject); } } ``` @@ -381,9 +400,9 @@ For example, your code could use the [Office.onReady or Office.initialize functi You can implement a button in the dialog box that will close it. To do this, the click event handler for the button should use `messageParent` to tell the host page that the button has been clicked. The following is an example. -```js +```javascript function closeButtonClick() { - const messageObject = {messageType: "dialogClosed"}; + const messageObject = { messageType: "dialogClosed" }; const jsonMessage = JSON.stringify(messageObject); Office.context.ui.messageParent(jsonMessage); } @@ -391,7 +410,7 @@ function closeButtonClick() { The host page handler for `DialogMessageReceived` would call `dialog.close`, as in this example. (See previous examples that show how the `dialog` object is initialized.) -```js +```javascript function processMessage(arg) { const messageFromDialog = JSON.parse(arg.message); if (messageFromDialog.messageType === "dialogClosed") { @@ -406,7 +425,8 @@ Even when you don't have your own close-dialog UI, an end user can close the dia All of the following samples use `displayDialogAsync`. Some have NodeJS-based servers and others have ASP.NET/IIS-based servers, but the logic of using the method is the same regardless of how the server-side of the add-in is implemented. -- [Training Content / Building Add-ins](https://github.com/OfficeDev/TrainingContent/tree/master/OfficeAddin/02%20Building%20Add-ins%20for%20Microsoft%20Excel) +- [Excel Tutorial - Completed](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/excel-tutorial) +- [Excel Shared Runtime Scenario](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-shared-runtime-scenario) - [Office Add-in Microsoft Graph ASPNET](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Office-Add-in-Microsoft-Graph-ASPNET) - [Office Add-in Microsoft Graph React](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Office-Add-in-Microsoft-Graph-React) - [Office Add-in NodeJS SSO](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Office-Add-in-NodeJS-SSO) @@ -418,7 +438,6 @@ All of the following samples use `displayDialogAsync`. Some have NodeJS-based se - [Outlook Add-in Actionable Message](https://github.com/OfficeDev/Outlook-Add-In-Actionable-Message) - [Outlook Add-in Sharing to OneDrive](https://github.com/OfficeDev/Outlook-Add-in-Sharing-to-OneDrive) - [PowerPoint Add-in Microsoft Graph ASPNET InsertChart](https://github.com/OfficeDev/PowerPoint-Add-in-Microsoft-Graph-ASPNET-InsertChart) -- [Excel Shared Runtime Scenario](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-shared-runtime-scenario) ## See also diff --git a/docs/develop/dialog-best-practices.md b/docs/develop/dialog-best-practices.md index 78df7039e0..c37d063bf1 100644 --- a/docs/develop/dialog-best-practices.md +++ b/docs/develop/dialog-best-practices.md @@ -1,33 +1,38 @@ --- -title: Best practices and rules for the Office dialog API -description: Provides rules and best practices for the Office dialog API, such as best practices for a single-page application (SPA). -ms.date: 05/16/2024 +title: Best practices and rules for the Office Dialog API +description: Provides rules, limitations, and best practices for the Office Dialog API, such as best practices for a single-page application (SPA). +ms.date: 06/17/2025 ms.topic: best-practice ms.localizationpriority: medium --- -# Best practices and rules for the Office dialog API +# Best practices and rules for the Office Dialog API -This article provides rules, gotchas, and best practices for the Office dialog API, including best practices for designing the UI of a dialog and using the API within a single-page application (SPA). +This article provides rules, limitations, and best practices for the Office Dialog API, including best practices for designing the UI of a dialog and using the API within a single-page application (SPA). > [!NOTE] -> To familiarize yourself with the basics of using the Office dialog API, see [Use the Office dialog API in your Office Add-ins](dialog-api-in-office-add-ins.md). +> To familiarize yourself with the basics of using the Office Dialog API, see [Use the Office Dialog API in your Office Add-ins](dialog-api-in-office-add-ins.md). > > See also [Handling errors and events with the Office dialog box](dialog-handle-errors-events.md). -## Rules and gotchas +## Rules and limitations -- The dialog box can only navigate to HTTPS URLs, not HTTP. +- A dialog box can only navigate to HTTPS URLs, not HTTP. - The URL passed to the [displayDialogAsync](/javascript/api/office/office.ui) method must be in the exact same domain as the add-in itself. It can't be a subdomain. However, the page that is passed to it can redirect to a page in another domain. -- A host page can have only one dialog box open at a time. The host page could be either a task pane or the [function file](/javascript/api/manifest/functionfile) of a [function command](../design/add-in-commands.md#types-of-add-in-commands). +- A host page can have only one dialog box open at a time. The host page could be either a task pane or the [function file](/javascript/api/manifest/functionfile) of a [function command](../design/add-in-commands.md#types-of-add-in-commands). Multiple dialogs can be open at the same time from custom ribbon buttons or menu items. - Only two Office APIs can be called in the dialog box, - [Office.context.ui.messageParent](/javascript/api/office/office.ui#office-office-ui-messageparent-member(1)) - `Office.context.requirements.isSetSupported` (For more information, see [Specify Office applications and API requirements](specify-office-hosts-and-api-requirements.md).) - The [messageParent](/javascript/api/office/office.ui#office-office-ui-messageparent-member(1)) function should usually be called from a page in the exact same domain as the add-in itself, but this isn't mandatory. For more information, see [Cross-domain messaging to the host runtime](dialog-api-in-office-add-ins.md#cross-domain-messaging-to-the-host-runtime). +- When a dialog box opens, it's centered on the screen on top of the Office application. +- A dialog box can be moved and resized by the user. +- A dialog box appears in the order in which it was created. > [!TIP] > In Office on the web and [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627), if the domain of your dialog is different from that of your add-in and it enforces the [Cross-Origin-Opener-Policy: same-origin](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy) response header, your add-in will be blocked from accessing messages from the dialog and your users will be shown [error 12006](dialog-handle-errors-events.md#errors-and-events-in-the-dialog-box). To prevent this, you must set the header to `Cross-Origin-Opener-Policy: unsafe-none` or configure your add-in and dialog to be in the same domain. +- In Outlook on the web and new Outlook on Windows, don't set the [window.name](https://developer.mozilla.org/docs/Web/API/Window/name) property when configuring a dialog in your add-in. The `window.name` property is used by these Outlook clients to maintain functionality across page redirects. + ## Best practices ### Avoid overusing dialog boxes @@ -61,6 +66,7 @@ When your add-in calls [Office.context.devicePermission.requestPermissions](/jav > > - Add-ins that run in Office desktop clients or in browsers not based on Chromium automatically show a dialog requesting for a user's permission. The developer doesn't need to implement the device permission API on these platforms. > - Add-ins that run in Safari are blocked from accessing a user's device capabilities. The device permission API isn't supported in Safari. +> - Access to a user's geolocation is only supported in **Outlook on the web** and new **Outlook on Windows**. ### Don't use the \_host\_info value @@ -74,29 +80,33 @@ The `close` method doesn't accept a callback parameter, and it doesn't return a ```javascript function openFirstDialog() { - Office.context.ui.displayDialogAsync("https://mydomain/firstDialog.html", { width: 50, height: 50}, - (result) => { - if(result.status === Office.AsyncResultStatus.Succeeded) { + Office.context.ui.displayDialogAsync( + "https://mydomain/firstDialog.html", + { width: 50, height: 50 }, + (result) => { + if (result.status === Office.AsyncResultStatus.Succeeded) { const dialog = result.value; dialog.close(); openSecondDialog(); } else { - // Handle errors + // Handle errors. } } ); } function openSecondDialog() { - Office.context.ui.displayDialogAsync("https://mydomain/secondDialog.html", { width: 50, height: 50}, + Office.context.ui.displayDialogAsync( + "https://mydomain/secondDialog.html", + { width: 50, height: 50 }, (result) => { - if(result.status === Office.AsyncResultStatus.Failed) { + if (result.status === Office.AsyncResultStatus.Failed) { if (result.error.code === 12007) { - openSecondDialog(); // Recursive call + openSecondDialog(); // Recursive call. } else { - // Handle other errors + // Handle other errors. } } } @@ -108,33 +118,39 @@ Alternatively, you could force the code to pause before it tries to open the sec ```javascript function openFirstDialog() { - Office.context.ui.displayDialogAsync("https://mydomain/firstDialog.html", { width: 50, height: 50}, - (result) => { - if(result.status === Office.AsyncResultStatus.Succeeded) { + Office.context.ui.displayDialogAsync( + "https://mydomain/firstDialog.html", + { width: 50, height: 50 }, + (result) => { + if (result.status === Office.AsyncResultStatus.Succeeded) { const dialog = result.value; dialog.close(); setTimeout(() => { - Office.context.ui.displayDialogAsync("https://mydomain/secondDialog.html", { width: 50, height: 50}, - (result) => { /* callback body */ } + Office.context.ui.displayDialogAsync( + "https://mydomain/secondDialog.html", + { width: 50, height: 50 }, + (result) => { + // Callback body. + } ); }, 1000); } else { - // Handle errors + // Handle errors. } } ); } ``` -### Best practices for using the Office dialog API in an SPA +### Best practices for using the Office Dialog API in an SPA If your add-in uses client-side routing, as single-page applications (SPAs) typically do, you have the option to pass the URL of a route to the [displayDialogAsync](/javascript/api/office/office.ui) method instead of the URL of a separate HTML page. *We recommend against doing so for the reasons given below.* > [!NOTE] > This article isn't relevant to *server-side* routing, such as in an Express-based web application. -#### Problems with SPAs and the Office dialog API +#### Problems with SPAs and the Office Dialog API The Office dialog box is in a new window with its own instance of the JavaScript engine, and hence it's own complete execution context. If you pass a route, your base page and all its initialization and bootstrapping code run again in this new context, and any variables are set to their initial values in the dialog box. So this technique downloads and launches a second instance of your application in the box window, which partially defeats the purpose of an SPA. In addition, code that changes variables in the dialog box window doesn't change the task pane version of the same variables. Similarly, the dialog box window has its own session storage (the [Window.sessionStorage](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage) property), which isn't accessible from code in the task pane. The dialog box and the host page on which `displayDialogAsync` was called look like two different clients to your server. (For a reminder of what a host page is, see [Open a dialog box from a host page](dialog-api-in-office-add-ins.md#open-a-dialog-box-from-a-host-page).) @@ -145,4 +161,9 @@ So, if you passed a route to the `displayDialogAsync` method, you wouldn't reall Instead of passing a client-side route to the `displayDialogAsync` method, we recommend that you do one of the following: - If the code that you want to run in the dialog box is sufficiently complex, create two different SPAs explicitly; that is, have two SPAs in different folders of the same domain. One SPA runs in the dialog box and the other in the dialog box's host page where `displayDialogAsync` was called. -- In most scenarios, only simple logic is needed in the dialog box. In such cases, your project will be greatly simplified by hosting a single HTML page, with embedded or referenced JavaScript, in the domain of your SPA. Pass the URL of the page to the `displayDialogAsync` method. While this means that you are deviating from the literal idea of a single-page app; you don't really have a single instance of an SPA when you are using the Office dialog API. +- In most scenarios, only simple logic is needed in the dialog box. In such cases, your project will be greatly simplified by hosting a single HTML page, with embedded or referenced JavaScript, in the domain of your SPA. Pass the URL of the page to the `displayDialogAsync` method. While this means that you are deviating from the literal idea of a single-page app; you don't really have a single instance of an SPA when you are using the Office Dialog API. + +## See also + +- [Use the Office Dialog API in Office Add-ins](dialog-api-in-office-add-ins.md) +- [Handle errors and events in the Office dialog box](dialog-handle-errors-events.md) diff --git a/docs/develop/dialog-handle-errors-events.md b/docs/develop/dialog-handle-errors-events.md index 85d2ada5f3..f1a1be4b77 100644 --- a/docs/develop/dialog-handle-errors-events.md +++ b/docs/develop/dialog-handle-errors-events.md @@ -1,7 +1,7 @@ --- title: Handling errors and events in the Office dialog box description: Learn how to trap and handle errors when opening and using the Office dialog box. -ms.date: 05/10/2024 +ms.date: 03/11/2025 ms.topic: error-reference ms.localizationpriority: medium --- @@ -11,13 +11,13 @@ ms.localizationpriority: medium This article describes how to trap and handle errors when opening the dialog box and errors that happen inside the dialog box. > [!NOTE] -> This article presupposes that you are familiar with the basics of using the Office dialog API as described in [Use the Office dialog API in your Office Add-ins](dialog-api-in-office-add-ins.md). +> This article presupposes that you're familiar with the basics of using the Office dialog API as described in [Use the Office dialog API in your Office Add-ins](dialog-api-in-office-add-ins.md). > > See also [Best practices and rules for the Office dialog API](dialog-best-practices.md). Your code should handle two categories of events. -- Errors returned by the call of `displayDialogAsync` because the dialog box cannot be created. +- Errors returned by the call of `displayDialogAsync` because the dialog box can't be created. - Errors, and other events, in the dialog box. ## Errors from displayDialogAsync @@ -26,7 +26,7 @@ In addition to general platform and system errors, four errors are specific to c |Code number|Meaning| |:-----|:-----| -|12004|The domain of the URL passed to `displayDialogAsync` isn't trusted. The domain must be the same domain as the host page (including protocol and port number).| +|12004|The domain of the URL passed to `displayDialogAsync` isn't trusted. The domain must be the same domain as the host page (including protocol and port number).<br><br>In Outlook on the web and the [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627), this error occurs when an add-in is hosted on a localhost server and its manifest doesn't specify an [AppDomain](/javascript/api/manifest/appdomain) element for localhost.| |12005|The URL passed to `displayDialogAsync` uses the HTTP protocol. HTTPS is required. (In some versions of Office, the error message text returned with 12005 is the same one returned for 12004.)| |<span id="12007">12007</span><!-- The span is needed because office-js-helpers has an error message that links to this table row. -->|A dialog box is already opened from this host window. A host window, such as a task pane, can only have one dialog box open at a time.| |12009|The user chose to ignore the dialog box. This error can occur in Office on the web, where users may choose not to allow an add-in to present a dialog box. For more information, see [Handling pop-up blockers with Office on the web](dialog-best-practices.md#handle-pop-up-blockers-with-office-on-the-web).| @@ -53,7 +53,7 @@ Three errors and events in the dialog box will raise a `DialogEventReceived` eve |Code number|Meaning| |:-----|:-----| -|12002|One of the following:<ul><li>No page exists at the URL that was passed to `displayDialogAsync`.</li><li>The page that was passed to `displayDialogAsync` loaded, but the dialog box was then redirected to a page that it cannot find or load, or it has been directed to a URL with invalid syntax.</li></ul>| +|12002|One of the following:<ul><li>No page exists at the URL that was passed to `displayDialogAsync`.</li><li>The page that was passed to `displayDialogAsync` loaded, but the dialog box was then redirected to a page that it can't find or load, or it has been directed to a URL with invalid syntax.</li></ul>| |12003|The dialog box was directed to a URL with the HTTP protocol. HTTPS is required.| |12006|One of the following:<ul><li>The dialog box was closed, usually because the user chose the **Close** button **X**.</li><li>The dialog returned a [Cross-Origin-Opener-Policy: same-origin](https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy) response header. To prevent this, you must set the header to `Cross-Origin-Opener-Policy: unsafe-none` or configure your add-in and dialog to be in the same domain as the host page.</li></ul>| @@ -75,7 +75,7 @@ For an example of a handler for the `DialogEventReceived` event that creates cus function processDialogEvent(arg) { switch (arg.error) { case 12002: - showNotification("The dialog box has been directed to a page that it cannot find or load, or the URL syntax is invalid."); + showNotification("The dialog box has been directed to a page that it can't find or load, or the URL syntax is invalid."); break; case 12003: showNotification("The dialog box has been directed to a URL with the HTTP protocol. HTTPS is required."); break; diff --git a/docs/develop/dialog-video.md b/docs/develop/dialog-video.md index 227cdd9bdc..19f2bbdfb4 100644 --- a/docs/develop/dialog-video.md +++ b/docs/develop/dialog-video.md @@ -1,21 +1,31 @@ --- title: Use the Office dialog box to play a video -description: Learn how to open and play a video in the Office dialog box. -ms.date: 07/08/2021 +description: Learn how to open and play a video in the Office dialog box to create engaging user experiences. +ms.date: 10/29/2025 ms.topic: how-to ms.localizationpriority: medium --- # Use the Office dialog box to show a video -This article explains how to play a video in an Office Add-in dialog box. +Play a video in an Office Add-in dialog box to create more engaging user experiences. + +Videos in dialog boxes are perfect for: + +- **Onboarding tutorials** that guide users through your add-in's features. +- **Product demos** that showcase functionality. +- **Training content** that helps users get up to speed quickly. > [!NOTE] > This article presumes you're familiar with the basics of using the Office dialog box as described in [Use the Office dialog API in your Office Add-ins](dialog-api-in-office-add-ins.md). To play a video in a dialog box with the Office dialog API, follow these steps. -1. Create a page containing an iframe and no other content. The page must be in the same domain as the host page. For a reminder of what a host page is, see [Open a dialog box from a host page](dialog-api-in-office-add-ins.md#open-a-dialog-box-from-a-host-page). In the `src` attribute of the iframe, point to the URL of an online video. The protocol of the video's URL must be HTTPS. In this article, we'll call this page "video.dialogbox.html". The following is an example of the markup. +1. Create a dedicated video page that contains an iframe and no other content. The page must be in the same domain as the host page. For a reminder of what a host page is, see [Open a dialog box from a host page](dialog-api-in-office-add-ins.md#open-a-dialog-box-from-a-host-page). + + In the `src` attribute of the iframe, point to the URL of an online video. The protocol of the video's URL must be HTTPS. In this example, we'll call this page **video.dialogbox.html**. + + Here's the markup: ```HTML <iframe class="ms-firstrun-video__player" width="640" height="360" @@ -24,9 +34,18 @@ To play a video in a dialog box with the Office dialog API, follow these steps. </iframe> ``` -2. Use a call of `displayDialogAsync` in the host page to open video.dialogbox.html. -3. If your add-in needs to know when the user closes the dialog box, register a handler for the `DialogEventReceived` event and handle the 12006 event. For details, see [Errors and events in the Office dialog box](dialog-handle-errors-events.md). +1. Call `displayDialogAsync` in the host page to open **video.dialogbox.html**. + +1. (Optional) If your add-in needs to know when the user closes the dialog, handle dialog close events. Register a handler for the `DialogEventReceived` event and handle the 12006 event. For details, see [Errors and events in the Office dialog box](dialog-handle-errors-events.md). + +## See it in action For a sample of a video playing in a dialog box, see the [video placemat design pattern](../design/first-run-experience-patterns.md#video-placemat). ![A video playing in an add-in dialog box in front of Excel.](../images/video-placemats-dialog-open.png) + +## See also + +- [Use the Office dialog API in your Office Add-ins](dialog-api-in-office-add-ins.md) +- [Best practices and rules for the Office Dialog API](dialog-best-practices.md) +- [Handle errors and events in the Office dialog box](dialog-handle-errors-events.md) diff --git a/docs/develop/enable-nested-app-authentication-in-your-add-in.md b/docs/develop/enable-nested-app-authentication-in-your-add-in.md index 2da8f9f173..e675f1ea2f 100644 --- a/docs/develop/enable-nested-app-authentication-in-your-add-in.md +++ b/docs/develop/enable-nested-app-authentication-in-your-add-in.md @@ -1,14 +1,14 @@ --- -title: Enable SSO in an Office Add-in using nested app authentication -description: Learn how to enable SSO in an Office Add-in using nested app authentication. -ms.date: 08/07/2024 +title: Enable single sign-on in an Office Add-in with nested app authentication +description: Learn how to enable SSO in an Office Add-in with nested app authentication. +ms.date: 07/14/2025 ms.topic: how-to ms.localizationpriority: high --- -# Enable SSO in an Office Add-in using nested app authentication (preview) +# Enable single sign-on in an Office Add-in with nested app authentication -You can use the MSAL.js library (version 3.11 and later) with nested app authentication to use SSO from your Office Add-in. Using nested app authentication offers several advantages over the On-Behalf-Of (OBO) flow. +You can use the MSAL.js library with nested app authentication to use single sign-on (SSO) from your Office Add-in. Using nested app authentication (NAA) offers several advantages over the On-Behalf-Of (OBO) flow. - You only need to use the MSAL.js library and don’t need the `getAccessToken` function in Office.js. - You can call services such as Microsoft Graph with an access token from your client code as an SPA. There’s no need for a middle-tier server. @@ -17,19 +17,19 @@ You can use the MSAL.js library (version 3.11 and later) with nested app authent ## NAA supported accounts and hosts -> [!IMPORTANT] -> Nested app authentication (NAA) is currently in preview. To try this feature, join the Microsoft 365 Insider Program (https://insider.microsoft365.com/join) and choose **Current Channel (Preview)**. Don't use NAA in production add-ins. We invite you to try out NAA in test or development environments and welcome feedback on your experience through GitHub (see the **Feedback** section at the end of this page). +NAA supports both Microsoft Accounts and Microsoft Entra ID (work/school) identities. It doesn't support [Azure Active Directory B2C](/azure/active-directory-b2c/overview) for business-to-consumer identity management scenarios. The following table explains the current support by platform. Platforms listed as generally available (GA) are ready for production usage in your add-in. -NAA supports both Microsoft Accounts and Microsoft Entra ID (work/school) identities. It doesn't support Azure Active Directory B2C for business-to-consumer identity management scenarios. The following table explains the current support in preview. Anything listed as "Coming soon" will be supported by the time that NAA is made generally available. +| Application | Web | Windows | Mac | iOS/iPad | Android | +|-------------|------------|------------------------------------------------------|------------|--------------------|----------------| +| Excel | In preview | In preview | In preview | In preview on iPad | Not applicable | +| Outlook | GA | GA | GA | GA (iOS) | GA | +| PowerPoint | In preview | In preview | In preview | In preview on iPad | Not applicable | +| Word | In preview | In preview | In preview | In preview on iPad | Not applicable | -| Application | Windows | Mac | Web | iOS/iPad | Android | -|-------------|------------------------------------------------------------------------------------|-----|--------------|------------|----------------| -| Excel | Yes (Current Channel (Preview)) | Yes | Coming soon | Yes (iPad) | Not applicable | -| Outlook | Yes* (Current Channel (Preview) for classic Outlook only, new Outlook coming soon) | Yes | Yes | Yes (iOS) | Yes | -| PowerPoint | Yes (Current Channel (Preview)) | Yes | Coming soon | Yes (iPad) | Not applicable | -| Word | Yes (Current Channel (Preview)) | Yes | Coming soon | Yes (iPad) | Not applicable | +> [!IMPORTANT] +> To use NAA on platforms that are still in preview (Word, Excel, and PowerPoint), join the [Microsoft 365 Insider Program](https://aka.ms/MSFT365InsiderProgram) and choose **Current Channel (Preview)**. Don't use NAA in production add-ins for any preview platforms. We invite you to try out NAA in test or development environments and welcome feedback on your experience through GitHub (see the **Feedback** section at the end of this page). -*\* - NAA for event-based activation in Outlook is currently supported in the Beta Channel.* +For information on using NAA in Microsoft Teams, see [Nested app authentication in Microsoft Teams](/microsoftteams/platform/concepts/authentication/nested-authentication). ## Register your single-page application @@ -47,7 +47,11 @@ To enable NAA, your app registration must include a specific redirect URI to ind `brk-multihub://your-add-in-domain` -For example if you were testing your add-in on port 3000 on the localhost server, you would use `brk-multihub://localhost:3000` as the redirect value. +Your domain must include only the origin and not its subpaths. For example: + +✔️ brk-multihub://localhost:3000<br> +✔️ brk-multihub://www.contoso.com<br> +❌ brk-multihub://www.contoso.com/go Trusted broker groups are dynamic by design and can be updated in the future to include additional hosts where your add-in may use NAA flows. Currently the brk-multihub group includes Office Word, Excel, PowerPoint, Outlook, and Teams (for when Office is activated inside). @@ -57,11 +61,11 @@ Configure your add-in to use NAA by calling the `createNestablePublicClientApp The following steps show how to enable NAA in the `taskpane.js` or `taskpane.ts` file in a project built with `yo office` (**Office Add-in Task Pane** project). -1. Add the `@azure/msal-browser` package to the `dependencies` section of the `package.json` file for your project. For more information on this package, see [Microsoft Authentication Library for JavaScript (MSAL.js) for Browser-Based Single-Page Applications](https://www.npmjs.com/package/%40azure/msal-browser). +1. Add the `@azure/msal-browser` package to the `dependencies` section of the `package.json` file for your project. For more information on this package, see [Microsoft Authentication Library for JavaScript (MSAL.js) for Browser-Based Single-Page Applications](https://www.npmjs.com/package/%40azure/msal-browser). We recommend using the latest version of the package (at time of the last article update it was 3.26.0). ```json "dependencies": { - "@azure/msal-browser": "^3.15.0", + "@azure/msal-browser": "^3.27.0", ... ``` @@ -134,6 +138,9 @@ The following code shows how to implement this authentication pattern in your ow } ``` + > [!IMPORTANT] + > The token request must include scopes other than just `offline_access`, `openid`, `profile`, or `email`. You can use any combination of the previous scopes, but you must include at least one additional scope. If not, the token request can fail. + 1. Replace `TODO 1` with the following code. This code calls `acquireTokenSilent` to get the access token. ```JavaScript @@ -176,7 +183,7 @@ The following code shows how to implement this authentication pattern in your ow ## Call an API -After acquiring the token, use it to call an API. The following example shows how to call the Microsoft Graph API by calling `fetch` with the token attached in the _Authorization_ header. +After acquiring the token, use it to call an API. The following example shows how to call the Microsoft Graph API by calling `fetch` with the token attached in the *Authorization* header. - Replace `TODO 4` with the following code. @@ -225,8 +232,17 @@ In certain cases, the `acquireTokenSilent` method's attempt to get the token f ### Have a fallback when NAA isn't supported -While we strive to provide a high-degree of compatibility with these flows across the Microsoft ecosystem, your add-in may be loaded in an older Office host that does not support NAA. In these cases, your add-in won't support seamless SSO and you may need to fall back to an alternate method of authenticating the user. In general you'll want to use the MSAL SPA authentication pattern with the [Office JS dialog API](auth-with-office-dialog-api.md). For more information, see the following resources. +While we strive to provide a high-degree of compatibility with these flows across the Microsoft ecosystem, your add-in may be loaded in an older Office host that does not support NAA. In these cases, your add-in won't support seamless SSO and you may need to fall back to an alternate method of authenticating the user. In general you'll want to use the MSAL SPA authentication pattern with the [Office JS dialog API](auth-with-office-dialog-api.md). + +Use the following code to check if NAA is supported when your add-in loads. +```javascript + Office.context.requirements.isSetSupported("NestedAppAuth", "1.1"); +``` + +For more information, see the following resources. + +- [Outlook sample: How to fall back and support Internet Explorer 11](https://github.com/OfficeDev/Office-Add-in-samples/blob/main/Samples/auth/Outlook-Add-in-SSO-NAA-IE/README.md) - [Authenticate and authorize with the Office dialog API](/office/dev/add-ins/develop/auth-with-office-dialog-api). - [Microsoft identity sample for SPA and JavaScript](https://github.com/Azure-Samples/ms-identity-javascript-tutorial/blob/main/2-Authorization-I/1-call-graph/README.md) - [Microsoft identity samples for various app types and frameworks](/entra/identity-platform/sample-v2-code?tabs=apptype) @@ -237,35 +253,35 @@ The following table shows which APIs are supported when NAA is enabled in the MS | Method | Supported by NAA | | ----------------------------- | --------------------- | -| _acquireTokenByCode_ | NO (throws exception) | -| _acquireTokenPopup_ | YES | -| _acquireTokenRedirect_ | NO (throws exception) | -| _acquireTokenSilent_ | YES | -| _addEventCallback_ | YES | -| _addPerformanceCallback_ | NO (throws exception) | -| _disableAccountStorageEvents_ | NO (throws exception) | -| _enableAccountStorageEvents_ | NO (throws exception) | -| _getAccountByHomeId_ | YES | -| _getAccountByLocalId_ | YES | -| _getAccountByUsername_ | YES | -| _getActiveAccount_ | YES | -| _getAllAccounts_ | YES | -| _getConfiguration_ | YES | -| _getLogger_ | YES | -| _getTokenCache_ | NO (throws exception) | -| _handleRedirectPromise_ | NO | -| _initialize_ | YES | -| _initializeWrapperLibrary_ | YES | -| _loginPopup_ | YES | -| _loginRedirect_ | NO (throws exception) | -| _logout_ | NO (throws exception) | -| _logoutPopup_ | NO (throws exception) | -| _logoutRedirect_ | NO (throws exception) | -| _removeEventCallback_ | YES | -| _removePerformanceCallback_ | NO (throws exception) | -| _setActiveAccount_ | NO | -| _setLogger_ | YES | -| _ssoSilent_ | YES | +| `acquireTokenByCode` | No (throws exception) | +| `acquireTokenPopup` | Yes | +| `acquireTokenRedirect` | No (throws exception) | +| `acquireTokenSilent` | Yes | +| `addEventCallback` | Yes | +| `addPerformanceCallback` | No (throws exception) | +| `disableAccountStorageEvents` | No (throws exception) | +| `enableAccountStorageEvents` | No (throws exception) | +| `getAccountByHomeId` | Yes | +| `getAccountByLocalId` | Yes | +| `getAccountByUsername` | Yes | +| `getActiveAccount` | Yes | +| `getAllAccounts` | Yes | +| `getConfiguration` | Yes | +| `getLogger` | Yes | +| `getTokenCache` | No (throws exception) | +| `handleRedirectPromise` | No | +| `initialize` | Yes | +| `initializeWrapperLibrary` | Yes | +| `loginPopup` | Yes | +| `loginRedirect` | No (throws exception) | +| `logout` | No (throws exception) | +| `logoutPopup` | No (throws exception) | +| `logoutRedirect` | No (throws exception) | +| `removeEventCallback` | Yes | +| `removePerformanceCallback` | No (throws exception) | +| `setActiveAccount` | No | +| `setLogger` | Yes | +| `ssoSilent` | Yes | ## Security reporting @@ -275,5 +291,13 @@ If you find a security issue with our libraries or services, report the issue to | Sample name | Description | | ----------- | ------------ | -| [Office Add-in with SSO using nested app authentication](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Office-Add-in-SSO-NAA) | Shows how to use MSAL.js nested app authentication (NAA) in an Office Add-in to access Microsoft Graph APIs for the signed-in user. The sample displays the signed-in user's name and email. It also inserts the names of files from the user's Microsoft OneDrive account into the document. | -| [Outlook add-in with SSO using nested app authentication](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Outlook-Add-in-SSO-NAA) | Shows how to use MSAL.js nested app authentication (NAA) in an Outlook Add-in to access Microsoft Graph APIs for the signed-in user. The sample displays the signed-in user's name and email. It also inserts the names of files from the user's Microsoft OneDrive account into a new message body. | +| [Office Add-in with SSO using nested app authentication](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Office-Add-in-SSO-NAA) | Shows how to use NAA in an Office Add-in to access Microsoft Graph APIs for the signed-in user. | +| [Outlook add-in with SSO using nested app authentication](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Outlook-Add-in-SSO-NAA) | Shows how to use NAA in an Outlook Add-in to access Microsoft Graph APIs for the signed-in user. | +|[Implement SSO in events in an Outlook add-in using nested app authentication](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Outlook-Event-SSO-NAA) |Shows how to use NAA and SSO in Outlook add-in events.| +|[Send identity claims to resources using nested app authentication (NAA) and SSO](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Outlook-Add-in-SSO-NAA-Identity)|Shows how to send the signed-in user's identity claims (such as name, email, or a unique ID) to a resource such as a database. This sample replaces an obsolete pattern for legacy Exchange Online tokens.| +|[Outlook add-in with SSO using nested app authentication including Internet Explorer fallback](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Outlook-Add-in-SSO-NAA-IE)|Shows how to implement a fallback authentication strategy when NAA isn't available and the add-in needs to support [Outlook versions that still use Internet Explorer 11](../concepts/browsers-used-by-office-web-add-ins.md).| + +## See also + +- [NAA FAQ](https://aka.ms/NAAFAQ) +- [Nested app authentication in Microsoft Teams](/microsoftteams/platform/concepts/authentication/nested-authentication). diff --git a/docs/develop/event-based-activation.md b/docs/develop/event-based-activation.md new file mode 100644 index 0000000000..ff30e6cbdb --- /dev/null +++ b/docs/develop/event-based-activation.md @@ -0,0 +1,219 @@ +--- +title: Activate add-ins with events +description: Learn how to develop an Office Add-in that implements event-based activation. +ms.date: 10/28/2025 +ms.topic: concept-article +ms.localizationpriority: medium +--- + +# Activate add-ins with events + +Event-based activation automatically triggers your add-in to complete their tasks without explicitly launching it. This allows the add-in to validate, insert, or refresh critical content without any manual operations. The add-in is opened in the background to avoid disrupting the user. You can also integrate event-based activation with the task pane and function commands. + +## Overview + +While the particular steps to add event-based functionality to your add-in vary by platform and manifest type, the general flow is as follows. + +1. Update the manifest with an extension for the event. +1. Connect the event in the manifest with a JavaScript function to handle the event. +1. Have the event handler function perform its actions, then call `event.completed` when it finishes. +1. Call [Office.actions.associate](/javascript/api/office/office.actions#office-office-actions-associate-member(1)) to connect the event handler function with the ID specified in the manifest. + +## Try out event-based activation + +Discover how to streamline workflows and improve user experiences with event-based activation. Try out the samples to see the feature in action. + +### Outlook samples + +- [Automatically set the subject of a new message or appointment](../outlook/on-new-compose-events-walkthrough.md) +- [Automatically check for an attachment before a message is sent](../outlook/smart-alerts-onmessagesend-walkthrough.md) +- [Automatically update your signature when switching between mail accounts](../outlook/onmessagefromchanged-onappointmentfromchanged-events.md) +- [Encrypt attachments, process meeting request attendees, and react to appointment date/time changes using Outlook event-based activation](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/outlook-encrypt-attachments) +- [Set your signature using Outlook event-based activation](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/outlook-set-signature) +- [Identify and tag external recipients using Outlook event-based activation](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/outlook-tag-external) +- [Verify the color categories of a message or appointment before it's sent using Smart Alerts](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/outlook-check-item-categories) +- [Verify the sensitivity label of a message](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/outlook-verify-sensitivity-label) + +### Word samples + +- [Add headers when a document opens](../word/add-headers-on-document-open.md) + +## Supported events + +The following tables list events that are currently available and the supported clients for each event. When an event is raised, the handler receives an `event` object which may include details specific to the type of event. The **Description** column includes a link to the related object where applicable. + +### Excel, PowerPoint, Word events + +| Event canonical name</br>and add-in only manifest name | Unified manifest for Microsoft 365 name | Description | Supported clients and channels | +| ----- | ----- | ----- | ----- | +| `OnDocumentOpened` | *Not yet supported* | Occurs when a user opens a document or creates a new document, spreadsheet, or presentation. | <ul><li>Windows (Build >= 16.0.18324.20032)</li><li>Office on the web</li><li>Office on Mac will be available later </li></ul>| + +### Outlook events + +Support for this feature in Outlook was introduced in [requirement set 1.10](/javascript/api/requirement-sets/outlook/requirement-set-1.10/outlook-requirement-set-1.10), with additional events now available in subsequent requirement sets. The following table lists each event's minimum requirement set and the clients and platforms that support it. For more information on Outlook clients and the requirement sets they support, see [Requirement sets supported by Exchange servers and Outlook clients](/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets#requirement-sets-supported-by-exchange-servers-and-outlook-clients). + +|Event canonical name</br>and add-in only manifest name|Unified manifest for Microsoft 365 name|Description|Minimum requirement set and supported clients| +|---|---|---|---| +|`OnNewMessageCompose`| newMessageComposeCreated |On composing a new message (includes reply, reply all, and forward) but not on editing, for example, a draft.|[1.10](/javascript/api/requirement-sets/outlook/requirement-set-1.10/outlook-requirement-set-1.10)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li><li>Android<sup>2</sup> <sup>3</sup></li><li>iOS<sup>2</sup> <sup>3</sup></li></ul>| +|`OnNewAppointmentOrganizer`|newAppointmentOrganizerCreated|On creating a new appointment but not on editing an existing one.|[1.10](/javascript/api/requirement-sets/outlook/requirement-set-1.10/outlook-requirement-set-1.10)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnMessageAttachmentsChanged`|messageAttachmentsChanged|On adding or removing attachments while composing a message.<br><br>Event-specific data object: [AttachmentsChangedEventArgs](/javascript/api/outlook/office.attachmentschangedeventargs?view=outlook-js-1.11&preserve-view=true)|[1.11](/javascript/api/requirement-sets/outlook/requirement-set-1.11/outlook-requirement-set-1.11)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnAppointmentAttachmentsChanged`|appointmentAttachmentsChanged|On adding or removing attachments while composing an appointment.<br><br>Event-specific data object: [AttachmentsChangedEventArgs](/javascript/api/outlook/office.attachmentschangedeventargs?view=outlook-js-1.11&preserve-view=true)|[1.11](/javascript/api/requirement-sets/outlook/requirement-set-1.11/outlook-requirement-set-1.11)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnMessageRecipientsChanged`|messageRecipientsChanged|On adding or removing recipients while composing a message.<br><br>Event-specific data object: [RecipientsChangedEventArgs](/javascript/api/outlook/office.recipientschangedeventargs?view=outlook-js-1.11&preserve-view=true)|[1.11](/javascript/api/requirement-sets/outlook/requirement-set-1.11/outlook-requirement-set-1.11)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li><li>Android<sup>2</sup> <sup>3</sup></li><li>iOS<sup>2</sup> <sup>3</sup></li></ul>| +|`OnAppointmentAttendeesChanged`|appointmentAttendeesChanged|On adding or removing attendees while composing an appointment.<br><br>Event-specific data object: [RecipientsChangedEventArgs](/javascript/api/outlook/office.recipientschangedeventargs?view=outlook-js-1.11&preserve-view=true)|[1.11](/javascript/api/requirement-sets/outlook/requirement-set-1.11/outlook-requirement-set-1.11)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnAppointmentTimeChanged`|appointmentTimeChanged|On changing date/time while composing an appointment.<br><br>Event-specific data object: [AppointmentTimeChangedEventArgs](/javascript/api/outlook/office.appointmenttimechangedeventargs?view=outlook-js-1.11&preserve-view=true)<br><br>**Important**: If you drag and drop an appointment to a different date/time slot on the calendar, the `OnAppointmentTimeChanged` event doesn't occur. It only occurs when the date/time is directly changed from an appointment. |[1.11](/javascript/api/requirement-sets/outlook/requirement-set-1.11/outlook-requirement-set-1.11)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnAppointmentRecurrenceChanged`|appointmentRecurrenceChanged|On adding, changing, or removing the recurrence details while composing an appointment. If the date/time is changed, the `OnAppointmentTimeChanged` event also occurs.<br><br>Event-specific data object: [RecurrenceChangedEventArgs](/javascript/api/outlook/office.recurrencechangedeventargs?view=outlook-js-1.11&preserve-view=true)|[1.11](/javascript/api/requirement-sets/outlook/requirement-set-1.11/outlook-requirement-set-1.11)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnInfoBarDismissClicked`|infoBarDismissClicked|On dismissing a notification while composing a message or appointment item. Only the add-in that added the notification will be notified.<br><br>Event-specific data object: [InfobarClickedEventArgs](/javascript/api/outlook/office.infobarclickedeventargs?view=outlook-js-1.11&preserve-view=true)|[1.11](/javascript/api/requirement-sets/outlook/requirement-set-1.11/outlook-requirement-set-1.11)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnMessageSend`|messageSending|On sending a message item. To learn more, try the [Smart Alerts walkthrough](../outlook/smart-alerts-onmessagesend-walkthrough.md).|[1.12](/javascript/api/requirement-sets/outlook/requirement-set-1.12/outlook-requirement-set-1.12)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnAppointmentSend`|appointmentSending|On sending an appointment item. To learn more, see [Handle OnMessageSend and OnAppointmentSend events in your Outlook add-in with Smart Alerts](../outlook/onmessagesend-onappointmentsend-events.md).|[1.12](/javascript/api/requirement-sets/outlook/requirement-set-1.12/outlook-requirement-set-1.12)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnMessageCompose`|messageComposeOpened|On composing a new message (includes reply, reply all, and forward) or editing a draft.|[1.12](/javascript/api/requirement-sets/outlook/requirement-set-1.12/outlook-requirement-set-1.12)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnAppointmentOrganizer`|appointmentOrganizerOpened|On creating a new appointment or editing an existing one.|[1.12](/javascript/api/requirement-sets/outlook/requirement-set-1.12/outlook-requirement-set-1.12)<ul><li>Web browser</li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnMessageFromChanged`|messageFromChanged|On changing the mail account in the **From** field of a message being composed. To learn more, see [Automatically update your signature when switching between Exchange accounts](../outlook/onmessagefromchanged-onappointmentfromchanged-events.md).|[1.13](/javascript/api/requirement-sets/outlook/requirement-set-1.13/outlook-requirement-set-1.13)<ul><li>Web browser<sup>4</sup></li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627)<sup>4</sup> and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li><li>Android<sup>2</sup> <sup>3</sup></li><li>iOS<sup>2</sup> <sup>3</sup></li></ul>| +|`OnAppointmentFromChanged`|appointmentFromChanged|On changing the mail account in the organizer field of an appointment being composed. To learn more, see [Automatically update your signature when switching between Exchange accounts](../outlook/onmessagefromchanged-onappointmentfromchanged-events.md).|[1.13](/javascript/api/requirement-sets/outlook/requirement-set-1.13/outlook-requirement-set-1.13)<ul><li>New Mac UI<sup>2</sup></li></ul>| +|`OnSensitivityLabelChanged`|sensitivityLabelChanged|On changing the sensitivity label while composing a message or appointment. To learn how to manage the sensitivity label of a mail item, see [Manage the sensitivity label of your message or appointment in compose mode](../outlook/sensitivity-label.md).<br><br>Event-specific data object: [SensitivityLabelChangedEventArgs](/javascript/api/outlook/office.sensitivitylabelchangedeventargs?view=outlook-js-preview&preserve-view=true)|[1.13](/javascript/api/requirement-sets/outlook/requirement-set-1.13/outlook-requirement-set-1.13)<ul><li>Web browser<sup>4</sup></li><li>Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627)<sup>4</sup> and classic<sup>1</sup>)</li><li>New Mac UI<sup>2</sup></li></ul>| +|`OnMessageReadWithCustomAttachment`|Not available|On opening a message that contains a specific attachment type in read mode.|[Preview](/javascript/api/requirement-sets/outlook/preview-requirement-set/outlook-requirement-set-preview)<sup>5</sup><ul><li>Windows (classic<sup>1</sup>)</li></ul>| +|`OnMessageReadWithCustomHeader`|Not available|On opening a message that contains a specific internet header name in read mode.|[Preview](/javascript/api/requirement-sets/outlook/preview-requirement-set/outlook-requirement-set-preview)<sup>5</sup><ul><li>Windows (classic<sup>1</sup>)</li></ul>| +|`OnMessageRead` (preview)|Not available|On matching the header of an encrypted message to the header key in an add-in's manifest. To learn more, see [Create an encryption Outlook add-in](../outlook/encryption-decryption.md).|[Preview](/javascript/api/requirement-sets/outlook/preview-requirement-set/outlook-requirement-set-preview)<ul><li>Windows (classic<sup>1</sup>)</li></ul>| + +> [!NOTE] +> <sup>1</sup> Event-based add-ins in classic Outlook on Windows require a minimum of Windows 10 Version 1903 (Build 18362) or Windows Server 2019 Version 1903 to run. +> +> <sup>2</sup> Add-ins that use the unified manifest for Microsoft 365 aren't directly supported in Outlook on Mac and on mobile devices. To run this type of add-in on Mac and on mobile platforms, the add-in must first be published to [Microsoft Marketplace](https://marketplace.microsoft.com/) then deployed in the [Microsoft 365 Admin Center](../publish/publish.md). For more information, see the "Client and platform support" section of [Office Add-ins with the unified app manifest for Microsoft 365](../develop/unified-manifest-overview.md#client-and-platform-support). +> +> <sup>3</sup> For more information, see [Implement event-based activation in Outlook mobile add-ins](../outlook/mobile-event-based.md). +> +> <sup>4</sup> The `OnMessageFromChanged` and `OnSensitivityLabelChanged` events aren't currently available with the unified manifest for Microsoft 365 in Outlook on the web and the new Outlook on Windows. To handle these events, implement an add-in only manifest instead. For information about the types of manifests, see [Office Add-ins manifest](add-in-manifests.md). +> +> <sup>5</sup> To preview the `OnMessageReadWithCustomAttachment` and `OnMessageReadWithCustomHeader` events, you must install classic Outlook on Windows Version 2312 (Build 17110.10000) or later. Then, join the [Microsoft 365 Insider program](https://techcommunity.microsoft.com/blog/microsoft365insiderblog/join-the-microsoft-365-insider-program-on-windows/4206638) and select the **Beta Channel** option to access Office beta builds. + +#### Event-based activation in Outlook on mobile devices + +Outlook on mobile supports APIs up to Mailbox requirement set 1.5. However, support is now enabled for additional APIs and features introduced in later requirement sets, such as the `OnNewMessageCompose` event. To learn more, see [Implement event-based activation in Outlook mobile add-ins](../outlook/mobile-event-based.md). + +## Behavior and limitations + +As you develop an event-based add-in, be mindful of the following feature behaviors and limitations. + +- Event-based add-ins work only when deployed by an administrator. If users install them directly from Microsoft Marketplace or the Office Store, they will not automatically launch (for workarounds to the Microsoft Marketplace limitation, see [Microsoft Marketplace listing options for your event-based add-in](../publish/autolaunch-store-options.md)). Admin deployments are done by uploading the manifest to the Microsoft 365 admin center. + +- APIs that interact with the UI or display UI elements are not supported for Word, PowerPoint, and Excel on Windows. This is because the event handler runs in a JavaScript-only runtime. For more information, see [Runtimes in Office Add-ins](../testing/runtimes.md). + +- Event-based add-ins require an internet connection to be able to launch when a specific event occurs. Add-in event handlers are expected to be short-running, lightweight, and as noninvasive as possible. After activation, your add-in will time out within approximately 300 seconds, the maximum length of time allowed for running event-based add-ins. To signal that your add-in has completed processing a launch event, your associated event handler must call the [event.completed](/javascript/api/outlook/office.mailboxevent#outlook-office-mailboxevent-completed-member(1)) method. (Note that code included after the `event.completed` statement isn't guaranteed to run.) Each time an event that your add-in handles is triggered, the add-in is reactivated and runs the associated event handler, and the timeout window is reset. The add-in ends after it times out, or the user closes the compose window or sends the item. + +- The behavior of multiple add-ins that subscribe to the same event isn't deterministic. Outlook launches the add-ins in no particular order. For Excel, PowerPoint, and Word, only one random add-in will be activated. For example, if multiple Word add-ins that handle `OnDocumentOpened`, only one of those handlers will run. + +- Currently, only five event-based add-ins can be actively running. + +- In all supported Outlook clients, the user must remain on the current mail item where the add-in was activated for it to complete running. Navigating away from the current item (for example, switching to another compose window or tab) terminates the add-in operation. However, an add-in that activates on the `OnMessageSend` event handles item switching differently depending on which Outlook client it's running on. To learn more, see the "User navigates away from current message" section of [Handle OnMessageSend and OnAppointmentSend events in your Outlook add-in with Smart Alerts](../outlook/onmessagesend-onappointmentsend-events.md#user-navigates-away-from-current-message). + +- In addition to item switching, an event-based add-in also ceases operation when the user sends the message or appointment they're composing. + +### Event-based add-in limitations in the new Outlook on Windows + +In the new Outlook on Windows, you must keep the main window of the client open for the add-in to process the mail item. If the main window is minimized, the add-in will pause or stop working. + +### Event-based add-in limitations in Excel, PowerPoint, Word, and classic Outlook on Windows + +When developing an event-based add-in to run on a Windows client, be mindful of the following: + +- Imports aren't supported in the JavaScript file where you implement the handling for event-based activation. +- Only the JavaScript file referenced in the manifest is supported for event-based activation. You must bundle your event-handling JavaScript code into this single file. The location of the referenced JavaScript file in the manifest varies depending on the type of manifest your add-in uses. + - **Add-in only manifest**: `<Override>` child element of the `<Runtime>` node + - **Unified manifest for Microsoft 365**: `"script"` property of the `"code"` object + + Note that a large JavaScript bundle may cause issues with the performance of your add-in. We recommend preprocessing heavy operations, so that they're not included in your event-handling code. +- When the JavaScript function specified in the manifest to handle an event runs, code in `Office.onReady()` and `Office.initialize` isn't run. We recommend adding any startup logic needed by event handlers, such as checking the user's client version, to the event handlers instead. + +### Event-based add-in limitations in Excel, PowerPoint, and Word + +The following platforms or features are not yet supported. + +- Office on Mac +- The unified manifest for Microsoft 365 + +### Unsupported APIs + +Some Office.js APIs that change or alter the UI aren't allowed from event-based add-ins. The following are blocked APIs. + +| API | Methods | +| --- | --- | +| `Office.devicePermission` | <ul><li>`requestPermissionsAsync`</li></ul> | +| `Office.context.auth`\* | <ul><li>`getAccessToken`</li><li>`getAccessTokenAsync`</li></ul> | +| `Office.context.mailbox` | <ul><li>`displayAppointmentForm`</li><li>`displayMessageForm`</li><li>`displayNewAppointmentForm`</li><li>`displayNewMessageForm`</li></ul> | +| `Office.context.mailbox.item` | <ul><li>`close`</li></ul> | +| `Office.context.ui` | <ul><li>`displayDialogAsync`</li><li>`messageParent`</li></ul>| + +> [!NOTE] +> \* [OfficeRuntime.auth](/javascript/api/office-runtime/officeruntime.auth) is supported in all versions that support event-based activation and single sign-on (SSO), while [Office.auth](/javascript/api/office/office.auth) is only supported in certain Outlook builds. For more information, see [Use single sign-on (SSO) or cross-origin resource sharing (CORS) in your event-based or spam-reporting Outlook add-in](../develop/use-sso-in-event-based-activation.md). + +### Preview features in event handlers (classic Outlook on Windows) + +Classic Outlook on Windows includes a local copy of the production and beta versions of Office.js instead of loading from the content delivery network (CDN). By default, the local production copy of the API is referenced. To reference the local beta copy of the API, you must configure your computer's registry. This will enable you to test [preview features](/javascript/api/requirement-sets/outlook/preview-requirement-set/outlook-requirement-set-preview) in your event handlers in classic Outlook on Windows. + +1. In the registry, navigate to `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Outlook\Options\WebExt\Developer`. If the key doesn't exist, create it. +1. Create an entry named `EnableBetaAPIsInJavaScript` and set its value to `1`. + + ![The EnableBetaAPIsInJavaScript registry value is set to 1."](../images/outlook-beta-registry-key.png) + +## Enable single sign-on (SSO) + +To enable SSO in your event-based add-in, you must add its JavaScript file to a well-known URI. For guidance on how to configure this resource, see [Use single sign-on (SSO) or cross-origin resource sharing (CORS) in your event-based or spam-reporting Office Add-in](../develop/use-sso-in-event-based-activation.md). + +### Request external data + +You can request external data by using an API like [Fetch](https://developer.mozilla.org/docs/Web/API/Fetch_API) or by using [XMLHttpRequest (XHR)](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest), a standard web API that issues HTTP requests to interact with servers. + +> [!NOTE] +> If your add-in will operate in a JavaScript-only runtime, use absolute URLs in your Fetch API calls. Relative URLs in Fetch API calls aren't supported in a JavaScript-only runtime. + +Be aware that you must use additional security measures when using XMLHttpRequest objects, requiring [Same Origin Policy](https://developer.mozilla.org/docs/Web/Security/Same-origin_policy) and [CORS (Cross-Origin Resource Sharing)](https://developer.mozilla.org/docs/Web/HTTP/CORS). + +> [!NOTE] +> Full CORS support is available in Office on the web, Mac, and Windows (starting in Version 2201, Build 16.0.14813.10000) clients. + +To make CORS requests from your event-based add-in, you must add the add-in and its JavaScript file to a well-known URI. For guidance on how to configure this resource, see [Use single sign-on (SSO) or cross-origin resource sharing (CORS) in your event-based or spam-reporting Office Add-in](../develop/use-sso-in-event-based-activation.md). + +## Troubleshoot your add-in + +As you develop your event-based add-in, you may need to troubleshoot issues, such as your add-in not loading or the event not occurring. For guidance on how to troubleshoot an event-based add-in, see [Troubleshoot event-based and spam-reporting add-ins](../testing/troubleshoot-event-based-and-spam-reporting-add-ins.md). + +## Deploy your add-in + +Depending on the Office application, event-based add-ins can be deployed through one of the following options. +- **Admin-managed deployment**: Add-in is deployed through the Microsoft 365 admin center. +- **Restricted listing on Microsoft Marketplace**: Add-in is published to Microsoft Marketplace, but it doesn't appear in search results. Add-in acquisition requires a flight code URL. The add-in must still be deployed by an admin for the event-based activation feature to work. +- **Unrestricted listing on Microsoft Marketplace**: Add-in is published to Microsoft Marketplace and can be searched for by users and admins using the add-in's name or ID. Admin deployment isn't necessary for the event-based activation feature to work. The add-in must meet certain requirements for unrestricted listing. + +The following table outlines the deployment options for event-based activation by Office application. + +| Office application | Admin-managed deployment | Microsoft Marketplace | +| --- | --- | --- | +| **Excel** | Supported | Restricted listing option | +| **Outlook** | Supported | Restricted and unrestricted listing options | +| **PowerPoint** | Supported | Restricted listing option | +| **Word** | Supported | Restricted listing option | + +For instructions on how to deploy an add-in through the Microsoft 365 admin center, see [Admin-managed deployment](#admin-managed-deployment). To learn more about listing your event-based add-in in Microsoft Marketplace, see [Microsoft Marketplace listing options for your event-based add-in](../publish/autolaunch-store-options.md). + +[!INCLUDE [outlook-smart-alerts-deployment](../includes/outlook-smart-alerts-deployment.md)] + +### Admin-managed deployment + +Admin deployments are done by uploading the manifest to the Microsoft 365 admin center. To do so, follow these steps. + +1. In the admin portal, expand the **Settings** section in the navigation pane then select **Integrated apps**. +1. On the **Integrated apps** page, choose the **Upload custom apps** action. + +![The Integrated apps page on the Microsoft 365 admin center with the Upload custom apps action highlighted.](../images/outlook-deploy-event-based-add-ins.png) + +For more information about how to deploy an add-in, please refer to [Deploy and publish Office Add-ins in the Microsoft 365 admin center](/microsoft-365/admin/manage/office-addins). + +### Deploy manifest updates + +If an event-based add-in was admin-deployed, any change you make to the manifest requires admin consent through the Microsoft 365 admin center. Until the admin accepts your changes, users in their organization are blocked from using the add-in. To learn more about the admin consent process, see [Admin consent for installing event-based add-ins](../publish/autolaunch-store-options.md#admin-consent-for-installing-event-based-add-ins). + +## See also + +- [Troubleshoot event-based and spam-reporting add-ins](../testing/troubleshoot-event-based-and-spam-reporting-add-ins.md) +- [Debug event-based and spam-reporting add-ins](../testing/debug-autolaunch.md) +- [Microsoft Marketplace listing options for your event-based add-in](../publish/autolaunch-store-options.md) +- [Handle OnMessageSend and OnAppointmentSend events in your Outlook add-in with Smart Alerts](../outlook/onmessagesend-onappointmentsend-events.md) diff --git a/docs/develop/extended-overrides.md b/docs/develop/extended-overrides.md deleted file mode 100644 index 0f13ed36c7..0000000000 --- a/docs/develop/extended-overrides.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Work with extended overrides of the manifest -description: Learn how to configure extensibility features with extended overrides of the manifest. -ms.topic: how-to -ms.date: 08/18/2023 -ms.localizationpriority: medium ---- - -# Work with Extended Overrides of the manifest - -When your add-in uses the XML-formatted add-in only manifest, some extensibility features of Office Add-ins are configured with JSON files that are hosted on your server, instead of with the add-in's manifest. - -> [!NOTE] -> This article assumes that you're familiar with Office Add-in manifests and their role in add-ins. Please read [Office Add-ins manifest](add-in-manifests.md), if you haven't recently. - -The following table specifies the extensibility features that require an extended override along with links to documentation of the feature. - -| Feature | Development Instructions | -| :----- | :----- | -| Keyboard shortcuts | [Add Custom keyboard shortcuts to your Office Add-ins](../design/keyboard-shortcuts.md) | - -<!-- In the following link, the "en-us" must be present or the link breaks. --> -The schema that defines the JSON format is [extended-manifest schema](https://developer.microsoft.com/json-schemas/office-js/extended-manifest.schema.json). - -> [!TIP] -> This article is somewhat abstract. Consider reading one of the articles in the table to add clarity to the concepts. - -## Tell Office where to find the JSON file - -Use the manifest to tell Office where to find the JSON file. Immediately *below* (not inside) the **\<VersionOverrides\>** element in the manifest, add an [ExtendedOverrides](/javascript/api/manifest/extendedoverrides) element. Set the `Url` attribute to the full URL of a JSON file. The following is an example of the simplest possible **\<ExtendedOverrides\>** element. - -```xml - ... - </VersionOverrides> - <ExtendedOverrides Url="https://contoso.com/addin/extended-overrides.json"></ExtendedOverrides> -</OfficeApp> -``` - -The following is an example of a very simple extended overrides JSON file. It assigns keyboard shortcut CTRL+SHIFT+A to a function (defined elsewhere) that opens the add-in's task pane. - -```json -{ - "actions": [ - { - "id": "SHOWTASKPANE", - "type": "ExecuteFunction", - "name": "Show task pane for add-in" - } - ], - "shortcuts": [ - { - "action": "SHOWTASKPANE", - "key": { - "default": "CTRL+SHIFT+A" - } - } - ] -} -``` - -## Localize the extended overrides file - -If your add-in supports multiple locales, you can use the `ResourceUrl` attribute of the **\<ExtendedOverrides\>** element to point Office to a file of localized resources. The following is an example. - -```xml - ... - </VersionOverrides> - <ExtendedOverrides Url="https://contoso.com/addin/extended-overrides.json" - ResourceUrl="https://contoso.com/addin/my-resources.json"> - </ExtendedOverrides> -</OfficeApp> -``` - -For more details about how to create and use the resources file, how to refer to its resources in the extended overrides file, and for additional options not discussed here, see [Localize extended overrides](localization.md#localize-extended-overrides). diff --git a/docs/develop/get-javascript-intellisense-in-visual-studio.md b/docs/develop/get-javascript-intellisense-in-visual-studio.md index 84816789ee..dd9b269d29 100644 --- a/docs/develop/get-javascript-intellisense-in-visual-studio.md +++ b/docs/develop/get-javascript-intellisense-in-visual-studio.md @@ -2,7 +2,7 @@ title: Get JavaScript IntelliSense in Visual Studio description: Learn how to use JSDoc to create IntelliSense for your JavaScript variables, objects, parameters, and return values. ms.topic: best-practice -ms.date: 08/18/2023 +ms.date: 09/30/2025 ms.localizationpriority: medium --- diff --git a/docs/develop/get-the-whole-document-from-an-add-in-for-powerpoint-or-word.md b/docs/develop/get-the-whole-document-from-an-add-in-for-powerpoint-or-word.md index fbf7bc5ee4..9cec2bae1c 100644 --- a/docs/develop/get-the-whole-document-from-an-add-in-for-powerpoint-or-word.md +++ b/docs/develop/get-the-whole-document-from-an-add-in-for-powerpoint-or-word.md @@ -1,7 +1,7 @@ --- title: Get the whole document from an add-in for PowerPoint or Word description: Learn to get the whole document from a PowerPoint or Word add-in. -ms.date: 04/26/2024 +ms.date: 02/12/2025 ms.topic: how-to ms.localizationpriority: medium --- @@ -22,7 +22,7 @@ This article assumes that you are using a text editor to create the task pane ad - A CSS file (**Program.css**) to contain the styles and formatting for the add-in. -- An add-in only manifest file (**GetDoc_App.xml**) for the add-in, available on a shared network folder or add-in catalog. The manifest file must point to the location of the HTML file mentioned previously. +- A manifest file (**GetDoc_App.xml** or **GetDoc_App.json**) for the add-in, available on a shared network folder or add-in catalog. The manifest file must point to the location of the HTML file mentioned previously. Alternatively, you can create an add-in for your Office application using one of the following options. You won't have to create new files as the equivalent of each required file will be available for you to update. For example, the Yeoman generator options include **./src/taskpane/taskpane.html**, **./src/taskpane/taskpane.js**, **./src/taskpane/taskpane.css**, and **./manifest.xml**. @@ -41,33 +41,114 @@ Before you begin creating this add-in for PowerPoint or Word, you should be fami The manifest file for an Office Add-in provides important information about the add-in: what applications can host it, the location of the HTML file, the add-in title and description, and many other characteristics. -1. In a text editor, add the following code to the manifest file. - - ```xml - <?xml version="1.0" encoding="utf-8" ?> - <OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:type="TaskPaneApp"> - <Id>[Replace_With_Your_GUID]</Id> - <Version>1.0</Version> - <ProviderName>[Provider Name]</ProviderName> - <DefaultLocale>EN-US</DefaultLocale> - <DisplayName DefaultValue="Get Doc add-in" /> - <Description DefaultValue="My get PowerPoint or Word document add-in." /> - <IconUrl DefaultValue="http://officeimg.vo.msecnd.net/_layouts/images/general/office_logo.jpg" /> - <SupportUrl DefaultValue="[Insert the URL of a page that provides support information for the app]" /> - <Hosts> - <Host Name="Document" /> - <Host Name="Presentation" /> - </Hosts> - <DefaultSettings> - <SourceLocation DefaultValue="[Network location of app]/GetDoc_App.html" /> - </DefaultSettings> - <Permissions>ReadWriteDocument</Permissions> - </OfficeApp> - ``` +In a text editor, add the following code to the manifest file. If you're using a Visual Studio project, select the "Add-in only manifest" option. + +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) + +> [!NOTE] +> The unified manifest is generally available for production Outlook add-ins. It's available only for preview in Excel, PowerPoint, and Word add-ins. + +```json +{ + "$schema": "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.schema.json#", + "manifestVersion": "devPreview", + "version": "1.0.0.0", + "id": "[Replace_With_Your_GUID]", + "localizationInfo": { + "defaultLanguageTag": "en-us" + }, + "developer": { + "name": "[Provider Name e.g., Contoso]", + "websiteUrl": "[Insert the URL for the app e.g., https://www.contoso.com]", + "privacyUrl": "[Insert the URL of a page that provides privacy information for the app e.g., https://www.contoso.com/privacy]", + "termsOfUseUrl": "[Insert the URL of a page that provides terms of use for the app e.g., https://www.contoso.com/servicesagreement]" + }, + "name": { + "short": "Get Doc add-in", + "full": "Get Doc add-in" + }, + "description": { + "short": "My get PowerPoint or Word document add-in.", + "full": "My get PowerPoint or Word document add-in." + }, + "icons": { + "outline": "_layouts/images/general/office_logo.jpg", + "color": "_layouts/images/general/office_logo.jpg" + }, + "accentColor": "#230201", + "validDomains": [ + "https://www.contoso.com/" + ], + "showLoadingIndicator": false, + "isFullScreen": false, + "defaultBlockUntilAdminAction": false, + "authorization": { + "permissions": { + "resourceSpecific": [ + { + "name": "Document.ReadWrite.User", + "type": "Delegated" + } + ] + } + }, + "extensions": [ + { + "requirements": { + "scopes": [ + "document", + "presentation" + ] + }, + "alternates": [ + { + "alternateIcons": { + "icon": { + "size": 32, + "url": "http://officeimg.vo.msecnd.net/_layouts/images/general/office_logo.jpg" + }, + "highResolutionIcon": { + "size": 64, + "url": "http://officeimg.vo.msecnd.net/_layouts/images/general/office_logo.jpg" + } + } + } + ] + } + ] +} +``` -1. Save the file as **GetDoc_App.xml** using UTF-8 encoding to a network location or to an add-in catalog. +# [Add-in only manifest](#tab/xmlmanifest) + +```xml +<?xml version="1.0" encoding="utf-8" ?> +<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:type="TaskPaneApp"> + <Id>[Replace_With_Your_GUID]</Id> + <Version>1.0</Version> + <ProviderName>[Provider Name]</ProviderName> + <DefaultLocale>EN-US</DefaultLocale> + <DisplayName DefaultValue="Get Doc add-in" /> + <Description DefaultValue="My get PowerPoint or Word document add-in." /> + <IconUrl DefaultValue="http://officeimg.vo.msecnd.net/_layouts/images/general/office_logo.jpg" /> + <HighResolutionIconUrl DefaultValue="http://officeimg.vo.msecnd.net/_layouts/images/general/office_logo.jpg" /> + <SupportUrl DefaultValue="[Insert the URL of a page that provides support information for the app]" /> + <Hosts> + <Host Name="Document" /> + <Host Name="Presentation" /> + </Hosts> + <DefaultSettings> + <SourceLocation DefaultValue="[Network location of app]/GetDoc_App.html" /> + </DefaultSettings> + <Permissions>ReadWriteDocument</Permissions> +</OfficeApp> +``` + +Save the file as **GetDoc_App.xml** using UTF-8 encoding to a network location or to an add-in catalog. + +--- ## Create the user interface for the add-in diff --git a/docs/develop/import-teams-toolkit.md b/docs/develop/import-teams-toolkit.md new file mode 100644 index 0000000000..363f3f8d52 --- /dev/null +++ b/docs/develop/import-teams-toolkit.md @@ -0,0 +1,138 @@ +--- +title: Import an add-in project to Microsoft 365 Agents Toolkit +description: Learn how to import an add-in project to Microsoft 365 Agents Toolkit. +ms.topic: how-to +ms.date: 11/06/2025 +ms.localizationpriority: medium +--- + +# Import an add-in project to Microsoft 365 Agents Toolkit + +The [Agents Toolkit extension for Visual Studio Code](/microsoftteams/platform/toolkit/teams-toolkit-fundamentals) is a richly featured tool for working with Apps for Microsoft 365, that is, extensions on the Microsoft 365 developer platform, including Teams apps, Office Add-ins, and Copilot extensions, among others. It also makes it easy to work with extensions that transcend the boundaries between Teams apps, add-ins, and Copilot extensions. For example, it makes sideloading such cross-boundary extensions easier. + +There can be no algorithmic procedure for importing an add-in into the toolkit because an algorithm would have to make assumptions about the following aspects of the project. + +- The folder and file structure of the existing add-in. But these structures vary depending on which tool was used to create the project and what version of that tool. The developer of the add-in might also have changed the structure after the project was created. +- The settings in various configuration files. But these settings also vary depending on how the project was created and changes made to the configuration since it was created. +- Which language, TypeScript or JavaScript, was used for the client-side source code of the web application. + +However, we can make some general recommendations. + +> [!NOTE] +> +> - This article doesn't apply to add-in projects that were created with Visual Studio. Such projects are based on the ASP.NET web application framework and are designed to run on Internet Information Server (IIS). Converting such a project to work in Agents Toolkit would significantly more difficult and is out-of-scope for this article. +> - Add-in projects in Agents Toolkit must use the [unified manifest for Microsoft 365](unified-manifest-overview.md). If your add-in project uses a feature that isn't yet supported with the unified manifest, then you can't import it to Agents Toolkit unless you first redesign it so that it doesn't use unsupported features. +> - Currently, add-ins that use the unified manifest can't be sideloaded on a Mac. If your development computer is a Mac, don't import your project into Agents Toolkit until sideloading on the Mac is supported. + +There are two basic strategies available. + +- [Use the importation feature of the toolkit](#use-the-importation-feature-of-the-toolkit) +- [Start with a new toolkit project](#start-with-a-new-toolkit-project) + +Regardless of which you choose, begin by ensuring that you have installed [Visual Studio Code](https://code.visualstudio.com/) and the [Agents Toolkit](/microsoftteams/platform/toolkit/install-teams-toolkit) extension. + +## Use the importation feature of the toolkit + +There are four tasks to using the importation feature. + +- [Prepare the existing manifest](#prepare-the-existing-manifest) +- [Import the project](#import-the-project) +- [Verify that the add-in can be sideloaded](#verify-that-the-add-in-can-be-sideloaded) +- [Make post-importation adjustments](#make-post-importation-adjustments) + +### Prepare the existing manifest + +> [!IMPORTANT] +> If the existing project uses the add-in only manifest, the importation feature automatically converts it to a unified manifest. So, you must carry out the steps in [Ensure that your manifest is ready to convert](convert-xml-to-json-manifest.md#ensure-that-your-manifest-is-ready-to-convert) before you import the project. + +### Import the project + +1. Open Visual Studio Code and select the Agents Toolkit icon on the **Activity Bar**. + + :::image type="content" source="../images/atk-toolkit-icon.png" alt-text="Agents Toolkit icon."::: + +1. Select **Create a New App**. +1. The **New Project** dropdown menu opens. The options listed vary depending on your version of Agents Toolkit. Select **Office Add-in**. + + :::image type="content" source="../images/atk-toolkit-new-project-list.png" alt-text="The options in New Project dropdown menu. One option is called 'Office Add-in'."::: + +1. The **App Features Using an Office Add-in** dropdown menu opens. The options listed vary depending on your version of Agents Toolkit. Select **Upgrade an Existing Office Add-in**. + + :::image type="content" source="../images/teams-toolkit-create-office-import-capability.png" alt-text="The options in the App Features Using an Office Add-in dropdown menu. The 'Upgrade an Existing Office Add-in' option is selected."::: + +1. In the **Existing add-in project folder** dropdown menu, browse to the root folder of the add-in project. +1. In the **Select import project manifest file** dropdown menu, browse to the add-in only manifest file, typically named **manifest.xml**. +1. In the **Workspace folder** dialog, select the folder where you want to put the converted project. +1. In the **Application name** dialog, give a name to the project (with no spaces). Agents Toolkit creates the project with your source files and scaffolding. It then opens the project *in a second Visual Studio Code window*. Close the original Visual Studio Code window. + +### Verify that the add-in can be sideloaded + +> [!NOTE] +> Add-ins that use the unified manifest can be sideloaded only on Office Version 2304 (Build 16320.20000) or later. + +Sideload the add-in using the instructions at [Sideload with Microsoft 365 Agents Toolkit](../testing/sideload-add-in-with-unified-manifest.md#sideload-with-microsoft-365-agents-toolkit). + +If you encounter problems, as a troubleshooting step, try [sideloading with a system prompt, bash shell, or terminal](../testing/sideload-add-in-with-unified-manifest.md#sideload-with-a-system-prompt-bash-shell-or-terminal). If you can, then the problem is isolated to the toolkit. + +It's possible that sideloading problems are the result of a file and folder structure, or configuration settings, that are different from what Agents Toolkit normally expects. See [Adjust the project structure and settings as needed](#adjust-the-project-structure-and-settings-as-needed). + +### Make post-importation adjustments + +After you import your add-in project, perform the following tasks. + +#### Edit the manifest + +1. Open the unified manifest file. +1. Navigate to the [`"developer"`](/microsoft-365/extensibility/schema/root-developer) property. Ensure that there are child `"privacyUrl"` and `"termsOfUseUrl"` properties and that they have appropriate values. + +#### Adjust the project structure and settings as needed + +The importation process creates some folders and files that Visual Studio Code or Agents Toolkit need, but it doesn't reorganize your source files; such as HTML, JavaScript, and CSS files. It also doesn't change the content of any files in the project, including tool configuration files. We recommend that you change your project to match the pattern of projects that are created in Agents Toolkit. As you work, keep the following points in mind. + +- HTML files in the toolkit projects don't have inline `<script>` elements. They only use `<script>` elements with a `src` attribute that loads an external file. +- Source files in a new toolkit project are in a folder named **\src**. Within this folder, the source files are further divided into subfolders based on the runtimes in which they normally are run. The following is a typical structure. + + ```console + \src + \commands + commands.html + commands.js + \taskpane + taskpane.css + taskpane.html + taskpane.js + ``` + +- Agents Toolkit projects have a folder named **\appPackage**. The manifest and any other files that should be in the app package zip file are in this folder. + +> [!IMPORTANT] +> +> - The URLs in manifest will reflect the original structure of the project. Change these URLs as needed if you make changes in the file and folder structure. +> - Tool configuration files, such as webpack.config.js, may have URLs. Change these as needed. + +## Start with a new toolkit project + +As an alternative to using the toolkit's importation feature, you can create a brand new add-in project in the toolkit and move files from the existing project into it and make changes to other files. The following are the tasks that you need to carry out. + +1. If the existing project uses the add-in only manifest, convert it and ensure that the old project sideloads with the new manifest. For detailed guidance, see [Convert an add-in to use the unified manifest for Microsoft 365](convert-xml-to-json-manifest.md). +1. Create a new add-in project in Agents Toolkit. For each choice the toolkit asks you to make, such as the choice between JavaScript and TypeScript, make the choice that best matches your existing add-in. See [Create Office Add-in projects with Microsoft 365 Agents Toolkit](agents-toolkit-overview.md). +1. Replace the manifest in the new project's **\appPackage** folder with your converted manifest. + + > [!NOTE] + > If the conversion process produced any language string files, such as **fr-fr.json**, add these to the **\appPackage** folder. + +1. Replace the files in the **\src** folder of the new project with the source files from your old project. To maximize compatibility with the configuration files in the new project, we recommend that you divide your source files into subfolders based on the runtimes in which they normally are run. For example, have separate folders for the source files of function commands, the taskpane, autorun events, and Excel custom functions. +1. Edit the manifest to ensure that any URLs in it are compatible with the new structure of the project. +1. Inspect the configuration files in the new project to ensure that they are compatible with the organization of the project. + + > [!TIP] + > When the old project and the new both have a configuration file with the same name (such as **babel.config.json**), use a file comparison ("diff") tool to find the differences. For each difference, determine which file is correct for the new project and change the file in the new project as needed. + +1. The **webpack.config.js** is likely to need editing. It isn't possible to give universal rules for that file, but the following principles apply in most cases. + + - Ensure that URLs match the structure of the project. + - Ensure that there is an `entry` subproperty for each subfolder under the **\src** folder. + - Ensure that the `plugins` array also takes account of each subfolder under the **\src** folder. + - Ensure that the `extensions` and `rules` properties take account of the file types in your project that should be handled by loaders and bundled. + +1. Ensure that you can sideload the add-in in the new project. See [Verify that the add-in can be sideloaded](#verify-that-the-add-in-can-be-sideloaded). diff --git a/docs/develop/initialize-add-in.md b/docs/develop/initialize-add-in.md index 1756ff9c46..e321873f41 100644 --- a/docs/develop/initialize-add-in.md +++ b/docs/develop/initialize-add-in.md @@ -1,7 +1,7 @@ --- title: Initialize your Office Add-in description: Learn how to initialize your Office Add-in. -ms.date: 08/18/2023 +ms.date: 10/16/2025 ms.localizationpriority: medium --- @@ -87,6 +87,9 @@ However, there are exceptions to this practice. For example, suppose you want to Another exception would be if you want a progress indicator to appear in the task pane while the add-in is loading. In this scenario, your code should call the jQuery `ready` and use its callback to render the progress indicator. Then the `Office.onReady` callback can replace the progress indicator with the final UI. +> [!IMPORTANT] +> If the Office JavaScript API library files are blocked by network filters, firewalls, or browser extensions, `Office.onReady` will never resolve. + ## Initialize with Office.initialize An initialize event fires when the Office.js library is loaded and ready for user interaction. You can assign a handler to `Office.initialize` that implements your initialization logic. The following is an example that checks to see that the user's version of Excel supports all the APIs that the add-in might call. diff --git a/docs/develop/install-latest-office-version.md b/docs/develop/install-latest-office-version.md index bda3d273e8..b627f26dbd 100644 --- a/docs/develop/install-latest-office-version.md +++ b/docs/develop/install-latest-office-version.md @@ -1,7 +1,7 @@ --- title: Install the latest version of Office description: Information about how to opt in to getting the latest builds of Office. -ms.date: 05/05/2023 +ms.date: 09/24/2024 ms.localizationpriority: medium --- @@ -11,8 +11,8 @@ New developer features, including those still in preview, are delivered first to ## Opt in to getting the latest builds of Office -- If you're a Microsoft 365 Family, Personal, or University subscriber, see [Be a Microsoft 365 Insider](https://insider.microsoft365.com). -- If you're a Microsoft 365 Apps for business customer, see [Microsoft 365 Insider ​for Business](https://insider.microsoft365.com/business). +- If you're a Microsoft 365 Family, Personal, or University subscriber, see [Be a Microsoft 365 Insider](https://aka.ms/MSFT365InsiderHandbook). +- If you're a Microsoft 365 Apps for business customer, see [Microsoft 365 Insider ​for Business](/microsoft-365-apps/insider/). - If you're running Office on a Mac: - Start an Office application. - Select **Check for Updates** on the Help menu. @@ -25,18 +25,8 @@ New developer features, including those still in preview, are delivered first to 1. Create a new file named **configuration.xml** and add the following XML. ```xml - <!-- Office 365 client configuration file sample. To be used for Office 365 ProPlus apps, - Office 365 Business apps, Project Pro for Office 365 and Visio Pro for Office 365. - - For detailed information regarding configuration options visit: http://aka.ms/ODT. - To use the configuration file be sure to remove the comments - - The following sample allows you to download and install the 32 bit version of the Office 365 ProPlus apps - and Visio Pro for Office 365 directly from the Office CDN using the First Release Branch - settings --> - <Configuration> - <Add OfficeClientEdition="32" Branch="FirstReleaseCurrent"> + <Add OfficeClientEdition="32" Branch="CurrentPreview"> <Product ID="O365ProPlusRetail"> <Language ID="en-us" /> </Product> @@ -44,18 +34,12 @@ New developer features, including those still in preview, are delivered first to <Updates Enabled="TRUE" /> <Display Level="None" AcceptEULA="TRUE" /> - <Logging Level="Standard" Path="%temp%" /> - - <!-- <Updates Enabled="TRUE" Branch="Current" /> --> - - <!-- <Display Level="None" AcceptEULA="TRUE" /> --> - - <!-- <Property Name="AUTOACTIVATE" Value="1" /> --> - + </Configuration> ``` 1. Run the following command as an administrator. + ```command line setup.exe /configure configuration.xml ``` @@ -63,9 +47,9 @@ New developer features, including those still in preview, are delivered first to > [!NOTE] > The command might take a long time to run without indicating progress. -When the installation process finishes, you will have the latest Office applications installed. To verify that you have the latest build, go to **File** > **Account** from any Office application. Under Office Updates, you'll see the (Office Insiders) label above the version number. +When the installation process finishes, you'll have the latest Office applications installed. To verify that you have the latest build, go to **File** > **Account** from any Office application. Under the About section, you'll see the version and build number, along with Current Channel (Preview). The Microsoft 365 Insider section is displayed or hidden for business customers depending on their company's settings. -![Product information, including the version number, with the Office Insiders label.](../images/office-insiders-label.png) +![Product information, including the version number, build, and channel.](../images/microsoft-365-insider.png) ## Minimum Office builds for Office JavaScript API requirement sets diff --git a/docs/develop/itp-and-third-party-cookies.md b/docs/develop/itp-and-third-party-cookies.md index 6928922145..604228af62 100644 --- a/docs/develop/itp-and-third-party-cookies.md +++ b/docs/develop/itp-and-third-party-cookies.md @@ -1,22 +1,22 @@ --- title: Develop your Office Add-in to work with ITP when using third-party cookies description: How to work with ITP and Office Add-ins when using third-party cookies. -ms.date: 08/05/2024 +ms.date: 09/24/2025 ms.localizationpriority: medium --- # Develop your Office Add-in to work with ITP when using third-party cookies -If your Office Add-in requires third-party cookies, those cookies are blocked if the [Runtime](../testing/runtimes.md) that loaded your add-in uses Intelligent Tracking Prevention (ITP). You may be using third-party cookies to authenticate users, or for other scenarios, such as storing settings. +If your Office Add-in needs third-party cookies for authentication or storing settings, you might run into issues with Intelligent Tracking Prevention (ITP). When the [Runtime](../testing/runtimes.md) that loads your add-in uses ITP, these cookies get blocked. -If your Office Add-in and website must rely on third-party cookies, use the following steps to work with ITP. +If your Office Add-in and website must rely on third-party cookies, follow these steps to work with ITP. -1. Set up [OAuth 2.0 Authorization](https://tools.ietf.org/html/rfc6749) so that the authenticating domain (in your case, the third-party that expects cookies) forwards an authorization token to your website. Use the token to establish a first-party session with a server-set Secure and [HttpOnly cookie](https://developer.mozilla.org/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies). -1. Use the [Storage Access API](https://webkit.org/blog/8124/introducing-storage-access-api/) so that the third-party can request permission to get access to its first-party cookies. Current versions of Office on Mac and Office on the web both support this API. +1. **Set up [OAuth 2.0 Authorization](https://tools.ietf.org/html/rfc6749)** so that the authenticating domain (the third-party that expects cookies) forwards an authorization token to your website. Use the token to establish a first-party session with a server-set Secure and [HttpOnly cookie](https://developer.mozilla.org/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies). +1. **Use the [Storage Access API](https://webkit.org/blog/8124/introducing-storage-access-api/)** so that the third-party can request permission to access its first-party cookies. Current versions of Office on Mac and Office on the web both support this API. > [!NOTE] - > If you're using cookies for purposes other than authentication, consider using `localStorage` for your scenario. + > For non-authentication purposes, consider using `localStorage` instead of cookies. > - > However, note that starting in Version 115 of Chromium-based browsers, such as Chrome and Edge, [storage partitioning](https://developer.chrome.com/docs/privacy-sandbox/storage-partitioning/) is enabled to prevent specific side-channel cross-site tracking (see also [Microsoft Edge browser policies](/deployedge/microsoft-edge-policies#defaultthirdpartystoragepartitioningsetting)). This means that data stored by storage APIs, such as local storage, are only available to contexts with the same origin and the same top-level site. + > However, starting in Version 115 of Chromium-based browsers like Chrome and Edge, [storage partitioning](https://developer.chrome.com/docs/privacy-sandbox/storage-partitioning/) is enabled to prevent cross-site tracking (see also [Microsoft Edge browser policies](/deployedge/microsoft-edge-policies#defaultthirdpartystoragepartitioningsetting)). This means storage APIs like local storage are only available to contexts with the same origin and top-level site. The following code sample shows how to use the Storage Access API. @@ -49,11 +49,16 @@ if (document.hasStorageAccess) { ## About ITP and third-party cookies -Third-party cookies are cookies that are loaded in an iframe, where the domain is different from the top level frame. ITP could affect complex authentication scenarios, where a pop-up dialog is used to enter credentials and then the cookie access is needed by an add-in iframe to complete the authentication flow. ITP could also affect silent authentication scenarios, where you have previously used a pop-up dialog to authenticate, but subsequent use of the add-in tries to authenticate through a hidden iframe. +Third-party cookies are cookies loaded in an iframe where the domain differs from the top-level frame. ITP can affect: -When developing Office Add-ins on Mac, access to third-party cookies is blocked by the MacOS Big Sur SDK. This is because WKWebView ITP is enabled by default on the Safari browser, and WKWebView blocks all third-party cookies. Office on Mac version 16.44 or later is integrated with the MacOS Big Sur SDK. +- **Complex authentication scenarios** where a pop-up dialog handles credentials and the add-in iframe needs cookie access to complete authentication. +- **Silent authentication scenarios** where you've previously authenticated through a pop-up but subsequent attempts try to authenticate through a hidden iframe. -In the Safari browser, end users can toggle the **Prevent cross-site tracking** checkbox under **Preference** > **Privacy** to turn off ITP. However, ITP can't be turned off for the embedded WKWebView control. +### Platform-specific behavior + +**Office on Mac**: Access to third-party cookies is blocked by the macOS Big Sur SDK. WKWebView ITP is enabled by default in Safari, and WKWebView blocks all third-party cookies. Office on Mac Version 16.44 (20121301) or later is integrated with the macOS Big Sur SDK. + +**Safari browser**: End users can turn off ITP by toggling the **Prevent cross-site tracking** checkbox under **Preferences** > **Privacy**. Please note that ITP can't be disabled for the embedded WKWebView control in Office on Mac. [!INCLUDE [chrome-tracking-prevention](../includes/chrome-tracking-prevention.md)] diff --git a/docs/develop/json-manifest-overview.md b/docs/develop/json-manifest-overview.md index c6da151f41..53d584f54b 100644 --- a/docs/develop/json-manifest-overview.md +++ b/docs/develop/json-manifest-overview.md @@ -1,8 +1,8 @@ ---- +--- title: Compare the add-in only manifest with the unified manifest for Microsoft 365 description: Get a comparison of the add-in only manifest with the unified manifest for Microsoft 365. ms.topic: overview -ms.date: 09/09/2024 +ms.date: 09/02/2025 ms.localizationpriority: high --- @@ -10,8 +10,7 @@ ms.localizationpriority: high This article is intended to help readers who are familiar with the add-in only manifest understand the unified manifest by comparing the two. Readers should also see [Office Add-ins with the unified manifest for Microsoft 365](unified-manifest-overview.md). -> [!NOTE] -> The unified manifest currently only supports Outlook add-ins and only in Office linked to a Microsoft 365 subscription and installed on Windows, on a mobile device, or in Outlook on the web. We're working on extending support to Excel, PowerPoint, and Word, as well as to Outlook on Mac, and to perpetual versions of Office. +[!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] ## Schemas and general points @@ -35,7 +34,7 @@ This section describes the unified manifest for readers who are familiar with th } ``` -- There are many places in the add-in only manifest where an element with a plural name has children with the singular version of the same name. For example, the markup to configure a custom menu includes an **\<Items\>** element which can have multiple **\<Item\>** element children. The JSON equivalent of these plural elements is a property with an array as its value. The members of the array are *anonymous* objects, not properties named "item" or "item1", "item2", etc. The following is an example. +- There are many places in the add-in only manifest where an element with a plural name has children with the singular version of the same name. For example, the markup to configure a custom menu includes an `<Items>` element which can have multiple `<Item>` element children. The JSON equivalent of these plural elements is a property with an array as its value. The members of the array are *anonymous* objects, not properties named "item" or "item1", "item2", etc. The following is an example. ```json "items": [ @@ -50,9 +49,9 @@ This section describes the unified manifest for readers who are familiar with th ### Top-level structure -The root level of the unified manifest, which roughly corresponds to the **\<OfficeApp\>** element in the add-in only manifest, is an anonymous object. +The root level of the unified manifest, which roughly corresponds to the `<OfficeApp>` element in the add-in only manifest, is an anonymous object. -The children of **\<OfficeApp\>** are commonly divided into two notional categories. The **\<VersionOverrides\>** element is one category. The other consists of all the other children of **\<OfficeApp\>**, which are collectively referred to as the base manifest. So too, the unified manifest has a similar division. There is a top-level "extensions" property that roughly corresponds in its purposes and child properties to the **\<VersionOverrides\>** element. The unified manifest also has over 10 other top-level properties that collectively serve the same purposes as the base manifest of the add-in only manifest. These other properties can be thought of collectively as the base manifest of the unified manifest. +The children of `<OfficeApp>` are commonly divided into two notional categories. The `<VersionOverrides>` element is one category. The other consists of all the other children of `<OfficeApp>`, which are collectively referred to as the base manifest. So too, the unified manifest has a similar division. There is a top-level [`"extensions"`](/microsoft-365/extensibility/schema/root#extensions) property that roughly corresponds in its purposes and child properties to the `<VersionOverrides>` element. The unified manifest also has over 10 other top-level properties that collectively serve the same purposes as the base manifest of the add-in only manifest. These other properties can be thought of collectively as the base manifest of the unified manifest. ### Base manifest @@ -60,51 +59,52 @@ The base manifest properties specify characteristics of the add-in that *any* ty |JSON property|Purpose|XML elements|Comments| |:-----|:-----|:-----|:-----| -|"$schema"| Identifies the manifest schema. | attributes of **\<OfficeApp\>** and **\<VersionOverrides\>** |*None* | -|"id"| GUID of the add-in. | **\<Id\>**|*None* | -|"version"| Version of the add-in. | **\<Version\>** |*None* | -|"manifestVersion"| Version of the manifest schema. | attributes of **\<OfficeApp\>** |*None* | -|"name"| Public name of the add-in. | **\<DisplayName\>** |*None* | -|"description"| Public description of the add-in. | **\<Description\>** |*None* | -|"accentColor"|*None* |*None* | This property has no equivalent in the add-in only manifest and isn't used in the unified manifest. But it must be present. | -|"developer"| Identifies the developer of the add-in. | **\<ProviderName\>** |*None* | -|"localizationInfo"| Configures the default locale and other supported locales. | **\<DefaultLocale\>** and **\<Override\>** |*None* | -|"webApplicationInfo"| Identifies the add-in's web app as it is known in Azure Active Directory. | **\<WebApplicationInfo\>** | In the add-in only manifest, the **\<WebApplicationInfo\>** element is inside **\<VersionOverrides\>**, not the base manifest. | -|"authorization"| Identifies any Microsoft Graph permissions that the add-in needs. | **\<WebApplicationInfo\>** | In the add-in only manifest, the **\<WebApplicationInfo\>** element is inside **\<VersionOverrides\>**, not the base manifest. | +|"$schema"| Identifies the manifest schema. | attributes of `<OfficeApp>` and `<VersionOverrides>` |*None* | +|[`"id"`](/microsoft-365/extensibility/schema/root#id)| GUID of the add-in. | `<Id>`|*None* | +|[`"version"`](/microsoft-365/extensibility/schema/root#version)| Version of the add-in. | `<Version>` |*None* | +|[`"manifestVersion"`](/microsoft-365/extensibility/schema/root#manifestversion)| Version of the manifest schema. | attributes of `<OfficeApp>` |*None* | +|[`"name"`](/microsoft-365/extensibility/schema/root#name)| Public name of the add-in. | `<DisplayName>` |*None* | +|[`"description"`](/microsoft-365/extensibility/schema/root#description)| Public description of the add-in. | `<Description>` |*None* | +|[`"accentColor"`](/microsoft-365/extensibility/schema/root#accentcolor)|*None* |*None* | This property has no equivalent in the add-in only manifest and isn't used in the unified manifest. But it must be present. | +|[`"developer"`](/microsoft-365/extensibility/schema/root#developer)| Identifies the developer of the add-in. | `<ProviderName>` |*None* | +|[`"localizationInfo"`](/microsoft-365/extensibility/schema/root#localizationinfo)| Configures the default locale and other supported locales. | `<DefaultLocale>` and `<Override>` |*None* | +|[`"webApplicationInfo"`](/microsoft-365/extensibility/schema/root#webApplicationInfo-property)| Identifies the add-in's web app as it is known in Microsoft Entra ID. | `<WebApplicationInfo>` | In the add-in only manifest, the `<WebApplicationInfo>` element is inside `<VersionOverrides>`, not the base manifest. | +|[`"authorization"`](/microsoft-365/extensibility/schema/root#authorization)| Identifies any Microsoft Graph permissions that the add-in needs. | `<WebApplicationInfo>` | In the add-in only manifest, the `<WebApplicationInfo>` element is inside `<VersionOverrides>`, not the base manifest. | -The **\<Hosts\>**, **\<Requirements\>**, and **\<ExtendedOverrides\>** elements are part of the base manifest in the add-in only manifest. But concepts and purposes associated with these elements are configured inside the "extensions" property of the unified manifest. +The `<Hosts>`, `<Requirements>`, and `<ExtendedOverrides>` elements are part of the base manifest in the add-in only manifest. But concepts and purposes associated with these elements are configured inside the `"extensions"` property of the unified manifest. -### "extensions" property +### `"extensions"` property -The "extensions" property in the unified manifest primarily represents characteristics of the add-in that wouldn't be relevant to other kinds of Microsoft 365 extensions. For example, the Office applications that the add-in extends (such as, Excel, PowerPoint, Word, and Outlook) are specified inside the "extensions" property, as are customizations of the Office application ribbon. The configuration purposes of the "extensions" property closely match those of the **\<VersionOverrides\>** element in the add-in only manifest. +The `"extensions"` property in the unified manifest primarily represents characteristics of the add-in that wouldn't be relevant to other kinds of Microsoft 365 extensions. For example, the Office applications that the add-in extends (such as, Excel, PowerPoint, Word, and Outlook) are specified inside the `"extensions"` property, as are customizations of the Office application ribbon. The configuration purposes of the `"extensions"` property closely match those of the `<VersionOverrides>` element in the add-in only manifest. > [!NOTE] -> The **\<VersionOverrides\>** section of the add-in only manifest has a "double jump" system for many string resources. Strings, including URLs, are specified and assigned an ID in the **\<Resources\>** child of **\<VersionOverrides\>**. Elements that require a string have a `resid` attribute that matches the ID of a string in the **\<Resources\>** element. The "extensions" property of the unified manifest simplifies things by defining strings directly as property values. There is nothing in the unified manifest that is equivalent to the **\<Resources\>** element. +> The `<VersionOverrides>` section of the add-in only manifest has a "double jump" system for many string resources. Strings, including URLs, are specified and assigned an ID in the `<Resources>` child of `<VersionOverrides>`. Elements that require a string have a `resid` attribute that matches the ID of a string in the `<Resources>` element. The `"extensions"` property of the unified manifest simplifies things by defining strings directly as property values. There is nothing in the unified manifest that is equivalent to the `<Resources>` element. -The following table shows a mapping of *some* high-level child properties of the "extensions" property in the unified manifest to XML elements in the current manifest. Dot notation is used to reference child properties. +The following table shows a mapping of *some* high-level child properties of the `"extensions"` property in the unified manifest to XML elements in the current manifest. Dot notation is used to reference child properties. > [!NOTE] -> This table contains only some selected representative descendant properties of "extensions". *It isn't an exhaustive list of all child properties of "extensions".* For the full reference of the unified manifest, see [Unified manifest for Microsoft 365](/microsoftteams/platform/resources/schema/manifest-schema). For the manifest reference that includes all the latest preview features, see [Public developer preview for the unified manifest for Microsoft 365](/microsoftteams/platform/resources/schema/manifest-schema-dev-preview). +> This table contains only some selected representative descendant properties of `"extensions"`. *It isn't an exhaustive list of all child properties of `"extensions"`.* For the full reference of the unified manifest, see [Microsoft 365 app manifest schema reference](/microsoft-365/extensibility/schema). |JSON property|Purpose|XML elements|Comments| |:-----|:-----|:-----|:-----| -| "requirements.capabilities" | Identifies the [requirement sets](office-versions-and-requirement-sets.md#office-requirement-sets-availability) that the add-in needs to be installable. that the add-in needs to be installable. | **\<Requirements\>** and **\<Sets\>** |*None* | -| "requirements.scopes" | Identifies the Office applications in which the add-in can be installed. | **\<Hosts\>** |*None* | -| "ribbons" | The ribbons that the add-in customizes. | **\<Hosts\>**, **ExtensionPoints**, and various **\*FormFactor** elements | The "ribbons" property is an array of anonymous objects that each merge the purposes of the these three elements. See ["ribbons" table](#ribbons-table).| -| "alternatives" | Specifies backwards compatibility with an equivalent COM add-in, XLL, or both. | **\<EquivalentAddins\>** | See the [EquivalentAddins - See also](/javascript/api/manifest/equivalentaddins#see-also) for background information. | -| "runtimes" | Configures the [embedded runtimes](../testing/runtimes.md) that the add-in uses, including various kinds of add-ins that have little or no UI, such as custom function-only add-ins and [function commands](../design/add-in-commands.md#types-of-add-in-commands). | **\<Runtimes\>**. **\<FunctionFile\>**, and **\<ExtensionPoint\>** (of type CustomFunctions) |*None* | -| "autoRunEvents" | Configures an event handler for a specified event. | **\<ExtensionPoint\>** (of type LaunchEvent) |*None* | +| [`"requirements.capabilities"`](/microsoft-365/extensibility/schema/requirements-extension-element-capabilities) | Identifies the [requirement sets](office-versions-and-requirement-sets.md#office-requirement-sets-availability) that the add-in needs to be installable. that the add-in needs to be installable. | `<Requirements>` and `<Sets>` |*None* | +| [`"requirements.scopes"`](/microsoft-365/extensibility/schema/requirements-extension-element#scopes) | Identifies the Office applications in which the add-in can be installed. | `<Hosts>` |*None* | +| [`"ribbons"`](/microsoft-365/extensibility/schema/element-extensions#ribbons) | The ribbons that the add-in customizes. | `<Hosts>`, **ExtensionPoints**, and various **\*FormFactor** elements | The `"ribbons"` property is an array of anonymous objects that each merge the purposes of the these three elements. See [`"ribbons"` table](#ribbons-table).| +| [`"alternates"`](/microsoft-365/extensibility/schema/element-extensions#alternates) | Specifies backwards compatibility with an equivalent COM add-in, XLL, or both. | `<EquivalentAddins>` | See the [EquivalentAddins - See also](/javascript/api/manifest/equivalentaddins#see-also) for background information. | +| [`"runtimes"`](/microsoft-365/extensibility/schema/element-extensions#runtimes) | Configures the [embedded runtimes](../testing/runtimes.md) that the add-in uses, including various kinds of add-ins that have little or no UI, such as custom function-only add-ins and [function commands](../design/add-in-commands.md#types-of-add-in-commands). | `<Runtimes>`. `<FunctionFile>`, and `<ExtensionPoint>` (of type CustomFunctions) |*None.* | +| [`"autoRunEvents"`](/microsoft-365/extensibility/schema/element-extensions#autorunevents) | Configures an event handler for a specified event. | `<ExtensionPoint>` (of type LaunchEvent) |*None.* | +| [`"keyboardShortcuts"`](/microsoft-365/extensibility/schema/element-extensions#keyboardshortcuts) (developer preview) | Defines custom keyboard shortcuts or key combinations to run specific actions. | `<ExtendedOverrides>` | *None.* | -#### "ribbons" table +#### `"ribbons"` table -The following table maps the child properties of the anonymous child objects in the "ribbons" array onto XML elements in the current manifest. +The following table maps the child properties of the anonymous child objects in the `"ribbons"` array onto XML elements in the current manifest. |JSON property|Purpose|XML elements|Comments| |:-----|:-----|:-----|:-----| -| "contexts" | Specifies the command surfaces that the add-in customizes. | Various **\*CommandSurface** elements, such as **PrimaryCommandSurface** and **MessageReadCommandSurface** |*None.* | -| "tabs" | Configures custom ribbon tabs. | **\<CustomTab\>** | The names and hierarchy of the descendant properties of "tabs" closely match the descendants of **\<CustomTab\>**. | -| "fixedControls" (developer preview) | Configures and adds the button of an [integrated spam-reporting](../outlook/spam-reporting.md) add-in to the Outlook ribbon. | **\<Control\>** child element of **\<ReportPhishingCustomization\>** | *None.* | -| "spamPreProcessingDialog" (developer preview) | Configures the preprocessing dialog shown after the button of a spam-reporting add-in is selected from the Outlook ribbon. | **\<PreProcessingDialog\>** child element of **\<ReportPhishingCustomization\>** | *None.* | +| `"contexts"` | Specifies the command surfaces that the add-in customizes. | Various **\*CommandSurface** elements, such as **PrimaryCommandSurface** and **MessageReadCommandSurface** |*None.* | +| `"tabs"` | Configures custom ribbon tabs. | `<CustomTab>` | The names and hierarchy of the descendant properties of `"tabs"` closely match the descendants of `<CustomTab>`. | +| `"fixedControls"` | Configures and adds the button of an [integrated spam-reporting](../outlook/spam-reporting.md) add-in to the Outlook ribbon. | `<Control>` child element of `<ReportPhishingCustomization>` | *None.* | +| `"spamPreProcessingDialog"` | Configures the preprocessing dialog shown after the button of a spam-reporting add-in is selected from the Outlook ribbon. | `<PreProcessingDialog>` child element of `<ReportPhishingCustomization>` | *None.* | For a full sample unified manifest, see [Sample unified manifest](unified-manifest-overview.md#sample-unified-manifest). diff --git a/docs/develop/loading-the-dom-and-runtime-environment.md b/docs/develop/loading-the-dom-and-runtime-environment.md index 8239e1df1b..e2da4e726f 100644 --- a/docs/develop/loading-the-dom-and-runtime-environment.md +++ b/docs/develop/loading-the-dom-and-runtime-environment.md @@ -1,7 +1,7 @@ ---- +--- title: Loading the DOM and runtime environment description: Load the DOM and Office Add-ins runtime environment. -ms.date: 05/20/2023 +ms.date: 10/16/2025 ms.localizationpriority: medium --- @@ -20,7 +20,7 @@ The following events occur when a content or task pane add-in starts. 1. The user opens a document that already contains an add-in or inserts an add-in in the document. -2. The Office client application reads the add-in's manifest from AppSource, an app catalog on SharePoint, or the shared folder catalog it originates from. +2. The Office client application reads the add-in's manifest from Microsoft Marketplace, an app catalog on SharePoint, or the shared folder catalog it originates from. 3. The Office client application opens the add-in's HTML page in a webview control. @@ -30,6 +30,9 @@ The following events occur when a content or task pane add-in starts. 5. The Office client application loads the runtime environment, which downloads and caches the Office JavaScript API library files from the content distribution network (CDN) server, and then calls the add-in's event handler for the [initialize](/javascript/api/office#Office_initialize_reason_) event of the [Office](/javascript/api/office) object, if a handler has been assigned to it. At this time it also checks to see if any callbacks (or chained `then()` method) have been passed (or chained) to the `Office.onReady` handler. For more information about the distinction between `Office.initialize` and `Office.onReady`, see [Initialize your add-in](initialize-add-in.md). + > [!IMPORTANT] + > If the Office JavaScript API library files are blocked by network filters, firewalls, or browser extensions, `Office.onReady` will never resolve. + 6. When the DOM and HTML body finish loading and the add-in finishes initializing, the main function of the add-in can proceed. ## Startup of an Outlook add-in diff --git a/docs/develop/localization.md b/docs/develop/localization.md index 602bab7516..2a466a5f56 100644 --- a/docs/develop/localization.md +++ b/docs/develop/localization.md @@ -1,7 +1,7 @@ ---- +--- title: Localization for Office Add-ins description: Use the Office JavaScript API to determine a locale and display strings based on the locale of the Office application, or to interpret or display data based on the locale of the data. -ms.date: 04/12/2024 +ms.date: 02/12/2025 ms.topic: how-to ms.localizationpriority: medium --- @@ -43,7 +43,40 @@ The Office JavaScript API provides two properties that support displaying or int ## Control localization from the manifest -The techniques for localizing with the manifest differ depending on whether you are using the add-in only manifest or the unified manifest for Microsoft 365, which is supported only on Outlook. +The techniques for localizing with the manifest differ depending on whether you're using the add-in only manifest or the unified app manifest for Microsoft 365. + +# [Unified app manifest for Microsoft 365](#tab/jsonmanifest) + +When using the unified app manifest for Microsoft 365, localize the public-facing strings in the manifest as described in [Localize strings in your app manifest](/microsoftteams/platform/concepts/build-and-test/apps-localization#localize-strings-in-your-app-manifest). The following is an example for an Outlook add-in. First is the [`"localizationInfo"`](/microsoft-365/extensibility/schema/root#localizationinfo) object in the manifest. Below that is the fr-fr.json file with the translated strings. The add-in has a task pane (with a French version of the home page), localized French icons, and a custom ribbon button that opens a video player in a dialog box. + +```json +"localizationInfo": { + "defaultLanguageTag": "en", + "additionalLanguages": [ + { + "languageTag": "fr-fr", + "file": "fr-fr.json" + } + ] +} +``` + +```json +{ + "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.16/MicrosoftTeams.Localization.schema.json", + "name.short": "Lecteur vidéo", + "name.full": "Lecteur vidéo pour Outlook", + "description.short": "Voir les vidéos YouTube dans Outlook via les mails.", + "description.full": "Visualisez les vidéos YouTube référencées dans vos courriers électronique directement depuis Outlook.", + "icons.color": "https://localhost:3000/assets/fr-fr/icon-128.png", + "extensions[0].audienceClaimUrl": "https://localhost:3000/fr-fr/taskpane.html", + "extensions[0].ribbons[0].tabs[0].groups[0].label": "Outils de médias", + "extensions[0].ribbons[0].tabs[0].groups[0].controls[0].icons[0].url": "https://localhost:3000/assets/fr-fr/player-icon.png", + "extensions[0].ribbons[0].tabs[0].groups[0].controls[0].label": "Ouvrir le lecteur vidéo", + "extensions[0].ribbons[0].tabs[0].groups[0].controls[0].supertip.description": "Cliquez pour ouvrir le lecteur vidéo.", + "extensions[0].ribbons[0].tabs[0].groups[0].controls[0].supertip.title": "Ouvrir le lecteur vidéo", +} +``` # [Add-in only manifest](#tab/xmlmanifest) @@ -51,8 +84,8 @@ Every Office Add-in specifies a [DefaultLocale] element and a locale in its mani |Element|Localization support| |:-----|:-----| -|[Description] |Users in each locale you specify can see a localized description for the add-in in AppSource (or private catalog).<br/>For Outlook add-ins, users can see the description in the Exchange Admin Center (EAC) after installation.| -|[DisplayName] |Users in each locale you specify can see a localized description for the add-in in AppSource (or private catalog).<br/>For Outlook add-ins, users can see the display name as a label for the Outlook add-in button and in the EAC after installation.<br/>For content and task pane add-ins, users can see the display name on the ribbon after installing the add-in.| +|[Description] |Users in each locale you specify can see a localized description for the add-in in Microsoft Marketplace (or private catalog).<br/>For Outlook add-ins, users can see the description in the Exchange Admin Center (EAC) after installation.| +|[DisplayName] |Users in each locale you specify can see a localized description for the add-in in Microsoft Marketplace (or private catalog).<br/>For Outlook add-ins, users can see the display name as a label for the Outlook add-in button and in the EAC after installation.<br/>For content and task pane add-ins, users can see the display name on the ribbon after installing the add-in.| |[IconUrl] |The icon image is optional. You can use the same override technique to specify a certain image for a specific culture. If you use and localize an icon, users in each locale you specify can see a localized icon image for the add-in.<br/>For Outlook add-ins, users can see the icon in the EAC after installing the add-in.<br/>For content and task pane add-ins, users can see the icon on the ribbon after installing the add-in.| |[HighResolutionIconUrl] **Important:** This element is available only when using add-in manifest version 1.1.|The high resolution icon image is optional but if it is specified, it must occur after the [IconUrl] element. When [HighResolutionIconUrl] is specified, and the add-in is installed on a device that supports high dpi resolution, the [HighResolutionIconUrl] value is used instead of the value for [IconUrl].<br/>You can use the same override technique to specify a certain image for a specific culture. If you use and localize an icon, users in each locale you specify can see a localized icon image for the add-in.<br/>For Outlook add-ins, users can see the icon in the EAC after installing the add-in.<br/>For content and task pane add-ins, users can see the icon on the ribbon after installing the add-in.| |[Resources] **Important:** This element is available only when using add-in manifest version 1.1. |Users in each locale you specify can see string and icon resources that you specifically create for the add-in for that locale. | @@ -140,141 +173,8 @@ For Outlook add-ins, the [SourceLocation] element also aligns to the form factor </PhoneSettings> ``` -# [Unified manifest](#tab/jsonmanifest) - -When using the unified manifest, localize the public-facing strings in the manifest as described in [Localize strings in your app manifest](/microsoftteams/platform/concepts/build-and-test/apps-localization#localize-strings-in-your-app-manifest). The following is an example for an Outlook add-in. First is the "localizationInfo" object in the manifest. Below that is the fr-fr.json file with the translated strings. The add-in has a task pane (with a French version of the home page), localized French icons, and a custom ribbon button that opens a video player in a dialog box. - -```json -"localizationInfo": { - "defaultLanguageTag": "en", - "additionalLanguages": [ - { - "languageTag": "fr-fr", - "file": "fr-fr.json" - } - ] -} -``` - -```json -{ - "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.16/MicrosoftTeams.Localization.schema.json", - "name.short": "Lecteur vidéo", - "name.full": "Lecteur vidéo pour Outlook", - "description.short": "Voir les vidéos YouTube dans Outlook via les mails.", - "description.full": "Visualisez les vidéos YouTube référencées dans vos courriers électronique directement depuis Outlook.", - "icons.color": "https://localhost:3000/assets/fr-fr/icon-128.png", - "extensions[0].audienceClaimUrl": "https://localhost:3000/fr-fr/taskpane.html", - "extensions[0].ribbons[0].tabs[0].groups[0].label": "Outils de médias", - "extensions[0].ribbons[0].tabs[0].groups[0].controls[0].icons[0].url": "https://localhost:3000/assets/fr-fr/player-icon.png", - "extensions[0].ribbons[0].tabs[0].groups[0].controls[0].label": "Ouvrir le lecteur vidéo", - "extensions[0].ribbons[0].tabs[0].groups[0].controls[0].supertip.description": "Cliquez pour ouvrir le lecteur vidéo.", - "extensions[0].ribbons[0].tabs[0].groups[0].controls[0].supertip.title": "Ouvrir le lecteur vidéo", -} -``` - --- -## Localize extended overrides - -> [!NOTE] -> This section isn't applicable if you're using the unified manifest. - -When the add-in is using an add-in only manifest, some extensibility features of Office Add-ins, such as keyboard shortcuts, are configured with JSON files that are hosted on your server, instead of with the add-in's XML-formatted manifest. This section assumes that you're familiar with extended overrides. See [Work with extended overrides of the manifest](extended-overrides.md) and [ExtendedOverrides](/javascript/api/manifest/extendedoverrides) element. - -Use the `ResourceUrl` attribute of the [ExtendedOverrides](/javascript/api/manifest/extendedoverrides) element to point Office to a file of localized resources. The following is an example. - -```xml - ... - </VersionOverrides> - <ExtendedOverrides Url="https://contoso.com/addin/extended-overrides.json" - ResourceUrl="https://contoso.com/addin/my-resources.json"> - </ExtendedOverrides> -</OfficeApp> -``` - -The extended overrides file then uses tokens instead of strings. The tokens name strings in the resource file. The following is an example that assigns a keyboard shortcut to a function (defined elsewhere) that displays the add-in's task pane. Note about this markup: - -- The example isn't quite valid. (We add a required additional property to it below.) -- The tokens must have the format **${resource.*name-of-resource*}**. - -```json -{ - "actions": [ - { - "id": "SHOWTASKPANE", - "type": "ExecuteFunction", - "name": "${resource.SHOWTASKPANE_action_name}" - } - ], - "shortcuts": [ - { - "action": "SHOWTASKPANE", - "key": { - "default": "${resource.SHOWTASKPANE_default_shortcut}" - } - } - ] -} -``` - -The resource file, which is also JSON-formatted, has a top-level `resources` property that is divided into subproperties by locale. For each locale, a string is assigned to each token that was used in the extended overrides file. The following is an example which has strings for `en-us` and `fr-fr`. In this example, the keyboard shortcut is the same in both locales, but that won't always be the case, especially when you are localizing for locales that have a different alphabet or writing system, and hence a different keyboard. - -```json -{ - "resources":{ - "en-us": { - "SHOWTASKPANE_default_shortcut": { - "value": "CTRL+SHIFT+A", - }, - "SHOWTASKPANE_action_name": { - "value": "Show task pane for add-in", - }, - }, - "fr-fr": { - "SHOWTASKPANE_default_shortcut": { - "value": "CTRL+SHIFT+A", - }, - "SHOWTASKPANE_action_name": { - "value": "Afficher le volet de tâche pour add-in", - } - } - } -} -``` - -There is no `default` property in the file that is a peer to the `en-us` and `fr-fr` sections. This is because the default strings, which are used when the locale of the Office host application doesn't match any of the *ll-cc* properties in the resources file, *must be defined in the extended overrides file itself*. Defining the default strings directly in the extended overrides file ensures that Office doesn't download the resource file when the locale of the Office application matches the default locale of the add-in (as specified in the manifest). The following is a corrected version of the preceding example of an extended overrides file that uses resource tokens. - -```json -{ - "actions": [ - { - "id": "SHOWTASKPANE", - "type": "ExecuteFunction", - "name": "${resource.SHOWTASKPANE_action_name}" - } - ], - "shortcuts": [ - { - "action": "SHOWTASKPANE", - "key": { - "default": "${resource.SHOWTASKPANE_default_shortcut}" - } - } - ], - "resources": { - "default": { - "SHOWTASKPANE_default_shortcut": { - "value": "CTRL+SHIFT+A", - }, - "SHOWTASKPANE_action_name": { - "value": "Show task pane for add-in", - } - } - } -} -``` - ## Match date/time format with client locale You can get the locale of the user interface of the Office client application by using the **[displayLanguage]** property. You can then display date and time values in a format consistent with the current locale of the Office application. One way to do that is to prepare a resource file that specifies the date/time display format to use for each locale that your Office Add-in supports. At run time, your add-in can use the resource file and match the appropriate date/time format with the locale obtained from the **[displayLanguage]** property. @@ -309,7 +209,7 @@ After you install the Language Accessory Pack, you can configure Office to use t You'll need to create a Visual Studio Office Add-in project. > [!NOTE] -> If you haven't installed Visual Studio, see the [Visual Studio IDE page](https://visualstudio.microsoft.com/vs/) for download instructions. During installation you'll need to select the Office/SharePoint development workload. If you have previously installed Visual Studio 2019 or later, [use the Visual Studio Installer](/visualstudio/install/modify-visual-studio/) to ensure that the Office/SharePoint development workload is installed. +> If you haven't installed Visual Studio, see the [Visual Studio IDE page](https://visualstudio.microsoft.com/vs/) for download instructions. During installation you'll need to select the Office/SharePoint development workload. If you've previously installed Visual Studio 2019 or later, [use the Visual Studio Installer](/visualstudio/install/modify-visual-studio/) to ensure that the Office/SharePoint development workload is installed. 1. Choose **Create a new project**. @@ -331,7 +231,7 @@ The text that you want to localize for another language appears in two areas. 1. In **Solution Explorer**, expand **WorldReadyAddIn**, **WorldReadyAddInManifest**, and then choose **WorldReadyAddIn.xml**. -1. In WorldReadyAddInManifest.xml, replace the [DisplayName] and [Description] elements with the following block of code. +1. In **WorldReadyAddInManifest.xml**, replace the [DisplayName] and [Description] elements with the following block of code. > [!NOTE] > You can replace the Spanish language localized strings used in this example for the [DisplayName] and [Description] elements with the localized strings for any other language. @@ -351,7 +251,7 @@ The text that you want to localize for another language appears in two areas. 1. In Visual Studio, in **Solution Explorer**, choose **Home.html**. -1. Replace the `<body>` element contents in Home.html with the following HTML, and save the file. +1. Replace the `<body>` element contents in **Home.html** with the following HTML, and save the file. ```html <body> @@ -383,44 +283,39 @@ To enable localized strings for the heading and paragraph, you place the strings #### Add the resource file to the add-in project -1. In **Solution Explorer** in Visual Studio, right-click (or select and hold) the **WorldReadyAddInWeb** project and choose **Add** > **New Item**. +1. In **Solution Explorer** in Visual Studio, right-click (or select and hold) the **WorldReadyAddInWeb** project, then choose **Add** > **New Item**. 1. In the **Add New Item** dialog box, choose **JavaScript File**. 1. Enter **UIStrings.js** as the file name and choose **Add**. -1. Add the following code to the UIStrings.js file, and save the file. +1. Add the following code to the **UIStrings.js** file, and save the file. ```js /* Store the locale-specific strings */ - const UIStrings = (function () - { + const UIStrings = (() => { "use strict"; const UIStrings = {}; // JSON object for English strings - UIStrings.EN = - { + UIStrings.EN = { "Greeting": "Welcome", "Introduction": "This is my localized add-in." }; // JSON object for Spanish strings - UIStrings.ES = - { + UIStrings.ES = { "Greeting": "Bienvenido", "Introduction": "Esta es mi aplicación localizada." }; - UIStrings.getLocaleStrings = function (locale) - { + UIStrings.getLocaleStrings = (locale) => { let text; // Get the resource strings that match the language. - switch (locale) - { + switch (locale) { case 'en-US': text = UIStrings.EN; break; @@ -439,11 +334,11 @@ To enable localized strings for the heading and paragraph, you place the strings })(); ``` -The UIStrings.js resource file creates an object, **UIStrings**, which contains the localized strings for your add-in UI. +The **UIStrings.js** resource file creates an object, **UIStrings**, which contains the localized strings for your add-in UI. #### Localize the text used for the add-in UI -To use the resource file in your add-in, you'll need to add a script tag for it on Home.html. When Home.html is loaded, UIStrings.js executes and the **UIStrings** object that you use to get the strings is available to your code. Add the following HTML in the head tag for Home.html to make **UIStrings** available to your code. +To use the resource file in your add-in, you'll need to add a script tag for it on **Home.html**. When **Home.html** is loaded, **UIStrings.js** executes and the **UIStrings** object that you use to get the strings is available to your code. Add the following HTML in the head tag for **Home.html** to make **UIStrings** available to your code. ```html <!-- Resource file for localized strings: --> @@ -458,7 +353,7 @@ If you want to change the localization for your add-in based on what language is After you know the language the application is using, you can use **UIStrings** to get the set of localized strings that matches the application language. -Replace the code in the Home.js file with the following code. The code shows how you can change the strings used in the UI elements on Home.html based on either the display language of the application or the editing language of the application. +Replace the code in the **Home.js** file with the following code. The code shows how you can change the strings used in the UI elements on **Home.html** based on either the display language of the application or the editing language of the application. > [!NOTE] > To switch between changing the localization of the add-in based on the language used for editing, uncomment the line of code `const myLanguage = Office.context.contentLanguage;` and comment out the line of code `const myLanguage = Office.context.displayLanguage;` @@ -468,33 +363,31 @@ Replace the code in the Home.js file with the following code. The code shows how /// <reference path="../UIStrings.js" /> -(function () { +(() => { "use strict"; // The initialize function must be run each time a new page is loaded. - Office.initialize = function (reason) - { - - $(document).ready(function () { + Office.onReady(() => { + $(document).ready(() => { // Get the language setting for editing document content. // To test this, uncomment the following line and then comment out the // line that uses Office.context.displayLanguage. // const myLanguage = Office.context.contentLanguage; - + // Get the language setting for UI display in the Office application. const myLanguage = Office.context.displayLanguage; let UIText; - + // Get the resource strings that match the language. // Use the UIStrings object from the UIStrings.js file // to get the JSON object with the correct localized strings. UIText = UIStrings.getLocaleStrings(myLanguage); - + // Set localized text for UI elements. $("#greeting").text(UIText.Greeting); $("#about").text(UIText.Introduction); }); - }; + }); })(); ``` @@ -504,15 +397,13 @@ To test your localized add-in, change the language used for display or editing i 1. In Word, choose **File** > **Options** > **Language**. The following figure shows the **Word Options** dialog box opened to the Language tab. - *Figure 2. Language options in the Word Options dialog box* - ![Word Options dialog.](../images/office15-app-how-to-localize-fig04.png) 2. Under **Choose Display Language**, select the language that you want for display, for example Spanish, and then choose the up arrow to move the Spanish language to the first position in the list. Alternatively, to change the language used for editing, under **Choose Editing Languages**, choose the language you want to use for editing, for example, Spanish, and then choose **Set as Default**. 3. Choose **OK** to confirm your selection, and then close Word. -4. Press **F5** in Visual Studio to run the sample add-in, or choose **Debug** > **Start Debugging** from the menu bar. +4. Press <kbd>F5</kbd> in Visual Studio to run the sample add-in, or choose **Debug** > **Start Debugging** from the menu bar. 5. In Word, choose **Home** > **Show Taskpane**. diff --git a/docs/develop/make-office-add-in-compatible-with-existing-com-add-in.md b/docs/develop/make-office-add-in-compatible-with-existing-com-add-in.md index d1f2d537f5..502179420f 100644 --- a/docs/develop/make-office-add-in-compatible-with-existing-com-add-in.md +++ b/docs/develop/make-office-add-in-compatible-with-existing-com-add-in.md @@ -1,60 +1,110 @@ ---- +--- title: Make your Office Add-in compatible with an existing COM add-in -description: Enable compatibility between your Office Add-in and equivalent COM add-in. -ms.date: 06/18/2024 +description: Enable compatibility between your Office Add-in and similar COM or VSTO add-in. +ms.date: 11/04/2025 ms.localizationpriority: medium --- -# Make your Office Add-in compatible with an existing COM add-in +# Make your Office Add-in compatible with an existing COM or VSTO add-in -If you have an existing COM add-in, you can build equivalent functionality in your Office Add-in, thereby enabling your solution to run on other platforms such as Office on the web or Mac. In some cases, your Office Add-in may not be able to provide all of the functionality that's available in the corresponding COM add-in. In these situations, your COM add-in may provide a better user experience on Windows than the corresponding Office Add-in can provide. +If you have an existing COM add-in or VSTO add-in, you can build nearly equivalent functionality in your Office Web Add-in, thereby enabling your solution to run on other platforms such as in Office on the web or on Mac. In this scenario, the two add-ins are called "equivalent" and you can use the manifest of the Office Web Add-in to control which add-in is available to users on Windows computers (or give users the choice). -[!INCLUDE [new-outlook-vsto-com-support](../includes/new-outlook-vsto-com-support.md)] +> [!NOTE] +> Because COM and VSTO add-ins can only be installed on Windows, this article refers to COM and VSTO add-ins collectively as "Windows-only" add-ins. + + As a general rule, add-ins should be treated as equivalent only when the following conditions are met, but there may be exceptional scenarios where add-ins are that don't meet these conditions can be treated as equivalent. + +- They're both created by the same developer, typically the entity specified in the [`"developer"`](/microsoft-365/extensibility/schema/root-developer) property of the unified manifest or the [ProviderName](/javascript/api/manifest/providername) element in the add-in only manifest. +- They both are designed to be installed on the same Office application or applications, and they address the same workload with mainly overlapping functionality. +- They have identical, or highly similar, public names, and user interfaces including control names and icons. -You can configure your Office Add-in so that when the equivalent COM add-in is already installed on a user's computer, Office on Windows runs the COM add-in instead of the Office Add-in. The COM add-in is called "equivalent" because Office will seamlessly transition between the COM add-in and the Office Add-in according to which one is installed on a user's computer. [!INCLUDE [Support note for equivalent add-ins feature](../includes/equivalent-add-in-support-note.md)] -## Specify an equivalent COM add-in +[!INCLUDE [new-outlook-vsto-com-support](../includes/new-outlook-vsto-com-support.md)] + +Because the Windows-only add-in and the Office Add-in may not have exactly the same features, there are three scenarios you need to consider. -### Obtain the ProgId of a COM add-in +- Your Office Add-in does not provide all of the functionality that's available in the corresponding Windows-only add-in. In this scenario, you should [configure the Office add-in to be hidden](#hide-the-office-add-in) on any Windows computer on which the Windows-only add-in is installed. +- Your Office Add-in provides more and better functionality than the corresponding Windows-only add-in. In this scenario, you should [configure the Office Add-in so that it detects the presence of the Windows-only add-in and hides it](#hide-the-windows-only-add-in). +- Neither add-in would be regarded as better than the other by all your users. In this scenario, you should configure the Office Add-in to [give each user on a Windows computer the choice of which add-in is hidden](#give-the-user-the-choice-of-which-add-in-to-use). -Before you can specify an equivalent COM add-in, you must first identify its `ProgId`. To obtain the `ProgId` of a COM add-in: +## Obtain the name of the Windows-only add-in -1. Open Windows Registry Editor on the computer where the COM add-in is installed. +Before you can configure the Office Add-in's manifest, you must first identify the name of the Windows-only add-in in the Windows Registry with these steps: + +1. Open Windows Registry Editor on any computer where the Windows-only add-in is installed. 1. Go to **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\\*<Office application\>*\Addins** or **HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\\*<Office application\>*\Addins**, where *\<Office application\>* is Excel, Outlook, PowerPoint, or Word. For example, **HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\Excel\Addins**. -1. Copy the name of the registry key associated with the COM add-in you need. Note that the names are case-sensitive. +1. Copy the name of the registry key associated with the Windows-only add-in you need. Note that the names are case-sensitive. + +## Hide the Office Add-in + +You can configure your Office Add-in so that when the equivalent Windows-only add-in is already installed on a user's computer, Office on Windows runs the Windows-only add-in instead of the Office Add-in. If the Windows-only add-in is ever uninstalled, Office will automatically activate the Office Add-in the next time the host Office application is started. If the Windows-only add-in is installed *after* the Office Add-in, then when the Office application is restarted, the Office Add-in will be hidden. For more information, see [Behavior for users when the Office Add-in is hidden](#behavior-for-users-when-the-office-add-in-is-hidden). ### Configure the manifest > [!IMPORTANT] > Applies to Excel, Outlook, PowerPoint, and Word. -To enable compatibility between your Office Add-in and COM add-in, identify the equivalent COM add-in in the [manifest](add-in-manifests.md) of your Office Add-in. Then, Office on Windows will use the COM add-in instead of the Office Add-in, if they're both installed. +To enable compatibility between your Office Add-in and the Windows-only add-in, identify the equivalent Windows-only add-in in the [manifest](add-in-manifests.md) of your Office Add-in using the name that you obtained in the section [Obtain the name of the Windows-only add-in](#obtain-the-name-of-the-windows-only-add-in). Then, Office on Windows will use the Windows-only add-in instead of the Office Add-in, if they're both installed. The configuration depends on the type of manifest that is being used. -The following example shows the portion of the manifest that specifies a COM add-in as an equivalent add-in. The value of the `ProgId` element identifies the COM add-in and the [EquivalentAddins](/javascript/api/manifest/equivalentaddins) element must be positioned immediately before the closing `VersionOverrides` tag. +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) + +The following example shows the portion of the manifest that specifies a Windows-only add-in as an equivalent add-in. The value of the [`"alternates.prefer.comAddin.progId"`](/microsoft-365/extensibility/schema/extension-alternate-versions-array-prefer-com-addin#progid) property identifies the Windows-only add-in. + +> [!NOTE] +> Although the property is called "comAddin", it actually refers to any Windows-only add-in, regardless of whether the add-in is COM or VSTO. Similarly, the term "progId" is usually associated with only COM add-ins, but in the manifest it refers to the name of the Windows-only add-in. + +```json +"extensions" [ + ... + "alternates" [ + { + "prefer": { + "comAddin": { + "progId": "ContosoAddin" + } + } + } + ] +] +``` + +> [!TIP] +> If you're unable to specify the `alternates.prefer` property in the manifest of your Outlook web add-in, you must configure Group Policy instead. This only applies to Outlook. For guidance, see [Configure the Group Policy setting for Outlook add-ins](#configure-the-group-policy-setting-for-outlook-add-ins). + +# [Add-in only manifest](#tab/xmlmanifest) + +The following example shows the portion of the manifest that specifies a Windows-only add-in as an equivalent add-in. The value of the `ProgId` element identifies the Windows-only add-in and the [EquivalentAddins](/javascript/api/manifest/equivalentaddins) element must be positioned immediately before the closing `VersionOverrides` tag. + +> [!NOTE] +> Although the term "ProgId" is usually associated with only COM add-ins, in the manifest it refers to the name of the Windows-only add-in, regardless of whether the add-in is COM or VSTO. + +> [!IMPORTANT] +> Use "COM" as the value of the `<Type>` element for both COM and VSTO add-ins. ```xml <VersionOverrides> ... <EquivalentAddins> <EquivalentAddin> - <ProgId>ContosoCOMAddin</ProgId> + <ProgId>ContosoAddin</ProgId> <Type>COM</Type> </EquivalentAddin> </EquivalentAddins> </VersionOverrides> ``` -> [!TIP] -> For information about COM add-in and XLL UDF compatibility, see [Make your custom functions compatible with XLL user-defined functions](../excel/make-custom-functions-compatible-with-xll-udf.md). Not applicable for Outlook. +--- -### Configure the Group Policy setting +> [!TIP] +> +> - For information about XLL UDF compatibility with an Excel add-in that contains custom functions, see [Make your custom functions compatible with XLL user-defined functions](../excel/make-custom-functions-compatible-with-xll-udf.md). +> - For Outlook only, an admin of a computer can specify an equivalent Windows-only add-in by using a Group Policy. For guidance, see [Configure the Group Policy setting for Outlook add-ins](#configure-the-group-policy-setting-for-outlook-add-ins). -> [!IMPORTANT] -> Applies to Outlook only. +### Configure the Group Policy setting for Outlook add-ins -To declare compatibility between your Outlook web add-in and COM add-in, identify the equivalent COM add-in in the **Deactivate Outlook web add-ins whose equivalent COM or VSTO add-in is installed** Group Policy setting. This must be configured on the user's machine. Then, classic Outlook on Windows will use the COM add-in instead of the web add-in, if they're both installed. +A user with administrator powers on their computer can configure a Windows-only add-in to be the equivalent of an *Outlook* add-in by using the **Deactivate Outlook web add-ins whose equivalent COM or VSTO add-in is installed** Group Policy setting on the computer. This can be achieved even when the manifest of the Outlook add-in doesn't have the equivalent add-in markup. Then, classic Outlook on Windows uses the Windows-only add-in instead of the Outlook add-in if they're both installed. The following are the steps to configure the policy. 1. Download the latest [Administrative Templates tool](https://www.microsoft.com/download/details.aspx?id=49030), paying attention to the tool's **Install Instructions**. 1. Open the Local Group Policy Editor (**gpedit.msc**). @@ -62,61 +112,233 @@ To declare compatibility between your Outlook web add-in and COM add-in, identif 1. Select the setting **Deactivate Outlook web add-ins whose equivalent COM or VSTO add-in is installed**. 1. Open the link to edit the policy setting. 1. In the dialog **Outlook web add-ins to deactivate**: - 1. Set **Value name** to the `Id` found in the web add-in's manifest. **Important**: Do *not* add curly braces `{}` around the entry. - 1. Set **Value** to the `ProgId` of the equivalent COM add-in. + 1. Set **Value name** to the ID of the Outlook add-in's manifest. In the add-in only manifest, use the value of the `<ID>` element. In the unified manifest, use the value of the `id` property in the root of the manifest. Do *not* add curly braces `{}` around the entry. + 1. Set **Value** to the name of the equivalent Windows-only add-in. See the section [Obtain the name of the Windows-only add-in](#obtain-the-name-of-the-windows-only-add-in). 1. Select **OK** to put the update into effect. ![The "Outlook web add-ins to deactivate" dialog.](../images/outlook-deactivate-gpo-dialog.png) -## Equivalent behavior for users +### Behavior for users when the Office Add-in is hidden -When an [equivalent COM add-in is specified](#specify-an-equivalent-com-add-in), Office on Windows will not display your Office Add-in's user interface (UI) if the equivalent COM add-in is installed. Office only hides the ribbon buttons of the Office Add-in and doesn't prevent installation. Therefore, your Office Add-in will still appear in the following locations within the UI. +When an equivalent Windows-only add-in is specified, Office on Windows won't display your Office Add-in's user interface (UI) if the equivalent Windows-only add-in is installed. But Office only hides the ribbon buttons of the Office Add-in and doesn't prevent installation. Therefore, your Office Add-in will still appear in the following locations within the UI. - Under **My add-ins**. - As an entry on the ribbon manager (Excel, Word, and PowerPoint only). > [!NOTE] -> Specifying an equivalent COM add-in in the manifest has no effect on other platforms, like Office on the web or on Mac. +> Specifying an equivalent Windows-only add-in in the manifest has no effect on other platforms, like Office on the web or on Mac. The following scenarios describe what happens depending on how the user acquires the Office Add-in. -### AppSource acquisition of an Office Add-in +#### Microsoft Marketplace acquisition of the Office Add-in -If a user acquires the Office Add-in from AppSource and the equivalent COM add-in is already installed, then Office will: +If a user acquires the Office Add-in from Microsoft Marketplace and the equivalent Windows-only add-in is already installed, then Office will: 1. Install the Office Add-in. 2. Hide the Office Add-in UI on the ribbon. -3. Display a call-out for the user that points out the COM add-in ribbon button. +3. Display a call-out for the user that points out the Windows-only add-in ribbon button. -### Centralized deployment of Office Add-in +#### Centralized deployment of the Office Add-in -If an admin deploys the Office Add-in to their tenant using centralized deployment, and the equivalent COM add-in is already installed, the user must restart Office before they'll see any changes. After Office restarts, it will: +If an admin deploys the Office Add-in to their tenant using centralized deployment, and the equivalent Windows-only add-in is already installed, the user must restart Office before they'll see any changes. After Office restarts, it will: 1. Install the Office Add-in. 2. Hide the Office Add-in UI on the ribbon. -3. Display a call-out for the user that points out the COM add-in ribbon button. +3. Display a call-out for the user that points out the Windows-only add-in ribbon button. -### Document shared with embedded Office Add-in +#### Document shared with the Office Add-in embedded -If a user has the COM add-in installed, and then gets a shared document with the embedded Office Add-in, then when they open the document, Office will: +If a user has the Windows-only add-in installed, and then gets a shared document with the embedded Office Add-in, then when they open the document, Office will: 1. Prompt the user to trust the Office Add-in. 2. If trusted, the Office Add-in will install. 3. Hide the Office Add-in UI on the ribbon. -## Other COM add-in behavior +### Other Windows-only add-in behavior + +#### Excel, PowerPoint, Word + +If a user uninstalls the equivalent Windows-only add-in, then Office on Windows restores the Office Add-in UI. + +After you specify an equivalent Windows-only add-in for your Office Add-in, Office stops processing updates for your Office Add-in. To acquire the latest updates for the Office Add-in, the user must first uninstall the Windows-only add-in. + +#### Outlook + +The Windows-only add-in must be connected when Outlook is started in order for the corresponding Outlook add-in to be disabled. + +If the Windows-only add-in is then disconnected during a subsequent Outlook session, the Outlook add-in will likely remain disabled until Outlook is restarted. + +## Hide the Windows-only add-in + +[!INCLUDE [Support limits on the equivalent add-ins feature](../includes/equivalent-add-ins-limitations.md)] + +### Configure the manifest + +The details to configure this feature depend on which type of manifest is being used by the Office Add-in. + +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) + +To disable the Windows-only add-in, take the following steps. + +1. If it doesn't already exist, create an [`"extensions.alternates.hide.windowsExtensions"`](/microsoft-365/extensibility/schema/extension-alternate-versions-array-hide-windows-extensions) property. +1. Add a child `effect` property to the `windowsExtensions` property and set its value to **disableWithNotification**. +1. Add a child [`"comAddin"`](/microsoft-365/extensibility/schema/extension-alternate-versions-array-hide-windows-extensions-com-addin) property to the `windowsExtensions` property. +1. Add a child `progIds` array property to the `comAddin` property. +1. Add the names of all the Windows-only add-ins that you want to hide to the `progIds` array. For information about how to obtain these names, see [Obtain the name of the Windows-only add-in](#obtain-the-name-of-the-windows-only-add-in). + +> [!NOTE] +> The string "com" is in the name `comAddin` for historical reasons. In the manifest, the property refers to either COM or VSTO add-ins. Similarly, the term "progIds" is usually associated with only COM add-ins, but names of VSTO add-ins can also be included in the `progIds` array. + +The following example shows how the JSON should look. + +```json +"extensions" [ + { + ... + "alternates": [ + { + "hide": { + "windowsExtensions": { + "effect": "disableWithNotification", + "comAddin": { + "progIds": [ + "ContosoAddin" + ] + } + } + } + } + ] + } +] +``` + +# [Add-in only manifest](#tab/xmlmanifest) + +To disable the Windows-only add-in, take the following steps. + +1. Create an [EquivalentAddins](/javascript/api/manifest/equivalentaddins) as the very last child of the **\<VersionOverrides/>** element. +1. Add an **\<EquivalentAddin\>** child for every Windows-only add-in that you want to hide. +1. For each **\<EquivalentAddin\>** element, add a **\<ProgId/>** and **\<Type/>** child, *in that order*. +1. Set the **\<ProgId/>** element to the name of a Windows-only add-in that you want to hide. For information about how to obtain these names, see [Obtain the name of the Windows-only add-in](#obtain-the-name-of-the-windows-only-add-in). +1. Set the **\<Type/>** element to "COM". + + > [!NOTE] + > The **\<Type\>** value is "COM" for historical reasons, but it refers to either a COM or a VSTO add-in. Similarly, the **\<ProgId\>** value can be either the progId of a COM add-in or the name of a VSTO add-in. + +1. Add an **\<Effect\>** element *as the very last* child of the **\<EquivalentAddins\>** element, and set its value to **DisableWithNotification**. + +The following is an example. + +```xml +<VersionOverrides> + ... + <EquivalentAddins> + <EquivalentAddin> + <ProgId>ContosoAddin</ProgId> + <Type>COM</Type> + </EquivalentAddin> + <Effect>DisableWithNotification</Effect> + </EquivalentAddins> +</VersionOverrides> +``` + +--- + +### Behavior for users when the Windows-only add-in is hidden + +When a Windows-only add-in is hidden, Office on Windows won't display its user interface (UI) if the equivalent Office Add-in is installed. A popup dialog notifies the user that this is happening. But Office only hides the Windows-only add-in and doesn't prevent installation. + +## Give the user the choice of which add-in to use + +[!INCLUDE [Support limits on the equivalent add-ins feature](../includes/equivalent-add-ins-limitations.md)] + +### Configure the manifest + +The details to configure this feature depend on which type of manifest is being used by the Office Add-in. + +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) + +To give the user a choice of which add-in to hide, take the following steps. + +1. If it doesn't already exist, create an [`"extensions.alternates.hide.windowsExtensions"`](/microsoft-365/extensibility/schema/extension-alternate-versions-array-hide-windows-extensions) property. +1. Add a child `effect` property to the `windowsExtensions` property and set its value to **userOptionToDisable**. +1. Add a child [`"comAddin"`](/microsoft-365/extensibility/schema/extension-alternate-versions-array-hide-windows-extensions-com-addin) property to the `windowsExtensions` property. +1. Add a child `progIds` array property to the `comAddin` property. +1. Add the names of all the equivalent Windows-only add-ins to the `progIds` array. For information about how to obtain these names, see [Obtain the name of the Windows-only add-in](#obtain-the-name-of-the-windows-only-add-in). + +> [!NOTE] +> The string "com" is in the name `comAddin` for historical reasons. In the manifest, the property refers to either COM or VSTO add-ins. Similarly, the term "progIds" is usually associated with only COM add-ins, but names of VSTO add-ins can also be included in the `progIds` array. + +The following example shows how the JSON should look. + +```json +"extensions" [ + { + ... + "alternates": [ + { + "hide": { + "windowsExtensions": { + "effect": "userOptionToDisable", + "comAddin": { + "progIds": [ + "ContosoAddin" + ] + } + } + } + } + ] + } +] +``` + +# [Add-in only manifest](#tab/xmlmanifest) + +To disable the Windows-only add-in, take the following steps. + +1. Create an [EquivalentAddins](/javascript/api/manifest/equivalentaddins) as the very last child of the **\<VersionOverrides/>** element. +1. Add an **\<EquivalentAddin\>** child for every Windows-only add-in that you want to hide. +1. For each **\<EquivalentAddin\>** element, add a **\<ProgId/>** and **\<Type/>** child, *in that order*. +1. Set the **\<ProgId/>** element to the name of a Windows-only add-in whose hidden/visible status you want the user to decide. For information about how to obtain these names, see [Obtain the name of the Windows-only add-in](#obtain-the-name-of-the-windows-only-add-in). +1. Set the **\<Type/>** element to "COM". + + > [!NOTE] + > The **\<Type\>** value is "COM" for historical reasons, but it refers to either a COM or a VSTO add-in. Similarly, the **\<ProgId\>** value can be either the progId of a COM add-in or the name of a VSTO add-in. + +1. Add an **\<Effect\>** element *as the very last* child of the **\<EquivalentAddins\>** element, and set its value to **UserOptionToDisable**. + +The following is an example. + +```xml +<VersionOverrides> + ... + <EquivalentAddins> + <EquivalentAddin> + <ProgId>ContosoAddin</ProgId> + <Type>COM</Type> + </EquivalentAddin> + <Effect>UserOptionToDisable</Effect> + </EquivalentAddins> +</VersionOverrides> +``` + +--- + +### Behavior for users when they have the choice of which add-in is hidden -### Excel, PowerPoint, Word +If you configure the manifest to give the user the choice, then the user sees a dialog similar to the following when they install the Office Add-in. The **Learn more** link in the dialog points to the following help page that provides information to help the user make the decision: [Resolve version conflicts for Office Add-ins](https://support.microsoft.com/office/1632ec51-82ed-4f8e-90b4-a246cbccccde). -If a user uninstalls the equivalent COM add-in, then Office on Windows restores the Office Add-in UI. +:::image type="content" source="../images/com-preference-prompt.png" alt-text="A dialog titled 'Contoso JS Add-in Installer'. The first paragraph says, 'Contoso JS Add-in has identified the following older versions of the add-in that may cause conflicts:'. Below this paragraph is a single bulleted paragraph that says 'COM Add-in name: Contoso'. Below this is a paragraph that says, 'Do you want to disable the older add-in versions? (If you choose No, you will still get the new version if you open Office on Mac or Office on the web.)'. Below this is a link labelled 'Learn more'. Below this are two buttons labelled Yes and No."::: -After you specify an equivalent COM add-in for your Office Add-in, Office stops processing updates for your Office Add-in. To acquire the latest updates for the Office Add-in, the user must first uninstall the COM add-in. +If the user chooses **Yes** and Office successfully disables and hides the Windows-only add-in, then a dialog similar to the following opens that advises the user to restart the Office application. -### Outlook +:::image type="content" source="../images/com-preference-disable-success.png" alt-text="A dialog titled 'The Older Version Add-in Disabled'. The first paragraph says, 'The older version of the add-in has been successfully disabled.' Below this, a paragraph says, 'To ensure the changes take effect, we recommend restarting this Office application. You can continue without restarting, but some updates may not be applied until the next launch.' Below this is an OK button."::: -The COM add-in must be connected when Outlook is started in order for the corresponding web add-in to be disabled. +If the user chooses **Yes** but Office can't disable the Windows-only add-in for any reason, then a dialog similar to the following opens that advises the user to manually disable the Windows-only add-in. -If the COM add-in is then disconnected during a subsequent Outlook session, the web add-in will likely remain disabled until Outlook is restarted. +:::image type="content" source="../images/com-preference-disable-failure.png" alt-text="A dialog titled 'Please Disable Add-in Manually'. The first paragraph says, 'The older version of the add-in could not be fully disabled. To complete the process, please manually disable the COM add-in in the Office application where it was installed.' Below this are instructions labelled 'Here's how'. The instructions read as follows: '1. Go to File, Options, Add-ins. 2. In the Manage dropdown at the bottom, choose the add-in type and click Go. 3. In the dialog, uncheck the add-in to disable it. 4. Restart the app to apply changes (optional but recommended).' Below this is an OK button."::: ## See also diff --git a/docs/develop/manifest-element-ordering.md b/docs/develop/manifest-element-ordering.md index c85ad5e700..8ff9558d07 100644 --- a/docs/develop/manifest-element-ordering.md +++ b/docs/develop/manifest-element-ordering.md @@ -1,7 +1,7 @@ ---- +--- title: How to find the proper order of manifest elements description: Learn how to find the correct order in which to place child elements in a parent element. -ms.date: 09/5/2024 +ms.date: 06/13/2025 ms.localizationpriority: medium --- @@ -11,12 +11,12 @@ The XML elements in the manifest of an Office Add-in must be under the proper pa The required ordering is specified in the XSD files in the [Schemas](/openspecs/office_file_formats/ms-owemxml/c6a06390-34b8-4b42-82eb-b28be12494a8) folder. The XSD files are categorized into subfolders for taskpane, content, and mail add-ins. -For example, in the **\<OfficeApp\>** element, the **\<Id\>**, **\<Version\>**, **\<ProviderName\>** must appear in that order. If an **\<AlternateId\>** element is added, it must be between the **\<Id\>** and **\<Version\>** element. Your manifest will not be valid and your add-in will not load, if any element is in the wrong order. +For example, in the `<OfficeApp>` element, the `<Id>`, `<Version>`, `<ProviderName>` must appear in that order. If an `<AlternateId>` element is added, it must be between the `<Id>` and `<Version>` element. Your manifest will not be valid and your add-in will not load, if any element is in the wrong order. > [!NOTE] > The [validator within office-addin-manifest](../testing/troubleshoot-manifest.md#validate-your-manifest-with-office-addin-manifest) uses the same error message when an element is out-of-order as it does when an element is under the wrong parent. The error says the child element is not a valid child of the parent element. If you get such an error but the reference documentation for the child element indicates that it *is* valid for the parent, then the problem is likely that the child has been placed in the wrong order. -The following sections show the manifest elements in the order in which they must appear. There are differences depending on whether the `type` attribute of the **\<OfficeApp\>** element is `TaskPaneApp`, `ContentApp`, or `MailApp`. To keep these sections from becoming too unwieldy, the highly complex **\<VersionOverrides\>** element is broken out into separate sections. +The following sections show the manifest elements in the order in which they must appear. There are differences depending on whether the `type` attribute of the `<OfficeApp>` element is `TaskPaneApp`, `ContentApp`, or `MailApp`. To keep these sections from becoming too unwieldy, the highly complex `<VersionOverrides>` element is broken out into separate sections. > [!Note] > Not all of the elements shown are mandatory. If the `minOccurs` value for a element is **0** in the [schema](/openspecs/office_file_formats/ms-owemxml/4e112d0a-c8ab-46a6-8a6c-2a1c1d1299e3), the element is optional. @@ -137,8 +137,8 @@ The following sections show the manifest elements in the order in which they mus <DefaultSettings> <SourceLocation> <Override> - <RequestedWidth> - <RequestedHeight> + <RequestedWidth> + <RequestedHeight> <Permissions> <AllowSnapshot> <VersionOverrides>* @@ -287,6 +287,7 @@ The following sections show the manifest elements in the order in which they mus <DisplayName> <FileName> <Type> + <Effect> ``` ## Mail add-in element ordering within VersionOverrides Ver. 1.0 @@ -503,6 +504,17 @@ The following sections show the manifest elements in the order in which they mus <Resource> <Scopes> <Scope> + <EquivalentAddins> + <EquivalentAddin> + <ProgId> + <DisplayName> + <FileName> + <Type> + <ConnectedServiceControls> + <ConnectedServiceControlsScopes> + <Scope> + <ExtendedPermissions> + <ExtendedPermission> ``` ## Content add-in element ordering within VersionOverrides diff --git a/docs/develop/office-javascript-api-object-model.md b/docs/develop/office-javascript-api-object-model.md index 18eae59f2a..943ab27294 100644 --- a/docs/develop/office-javascript-api-object-model.md +++ b/docs/develop/office-javascript-api-object-model.md @@ -125,7 +125,7 @@ The [CustomXmlParts](/javascript/api/office/office.customxmlparts) and [CustomXm **Applies to:** Task pane add-ins for Word and PowerPoint -The [Document.getFileAsync](/javascript/api/office/office.document#office-office-document-getfileasync-member(1)) method and members of the [File](/javascript/api/office/office.file) and [Slice](/javascript/api/office/office.slice) objects to provide functionality for getting entire Word and PowerPoint document files in slices (chunks) of up to 4 MB at a time. For more information, see [Get the whole document from an add-in for PowerPoint or Word](../word/get-the-whole-document-from-an-add-in-for-word.md). +The [Document.getFileAsync](/javascript/api/office/office.document#office-office-document-getfileasync-member(1)) method and members of the [File](/javascript/api/office/office.file) and [Slice](/javascript/api/office/office.slice) objects to provide functionality for getting entire Word and PowerPoint document files in slices (chunks) of up to 4 MB at a time. For more information, see [Get the whole document from an add-in for PowerPoint or Word](../develop/get-the-whole-document-from-an-add-in-for-powerpoint-or-word.md). ## Mailbox object diff --git a/docs/develop/office-versions-and-requirement-sets.md b/docs/develop/office-versions-and-requirement-sets.md index fde5e27eb3..f0697c46b7 100644 --- a/docs/develop/office-versions-and-requirement-sets.md +++ b/docs/develop/office-versions-and-requirement-sets.md @@ -1,7 +1,7 @@ --- title: Office versions and requirement sets description: Supported Office.js platforms using JavaScript API. -ms.date: 05/16/2024 +ms.date: 03/11/2025 ms.localizationpriority: high --- @@ -45,19 +45,7 @@ An add-in can only use APIs in requirement sets that are supported by the versio - [PowerPoint JavaScript API requirement sets](/javascript/api/requirement-sets/powerpoint/powerpoint-api-requirement-sets) (PowerPointApi) - [Word JavaScript API requirement sets](/javascript/api/requirement-sets/word/word-api-requirement-sets) (WordApi) -Some requirement sets contain APIs that can be used by several Office applications. For information about these requirement sets, refer to the following articles. - -- [Office common requirement sets](/javascript/api/requirement-sets/common/office-add-in-requirement-sets) -- [Add-in commands requirement sets](/javascript/api/requirement-sets/common/add-in-commands-requirement-sets) -- [Device Permission Service requirement sets](/javascript/api/requirement-sets/common/device-permission-service-requirement-sets) -- [Dialog API requirement sets](/javascript/api/requirement-sets/common/dialog-api-requirement-sets) -- [Dialog Origin requirement sets](/javascript/api/requirement-sets/common/dialog-origin-requirement-sets) -- [Identity API requirement sets](/javascript/api/requirement-sets/common/identity-api-requirement-sets) -- [Image Coercion requirement sets](/javascript/api/requirement-sets/common/image-coercion-requirement-sets) -- [Keyboard Shortcuts requirement sets](/javascript/api/requirement-sets/common/keyboard-shortcuts-requirement-sets) -- [Open Browser Window requirement sets](/javascript/api/requirement-sets/common/open-browser-window-api-requirement-sets) -- [Ribbon API requirement sets](/javascript/api/requirement-sets/common/ribbon-api-requirement-sets) -- [Shared Runtime requirement sets](/javascript/api/requirement-sets/common/shared-runtime-requirement-sets) +Some requirement sets contain APIs that can be used by several Office applications. For information about these requirement sets, see [Office Common API requirement sets](/javascript/api/requirement-sets/common/office-add-in-requirement-sets). The version number of a requirement set, such as the "1.1" in `ExcelApi 1.1`, is relative to the Office application. The version number of a given requirement set (e.g., `ExcelApi 1.1`) does not correspond to the version number of Office.js or to requirement sets for other Office applications (e.g., Word, Outlook, etc.). Requirement sets for the different Office applications are released at different rates. For example, `ExcelApi 1.5` was released before the `WordApi 1.3` requirement set. diff --git a/docs/develop/overview-authn-authz.md b/docs/develop/overview-authn-authz.md index d980d061d2..67c17e7c96 100644 --- a/docs/develop/overview-authn-authz.md +++ b/docs/develop/overview-authn-authz.md @@ -37,7 +37,7 @@ Before you begin implementing user authentication with SSO, be sure that you're ### Access your Web APIs through SSO -If your add-in has server-side APIs that require an authorized user, call the [getAccessToken](/javascript/api/office-runtime/officeruntime.auth#office-runtime-officeruntime-auth-getaccesstoken-member(1)) method to get an access token. The access token provides access to your own web server (configured through a [Microsoft Azure app registration](register-sso-add-in-aad-v2.md)). When you call APIs on your web server, you also pass the access token to authorize the user. +If your add-in has server-side APIs that require an authorized user, call the [getAccessToken](/javascript/api/office-runtime/officeruntime.auth#office-runtime-officeruntime-auth-getaccesstoken-member(1)) method to get an access token. The access token provides access to your own web server (configured through an [app registration in Microsoft Entra ID](register-sso-add-in-aad-v2.md)). When you call APIs on your web server, you also pass the access token to authorize the user. The following code shows how to construct an HTTPS GET request to the add-in's web server API to get some data. The code runs on the client side, such as in a task pane. It first gets the access token by calling `getAccessToken`. Then it constructs an AJAX call with the correct authorization header and URL for the server API. diff --git a/docs/develop/persisting-add-in-state-and-settings.md b/docs/develop/persisting-add-in-state-and-settings.md index d8f3dff6eb..47dfae58eb 100644 --- a/docs/develop/persisting-add-in-state-and-settings.md +++ b/docs/develop/persisting-add-in-state-and-settings.md @@ -1,7 +1,7 @@ --- title: Persist add-in state and settings description: Learn how to persist data in Office Web Add-in applications running in the stateless environment of a browser control. -ms.date: 08/07/2024 +ms.date: 10/16/2025 ms.localizationpriority: medium --- @@ -22,7 +22,21 @@ Some browsers or the user's browser settings may block browser-based storage tec ### Storage partitioning -As a best practice, any private data should be stored in partitioned `localStorage`. [Office.context.partitionKey](/javascript/api/office/office.context#office-office-context-partitionkey-member) provides a key for use with local storage. This ensures that data stored in local storage is only available in the same context. The following example shows how to use the partition key with `localStorage`. Note that the partition key is undefined in environments without partitioning, such as the browser controls for Windows applications. +As a best practice, any private data should be stored in partitioned `localStorage`. [Office.context.partitionKey](/javascript/api/office/office.context#office-office-context-partitionkey-member) provides a key for use with local storage. This ensures that data stored in local storage is only available in the same context. + +> [!NOTE] +> The partition key is undefined in environments without partitioning, such as the webview controls for Office on Windows. Where it is defined, the partition key is a hash of the following two domains. +> +> - The domain that the top-level browser window is at, such as `excel.cloud.microsoft` in the case of Excel on the web. +> - The domain of the add-in, such as `myAddin.contoso.com`. +> +> So, each of the following would be a different partition: +> +> - `excel.cloud.microsoft` + `myAddin.contoso.com` +> - `word.cloud.microsoft` + `myAddin.contoso.com` +> - `word.cloud.microsoft` + `myOtherAddin.contoso.com` + +The following example shows how to use the partition key with `localStorage`. ```js // Store the value "Hello" in local storage with the key "myKey1". @@ -280,4 +294,4 @@ function getReviewers() { - [Outlook add-ins](../outlook/outlook-add-ins-overview.md) - [Get and set add-in metadata for an Outlook add-in](../outlook/metadata-for-an-outlook-add-in.md) - [Get and set internet headers on a message in an Outlook add-in](../outlook/internet-headers.md) -- [Excel-Add-in-JavaScript-PersistCustomSettings](https://github.com/OfficeDev/Excel-Add-in-JavaScript-PersistCustomSettings) +- [Save custom settings in your Office Add-in](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/office-add-in-save-custom-settings) diff --git a/docs/develop/platform-specific-requirement-sets.md b/docs/develop/platform-specific-requirement-sets.md new file mode 100644 index 0000000000..ea958da64e --- /dev/null +++ b/docs/develop/platform-specific-requirement-sets.md @@ -0,0 +1,126 @@ +--- +title: Understanding platform-specific requirement sets +description: Understand and learn how to use platform-specific requirement sets. +ms.topic: how-to +ms.date: 10/27/2025 +ms.localizationpriority: medium +--- + +# Understanding platform-specific requirement sets + +The Office Add-ins platform allows you to build solutions that extend Office applications and interact with content in Office documents. Your solution can run in Office across several platforms, including Windows, Mac, iPad, and in a browser. We've provided requirement sets that help you declare which APIs and platforms your add-in supports. Requirement sets are named groups of API members which are usually supported on all available platforms. However, with platform-specific requirement sets, APIs are implemented and made available first in the target platforms. + +Each application that supports Office Add-ins has its usual set of available platforms. For a comprehensive listing, see [Office client application and platform availability for Office Add-ins](/javascript/api/requirement-sets). For the purpose of this discussion, we'll focus on Excel, Outlook, PowerPoint, and Word. + +Cross-platform requirement sets are available on Windows, Mac, and in a browser. Depending on the features being made available, a requirement set may also be supported on iPad or mobile platforms. + +However, platform-specific requirement sets provide support for a subset of the usual platforms. For example, online-only requirement sets provide APIs that are only available when the add-in runs in a web browser. Similarly, desktop-only requirement sets provide APIs that may only be available when the add-in runs in Windows and Mac. See the specific requirement set page for actual platform support. + +## Current platform-specific requirement sets + +At present, platform-specific requirement sets are available in Excel and Word. Excel and Word include both online-only and desktop-only requirement sets. For the full list, see [Special requirement sets](/javascript/api/overview#special-requirement-sets). + +Note that in Outlook, platform-specific behavior may be found in extension points. For example, [MobileOnlineMeetingCommandSurface](/javascript/api/manifest/extensionpoint#mobileonlinemeetingcommandsurface) and [MobileLogEventAppointmentAttendee](/javascript/api/manifest/extensionpoint#mobilelogeventappointmentattendee) are only available to add-ins running in Outlook on Android and on iOS. + +## Why platform-specific requirement sets? + +We're providing platform-specific requirement sets for a few reasons. + +1. **Feature availability.** Some features aren't implemented in the Office applications UI on a particular platform. As such, the API can only be made available on supported platforms. Having these types of APIs in a platform-specific requirement set means that developers can use those APIs in their add-ins. This is especially useful for cases where the feature may never be implemented in other platforms. +1. **Platform-specific add-ins.** Developers who have add-ins focused on a particular platform don't need to wait for those APIs to be implemented in other platforms. These developers are able to incorporate those APIs into their solutions and ship to their customers much sooner. +1. **Tailored experiences.** Customers can use an Office application differently depending on the platform for several reasons, like feature availability or comfort level, for example. Let's say that on the Windows version, a customer completes one set of tasks but on an iPad, they complete a different set of tasks. You can have your add-in provide a tailored experience based on your users' usual scenarios per platform. + +To help you decide if platform-specific requirement sets can work for you, consider the following. + +## API promotion to cross-platform requirement set + +When APIs in a platform-specific requirement set are supported cross-platform, they're added to the next requirement set targeted for release. Even after the new requirement is made generally available, those APIs *still remain* in the platform-specific requirement set. + +## How to use a platform-specific requirement set + +The following sections describe where you can specify your minimum requirement set. For more information about these options, see [Specify which Office versions and platforms can host your add-in](specify-office-hosts-and-api-requirements.md). + +### Manifest + +When you note a requirement set in the [Set element](/javascript/api/manifest/set) of your add-in manifest, you're indicating the minimum set of APIs that your add-in needs. Combined with supported Office host applications and other information, this determines whether or not your add-in activates in an Office client. + +When you declare a platform-specific requirement set, your add-in activates only when it's run in Office on that platform. For example, if you have the WordApiDesktop 1.1 requirement set in your manifest, your add-in will only activate in Word on Windows and on Mac. + +Keep in mind that in the case where the APIs become supported cross-platform, you'll need to update your add-in manifest to add a cross-platform requirement set and remove the platform-specific requirement set. If your add-in is available in Microsoft Marketplace, you'll need to resubmit it for validation. + +### Code + +Another option is to implement a runtime check in your code. This way, you can make new features available to your customers on those platforms. The runtime check also ensures that the platform-specific code doesn't run on unsupported platforms and cross-platform features continue to work for your customers. The following code is an example that checks for a specific requirement set. + +```javascript +if (Office.context.requirements.isSetSupported("WordApiDesktop", "1.1")) { + // Any API exclusive to this WordApiDesktop requirement set. +} +``` + +Whenever platform-specific APIs become available cross-platform, enable your customers on all supported platforms to use those features by implementing one of the following options. + +- Remove the runtime check. But note that customers on older Office clients, especially on Windows, may hit errors if their client doesn't support the new APIs yet. +- Update the runtime code to check for the cross-platform requirement set. + +A variation is to do a runtime check for a particular API. This means that the encapsulated code should run on any platforms that support that API. If the API was first released in a platform-specific requirement set then promoted to a cross-platform one, you shouldn't need to update your code unless you made assumptions about the supported platforms. The following code is an example. + +```javascript +if (Office.context.document.setSelectedDataAsync) +{ + // Run code that uses document.setSelectedDataAsync. +} +``` + +## Notify customers on Microsoft Marketplace + +If your add-in is in Microsoft Marketplace or the Office store, be sure to notify customers about any platform-specific behavior. + +**Details + support** > **Products supported** on your add-in's Microsoft Marketplace page should automatically show the appropriate supported platforms based on the requirements you declared in the manifest. + +However, if your add-in is supported cross-platform but you also implemented platform-specific behaviors, you should point out those feature differences in the **Overview** section on your add-in's Microsoft Marketplace page. + +## Exceptions + +The following are exceptions to the approach described. + +### Online-only requirement sets + +An online-only requirement set is a superset of the latest numbered requirement set. For each Office application with an online-only requirement set, `1.1` is the only version. It's invalid to specify an online-only requirement set in the [Set element](/javascript/api/manifest/set) of your add-in manifest. + +To check for APIs that are only supported in these requirement sets and to prevent your add-in from trying to run the code on unsupported platforms, add code similar to the following: + +```javascript +if (Office.context.requirements.isSetSupported("ExcelApiOnline", "1.1")) { + // Any API exclusive to the ExcelApiOnline requirement set. +} +``` + +```javascript +if (Office.context.requirements.isSetSupported("WordApiOnline", "1.1")) { + // Any API exclusive to the WordApiOnline requirement set. +} +``` + +When APIs in an online-only requirement set are supported cross-platform, they're added to the next released requirement set. After the new requirement set is made generally available, those APIs are *removed* from the online-only requirement set. + +Follow the guidance in the earlier [Code](#code) section to adjust your add-in implementation accordingly. + +### Desktop-only HiddenDocument requirement sets in Word + +It's important to note that while the HiddenDocument requirement sets in Word are desktop-only, it's invalid to specify a HiddenDocument requirement set in the [Set element](/javascript/api/manifest/set) of your add-in manifest. + +To check for APIs that are only supported in these requirement sets and to prevent your add-in from trying to run the code on unsupported platforms, add code similar to the following: + +```javascript +if (Office.context.requirements.isSetSupported("WordApiHiddenDocument", "1.5")) { + // Any API exclusive to this WordApiHiddenDocument requirement set. +} +``` + +## See also + +- [Understanding the Office JavaScript API](understanding-the-javascript-api-for-office.md) +- [Office versions and requirement sets](office-versions-and-requirement-sets.md) +- [Specify Office applications and API requirements](specify-office-hosts-and-api-requirements.md) +- [Office client application and platform availability for Office Add-ins](/javascript/api/requirement-sets) diff --git a/docs/develop/referencing-the-javascript-api-for-office-library-from-its-cdn.md b/docs/develop/referencing-the-javascript-api-for-office-library-from-its-cdn.md index 2d03f86c99..a6a88570fc 100644 --- a/docs/develop/referencing-the-javascript-api-for-office-library-from-its-cdn.md +++ b/docs/develop/referencing-the-javascript-api-for-office-library-from-its-cdn.md @@ -1,7 +1,7 @@ ---- +--- title: Referencing the Office JavaScript API library description: Learn how to reference the Office JavaScript API library and type definitions in your add-in. -ms.date: 05/03/2023 +ms.date: 01/14/2025 ms.localizationpriority: medium --- @@ -21,11 +21,36 @@ This will download and cache the Office JavaScript API files the first time your > [!IMPORTANT] > You must reference the Office JavaScript API from inside the `<head>` section of the page to ensure that the API is fully initialized prior to any body elements. +## Office.js-specific web API behavior + +Office.js replaces the default [Window.history](https://developer.mozilla.org/docs/Web/API/History) methods of `replaceState` and `pushState` with `null`. This is done to [support older Microsoft webviews and Office versions](support-ie-11.md). If your add-in relies on these methods and doesn't need to run on Office versions that use the Internet Explorer 11 browser control, replace the Office.js library reference with the following workaround. + +```HTML +<script type="text/javascript"> + // Cache the history method values. + window._historyCache = { + replaceState: window.history.replaceState, + pushState: window.history.pushState + }; +</script> + +<script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script> + +<script type="text/javascript"> + // Restore the history method values after loading Office.js + window.history.replaceState = window._historyCache.replaceState; + window.history.pushState = window._historyCache.pushState; +</script> + +``` + +Thank you to [@stepper and the Stack Overflow community](https://stackoverflow.com/questions/42642863/office-js-nullifies-browser-history-functions-breaking-history-usage) for suggesting and verifying this workaround. + ## API versioning and backward compatibility In the previous HTML snippet, the `/1/` in front of `office.js` in the CDN URL specifies the latest incremental release within version 1 of Office.js. Because the Office JavaScript API maintains backward compatibility, the latest release will continue to support API members that were introduced earlier in version 1. -If you plan to publish your Office Add-in from AppSource, you must use this CDN reference. Local references are only appropriate for internal, development, and debugging scenarios. +If you plan to publish your Office Add-in from Microsoft Marketplace, you must use this CDN reference. Local references are only appropriate for internal, development, and debugging scenarios. > [!NOTE] > To use preview APIs, reference the preview version of the Office JavaScript API library on the CDN: `https://appsforoffice.microsoft.com/lib/beta/hosted/office.js`. diff --git a/docs/develop/register-sso-add-in-aad-v2.md b/docs/develop/register-sso-add-in-aad-v2.md index 14159dae89..a92ba882c2 100644 --- a/docs/develop/register-sso-add-in-aad-v2.md +++ b/docs/develop/register-sso-add-in-aad-v2.md @@ -1,4 +1,4 @@ ---- +--- title: Register an Office Add-in that uses SSO with the Microsoft identity platform description: Learn how to register an Office Add-in with the Microsoft identity platform to use SSO with Word, Excel, PowerPoint, and Outlook. ms.date: 04/18/2023 @@ -15,7 +15,7 @@ The following table itemizes the information that you need to carry out this pro |---------|---------|---------| |A human readable name for the add-in. (Uniqueness recommended, but not required.)|`Contoso Marketing Excel Add-in (Prod)`| `<add-in-name>` | |An application ID which Azure generates for you as part of the registration process.|`c6c1f32b-5e55-4997-881a-753cc1d563b7`|`<app-id>`| -|The fully qualified domain name (except for protocol) of the add-in. *You must use a domain that you own.* For this reason, you cannot use certain well-known domains such as `azurewebsites.net` or `cloudapp.net`. The domain must be the same, including any subdomains, as is used in the URLs in the **\<Resources\>** section of the add-in's manifest.|`localhost:6789`, `addins.contoso.com`|`<fully-qualified-domain-name>`| +|The fully qualified domain name (except for protocol) of the add-in. *You must use a domain that you own.* For this reason, you cannot use certain well-known domains such as `azurewebsites.net` or `cloudapp.net`. The domain must be the same, including any subdomains, as is used in the URLs in the `<Resources>` section of the add-in's manifest.|`localhost:6789`, `addins.contoso.com`|`<fully-qualified-domain-name>`| |The permissions to the Microsoft identity platform and Microsoft Graph that your add-in needs. (`profile` is always required.)|`profile`, `Files.Read.All`|N/A| > [!CAUTION] diff --git a/docs/develop/requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md b/docs/develop/requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md index 8265c30b90..7985056dbd 100644 --- a/docs/develop/requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md +++ b/docs/develop/requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md @@ -1,42 +1,60 @@ --- title: Requesting permissions for API use in add-ins -description: Learn about different permission levels to declare in the manifest of a content or task pane add-in to specify the level of JavaScript API access. -ms.date: 05/18/2023 +description: Learn about different permission levels to declare in the manifest of an add-in to specify the level of JavaScript API access. +ms.date: 06/17/2025 ms.localizationpriority: medium --- # Requesting permissions for API use in add-ins -This article describes the different permission levels that you can declare in your content or task pane add-in's manifest to specify the level of JavaScript API access your add-in requires for its features. +This article describes the different permission levels that you declare in your add-in's manifest to specify the level of JavaScript API access your add-in requires for its features. -> [!NOTE] -> To learn about permission levels for mail (Outlook) add-ins, see [Outlook permissions model](../outlook/privacy-and-security.md#permissions-model). +> [!IMPORTANT] +> This article applies to only non-Outlook add-ins. To learn about permission levels for Outlook add-ins, see [Understanding Outlook add-in permissions](../outlook/understanding-outlook-add-in-permissions.md). ## Permissions model -A five-level JavaScript API access-permissions model provides the basis for privacy and security for users of your content and task pane add-ins. Figure 1 shows the five levels of API permissions you can declare in your add-in's manifest. +A five-level JavaScript API access-permissions model provides the basis for privacy and security for users of your add-ins. The following figure shows the five levels of API permissions you can declare in your add-in's manifest. -*Figure 1. The five-level permission model for content and task pane add-ins* +![Levels of permissions for add-ins.](../images/office15-app-sdk-task-pane-app-permission.png) -![Levels of permissions for task pane apps.](../images/office15-app-sdk-task-pane-app-permission.png) +These permissions specify the subset of the API that the add-in [runtime](../testing/runtimes.md) allows your add-in to use when a user inserts, and then activates (trusts) your add-in. To declare the permission level your add-in requires, specify one of the permission values in the manifest. The markup varies depending on the type of manifest. -These permissions specify the subset of the API that the add-in [runtime](../testing/runtimes.md) will allow your content or task pane add-in to use when a user inserts, and then activates (trusts) your add-in. To declare the permission level your content or task pane add-in requires, specify one of the permission text values in the [Permissions](/javascript/api/manifest/permissions) element of your add-in's manifest. The following example requests the **WriteDocument** permission, which will allow only methods that can write to (but not read) the document. +- **Unified manifest for Microsoft 365**: Use the [`"authorization.permissions.resourceSpecific"`](/microsoft-365/extensibility/schema/root-authorization-permissions#resourcespecific) property. The following example requests the **write document** permission, which allows only methods that can write to (but not read) the document. -```XML -<Permissions>WriteDocument</Permissions> -``` + ```json + "authorization": { + "permissions": { + "resourceSpecific": [ + ... + { + "name": "Document.Write.User", + "type": "Delegated" + }, + ] + } + }, + ``` -As a best practice, you should request permissions based on the principle of _least privilege_. That is, you should request permission to access only the minimum subset of the API that your add-in requires to function correctly. For example, if your add-in needs only to read data in a user's document for its features, you should request no more than the **ReadDocument** permission. + [!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] -The following table describes the subset of the JavaScript API that is enabled by each permission level. +- **Add-in only manifest**: Use the [Permissions](/javascript/api/manifest/permissions) element of the manifest. The following example requests the **write document** permission, which allows only methods that can write to (but not read) the document. -|Permission|Enabled subset of the API| -|:-----|:-----| -|**Restricted**|The methods of the [Settings](/javascript/api/office/office.settings) object, and the [Document.getActiveViewAsync](/javascript/api/office/office.document#office-office-document-getactiveviewasync-member(1)) method. This is the minimum permission level that can be requested by a content or task pane add-in.| -|**ReadDocument**|In addition to the API allowed by the **Restricted** permission, adds access to the API members necessary to read the document and manage bindings. This includes the use of:<br/><ul><li><p>The <a href="http://github.com/javascript/api/office/office.document#getSelectedDataAsync_coercionType__options__callback_" target="_blank">Document.getSelectedDataAsync</a> method to get the selected text, HTML (Word only), or tabular data, but not the underlying Open Office XML (OOXML) code that contains all of the data in the document.</p></li><li><p>The <a href="http://github.com/javascript/api/office/office.document#getFileAsync_fileType__options__callback_" target="_blank">Document.getFileAsync</a> method to get all of the text in the document, but not the underlying OOXML binary copy of the document.</p></li><li><p>The <a href="http://github.com/javascript/api/office/office.binding#getDataAsync_options__callback_" target="_blank">Binding.getDataAsync</a> method for reading bound data in the document.</p></li><li><p>The <a href="http://github.com/javascript/api/office/office.bindings#addFromNamedItemAsync_itemName__bindingType__options__callback_" target="_blank">addFromNamedItemAsync</a>, <a href="http://github.com/javascript/api/office/office.bindings#addFromPromptAsync_bindingType__options__callback_" target="_blank">addFromPromptAsync</a>, <a href="http://github.com/javascript/api/office/office.bindings#addFromSelectionAsync_bindingType__options__callback_" target="_blank">addFromSelectionAsync</a> methods of the <span class="keyword">Bindings</span> object for creating bindings in the document.</p></li><li><p>The <a href="http://github.com/javascript/api/office/office.bindings#getAllAsync_options__callback_" target="_blank">getAllAsync</a>, <a href="http://github.com/javascript/api/office/office.bindings#getByIdAsync_id__options__callback_" target="_blank">getByIdAsync</a>, and <a href="http://github.com/javascript/api/office/office.bindings#releaseByIdAsync_id__options__callback_" target="_blank">releaseByIdAsync</a> methods of the <span class="keyword">Bindings</span> object for accessing and removing bindings in the document.</p></li><li><p>The <a href="http://github.com/javascript/api/office/office.document#getFilePropertiesAsync_options__callback_" target="_blank">Document.getFilePropertiesAsync</a> method to access document file properties, such as the URL of the document.</p></li><li><p>The <a href="http://github.com/javascript/api/office/office.document#goToByIdAsync_id__goToType__options__callback_" target="_blank">Document.goToByIdAsync</a> method to navigate to named objects and locations in the document.</p></li><li><p>For task pane add-ins for Project, all of the "get" methods of the <a href="http://github.com/javascript/api/office/office.document" target="_blank">ProjectDocument</a> object. </p></li></ul>| -|**ReadAllDocument**|In addition to the API allowed by the **Restricted** and **ReadDocument** permissions, allows the following additional access to document data.<br/><ul><li><p>The <span class="keyword">Document.getSelectedDataAsync</span> and <span class="keyword">Document.getFileAsync</span> methods can access the underlying OOXML code of the document (which in addition to the text may include formatting, links, embedded graphics, comments, revisions, and so forth).</p></li></ul>| -|**WriteDocument**|In addition to the API allowed by the **Restricted** permission, adds access to the following API members.<br/><ul><li><p>The <a href="http://github.com/javascript/api/office/office.document#setSelectedDataAsync_data__options__callback_" target="_blank">Document.setSelectedDataAsync</a> method to write to the user's selection in the document.</p></li></ul>| -|**ReadWriteDocument**|In addition to the API allowed by the **Restricted**, **ReadDocument**, **ReadAllDocument**, and **WriteDocument** permissions, includes access to all remaining API supported by content and task pane add-ins, including methods for subscribing to events. You must declare the **ReadWriteDocument** permission to access these additional API members:<br/><ul><li><p>The <a href="http://github.com/javascript/api/office/office.binding#setDataAsync_data__options__callback_" target="_blank">Binding.setDataAsync</a> method for writing to bound regions of the document.</p></li><li><p>The <a href="http://github.com/javascript/api/office/office.tablebinding#addRowsAsync_rows__options__callback_" target="_blank">TableBinding.addRowsAsync</a> method for adding rows to bound tables.</p></li><li><p>The <a href="http://github.com/javascript/api/office/office.tablebinding#addColumnsAsync_tableData__options__callback_" target="_blank">TableBinding.addColumnsAsync</a> method for adding columns to bound tables.</p></li><li><p>The <a href="http://github.com/javascript/api/office/office.tablebinding#deleteAllDataValuesAsync_options__callback_" target="_blank">TableBinding.deleteAllDataValuesAsync</a> method for deleting all data in a bound table.</p></li><li><p>The <a href="http://github.com/javascript/api/office/office.tablebinding#setFormatsAsync_cellFormat__options__callback_" target="_blank">setFormatsAsync</a>, <a href="http://github.com/javascript/api/office/office.tablebinding#clearFormatsAsync_options__callback_" target="_blank">clearFormatsAsync</a>, and <a href="http://github.com/javascript/api/office/office.tablebinding#setTableOptionsAsync_tableOptions__options__callback_" target="_blank">setTableOptionsAsync</a> methods of the <span class="keyword">TableBinding</span> object for setting formatting and options on bound tables.</p></li><li><p>All of the members of the <a href="http://github.com/javascript/api/office/office.customxmlnode" target="_blank">CustomXmlNode</a>, <a href="http://github.com/javascript/api/office/office.customxmlpart" target="_blank">CustomXmlPart</a>, <a href="http://github.com/javascript/api/office/office.customxmlparts" target="_blank">CustomXmlParts</a>, and <a href="http://github.com/javascript/api/office/office.customxmlprefixmappings" target="_blank">CustomXmlPrefixMappings</a> objects.</p></li><li><p>All of the methods for subscribing to the events supported by content and task pane add-ins, specifically the <span class="keyword">addHandlerAsync</span> and <span class="keyword">removeHandlerAsync</span> methods of the <a href="http://github.com/javascript/api/office/office.binding" target="_blank">Binding</a>, <a href="http://github.com/javascript/api/office/office.customxmlpart" target="_blank">CustomXmlPart</a>, <a href="http://github.com/javascript/api/office/office.document" target="_blank">Document</a>, <a href="http://github.com/javascript/api/office/office.document" target="_blank">ProjectDocument</a>, and <a href="http://github.com/javascript/api/office/office.document#settings" target="_blank">Settings</a> objects.</p></li></ul>| + ```XML + <Permissions>WriteDocument</Permissions> + ``` + +As a best practice, you should request permissions based on the principle of *least privilege*. That is, you should request permission to access only the minimum subset of the API that your add-in requires to function correctly. For example, if your add-in needs only to read data in a user's document for its features, you should request no more than the **read document** permission. + +The following table describes the subsets of the [Common and Application-specific JavaScript APIs](understanding-the-javascript-api-for-office.md#api-models) that are enabled by each permission level. + +|Permission canonical name|Add-in only manifest name|Unified manifest name|Enabled subset of the Application-specific APIs|Enabled subset of the Common APIs| +|:-----|:-----|:-----|:-----|:-----| +|**restricted**|Restricted|Document.Restricted.User|None|The methods of the [Settings](/javascript/api/office/office.settings) object, and the [Document.getActiveViewAsync](/javascript/api/office/office.document#office-office-document-getactiveviewasync-member(1)) method. This is the minimum permission level that can be requested by an add-in.| +|**read document**|ReadDocument|Document.Read.User|All and only APIs that read the document or its properties.|In addition to the API allowed by the **restricted** permission, adds access to the API members necessary to read the document and manage bindings. This includes the use of:<ul><li>The [Document.getSelectedDataAsync](/javascript/api/office/office.document#office-office-document-getselecteddataasync-member(1)) method to get the selected text, HTML (Word only), or tabular data, but not the underlying Open Office XML (OOXML) code that contains all of the data in the document.</li><li>The [Document.getFileAsync](/javascript/api/office/office.document#office-office-document-getfileasync-member(1)) method to get all of the text in the document, but not the underlying OOXML binary copy of the document</li><li>The [Binding.getDataAsync](/javascript/api/office/office.binding#office-office-binding-getdataasync-member(1)) method for reading bound data in the document.</li><li>The [addFromNamedItemAsync](/javascript/api/office/office.binding#office-office-bindings-addfromnameditemasync-member(1)), [addFromPromptAsync](/javascript/api/office/office.binding#office-office-bindings-addfrompromptasync-member(1)), and [addFromSelectionAsync](/javascript/api/office/office.binding#office-office-bindings-addfromselectionasync-member(1)) methods of the Bindings object for creating bindings in the document.</li><li>The [getAllAsync](/javascript/api/office/office.binding#office-office-bindings-getallasync-member(1)), [getByIdAsync](/javascript/api/office/office.binding#office-office-bindings-getbyidasync-member(1)), and [releaseByIdAsync](/javascript/api/office/office.binding#office-office-bindings-releasebyidasync-member(1)) methods of the Bindings object for accessing and removing bindings in the document.</li><li>The [Document.getFilePropertiesAsync](/javascript/api/office/office.document#office-office-document-getfilepropertiesasync-member(1)) method to access document file properties, such as the URL of the document.</li><li><p>The [Document.goToByIdAsync](/javascript/api/office/office.document#office-office-document-gotobyidasync-member(1)) method to navigate to named objects and locations in the document.</p></li><li>For task pane add-ins for Project, all of the "get" methods of the [ProjectDocument](/javascript/api/office/office.document) object.</li></ul>| +|**read all document**|ReadAllDocument|Document.ReadAll.User|Same as **read document**.|In addition to the API allowed by the **restricted** and **read document** permissions, allows the following additional access to document data.<ul><li><p>The [Document.getSelectedDataAsync](/javascript/api/office/office.document#office-office-document-getselecteddataasync-member(1)) and [Document.getFileAsync](/javascript/api/office/office.document#office-office-document-getfileasync-member(1)) methods can access the underlying OOXML code of the document (which in addition to the text may include formatting, links, embedded graphics, comments, revisions, and so forth).</li></ul>| +|**write document**|WriteDocument|Document.Write.User|All and only APIs that write to the document or its properties.|In addition to the API allowed by the **restricted** permission, adds access to the following API members.<ul><li>The [Document.setSelectedDataAsync](/javascript/api/office/office.document#office-office-document-setselecteddataasync-member(1)) method to write to the user's selection in the document.</li></ul>| +|**read/write document**|ReadWriteDocument|Document.ReadWrite.User|All Application-specfic APIs, including those that subscribe to events.|In addition to the API allowed by the **restricted**, **read document**, **read all document**, and **write document** permissions, includes access to all remaining API supported by add-ins, including methods for subscribing to events. You must declare the **read/write document** permission to access these additional API members:<ul><li><p>The [Binding.setDataAsync](/javascript/api/office/office.binding#office-office-binding-setdataasync-member(1)) method for writing to bound regions of the document</li><li>The [TableBinding.addRowsAsync](/javascript/api/office/office.tablebinding#office-office-tablebinding-addrowsasync-member(1)) method for adding rows to bound tables.</li><li>The [TableBinding.addColumnsAsync](/javascript/api/office/office.tablebinding#office-office-tablebinding-addcolumnsasync-member(1)) method for adding columns to bound tables.</li><li>The [TableBinding.deleteAllDataValuesAsync](/javascript/api/office/office.tablebinding#office-office-tablebinding-deletealldatavaluesasync-member(1)) method for deleting all data in a bound table.</li><li>The [setFormatsAsync](/javascript/api/office/office.tablebinding#office-office-tablebinding-setformatsasync-member(1)), [clearFormatsAsync](/javascript/api/office/office.tablebinding#office-office-tablebinding-clearformatsasync-member(1)), and [setTableOptionsAsync](/javascript/api/office/office.tablebinding#office-office-tablebinding-settableoptionsasync-member(1)) methods of the TableBinding object for setting formatting and options on bound tables.</li><li>All of the members of the [CustomXmlNode](/javascript/api/office/office.customxmlnode), [CustomXmlPart](/javascript/api/office/office.customxmlpart), [CustomXmlParts](/javascript/api/office/office.customxmlparts), and [CustomXmlPrefixMappings](/javascript/api/office/office.customxmlprefixmappings) objects</li><li>All of the methods for subscribing to the events supported by add-ins, specifically the `addHandlerAsync` and `removeHandlerAsync` methods of the [Binding](/javascript/api/office/office.binding), [CustomXmlPart](/javascript/api/office/office.customxmlpart), [Document](/javascript/api/office/office.document), [ProjectDocument](/javascript/api/office/office.document), and [Settings](/javascript/api/office/office.document#office-office-document-settings-member) objects.</li></ul>| ## See also diff --git a/docs/develop/requirements-property-unified-manifest.md b/docs/develop/requirements-property-unified-manifest.md index efe33cc785..8cc5fe888d 100644 --- a/docs/develop/requirements-property-unified-manifest.md +++ b/docs/develop/requirements-property-unified-manifest.md @@ -1,7 +1,7 @@ ---- +--- title: Specify Office Add-in requirements in the unified manifest for Microsoft 365 description: Learn how to use requirements to configure on which host and platforms an add-in can be installed and which features are available. -ms.date: 07/03/2024 +ms.date: 04/18/2025 ms.topic: how-to ms.localizationpriority: medium --- @@ -48,7 +48,17 @@ You can have more than one capability object. The following example shows how to ## Filter features -The "requirements" properties in descendant objects of "extensions" are used to block some features of an add-in while still allowing the add-in to be installed. The implementation of this filtering is done at the source of installation, such as [AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center) or [Microsoft 365 Admin Center](/office/dev/add-ins/publish/publish). If the version of Office doesn't support the requirements specified for the feature, then the JSON node for the feature is removed from the manifest before it is installed in the Office application. +The "requirements" properties in descendant objects of "extensions" are used to block some features of an add-in while still allowing the add-in to be installed. The implementation of this filtering is done at the source of installation, such as [Microsoft Marketplace](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center) or [Microsoft 365 Admin Center](/office/dev/add-ins/publish/publish). If the version of Office doesn't support the requirements specified for the feature, then the JSON node for the feature is removed from the manifest before it is installed in the Office application. + +> [!TIP] +> Don't include a capability, formFactor, or scope requirement in a descendant object of "extensions" that's *less* restrictive than the corresponding capability, formFactor, or scope requirement in the ancestor "extensions.requirements" property, if there is one. Since the add-in can't be installed on clients that don't meet the ancestor requirement, no feature filtering would occur anyway. For example, if an "extensions.requirements.capabilities" property requires **Mailbox 1.10**, there's no point in requiring **Mailbox 1.9** in any descendant objects. + +> [!NOTE] +> Office Add-ins that use the unified manifest for Microsoft 365 are *directly* supported in Office on the web, in [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627), and in Office on Windows connected to a Microsoft 365 subscription, Version 2304 (Build 16320.00000) or later. +> +> When the app package that contains the unified manifest is deployed in [Microsoft Marketplace](https://marketplace.microsoft.com/) or the [Microsoft 365 Admin Center](/office/dev/add-ins/publish/publish) then an add-in only manifest is generated from the unified manifest and stored. This add-in only manifest enables the add-in to be installed on platforms that don't directly support the unified manifest, including Office on Mac, Office on mobile, subscription versions of Office on Windows earlier than 2304 (Build 16320.00000), and perpetual versions of Office on Windows. +> +> Feature filtering is less fine-grained in the add-in only manifest. As a result, on platforms that don't directly support the unified manifest, adding a "requirements" subproperty to *any* child of "extensions" is effectively the same as adding that same "requirements" subproperty to *all* the children of "extensions" with one possible exception. So, on these platforms *none* of the features that are configured in these child properties of "extensions" will be available on platform and version combinations that don't meet the specified requirements. The exception is the "extensions.alternates" property. If this property is present, the alternates feature will be filtered in or out based only on its own "requirements" subproperty (if any), not on the "requirements" subproperties of any other child properties of "extensions". ### extensions.alternates.requirements @@ -58,14 +68,9 @@ The "extensions.alternates" property enables add-in developers to do the followi - Either hide or give preference to the version that uses the older technology. - Specify icons that are needed to make the unified manifest version of the add-in installable on Office versions that don't directly support the unified manifest. -> [!NOTE] -> Office Add-ins that use the unified manifest for Microsoft 365 are *directly* supported in Office on the web, in [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627), and in Office on Windows connected to a Microsoft 365 subscription, Version 2304 (Build 16320.00000) or later. -> -> When the app package that contains the unified manifest is deployed in [AppSource](https://appsource.microsoft.com/) or the [Microsoft 365 Admin Center](/office/dev/add-ins/publish/publish) then, if the manifest has a valid "alternateIcons" property, an add-in only manifest is generated from the unified manifest and stored. This add-in only manifest enables the add-in to be installed on platforms that don't directly support the unified manifest, including Office on Mac, Office on mobile, subscription versions of Office on Windows earlier than 2304 (Build 16320.00000), and perpetual versions of Office on Windows. - For more information, see [Manage both a unified manifest and an add-in only manifest version of your Office Add-in](/office/dev/add-ins/concepts/duplicate-legacy-metaos-add-ins). -The "requirements" subproperty of "extensions.alternates" to selectively apply the "hide" or "prefer" subproperties only when certain requirements are met. +Use the "requirements" subproperty of "extensions.alternates" to selectively apply the "hide" or "prefer" subproperties only when certain requirements are met. For example, suppose that you want to hide (from the Office UI for installing add-ins) an older version of your add-in, but only in Office versions that support the **Mailbox 1.10** requirement set. You could do that with markup similar to the following: @@ -134,6 +139,10 @@ For example, suppose an Outlook add-in is configured to autolaunch in response t ] ``` +### extensions.contentRuntimes.requirements + +The "extensions.contentRuntimes" property can't be combined with any other child property of "extensions" (except "extensions.requirements"). This means that the content is the *only* feature of the add-in, so it makes no sense to filter out the feature's availability on some combinations of platform and Office version while allowing add-in to be installable on those same combinations. Accordingly, don't use the "requirements" property in "contentRuntimes". To control the installability of the content add-in, use the "extensions.requirements" property of the parent "extensions". + ### extensions.contextMenus.requirements The "extensions.contextMenus" property configures the add-in's context menus. A context menu is a shortcut menu that appears when you right-click (or select and hold) in the Office UI. The "requirements" subproperty can be used to allow context menus only when certain requirements are met. @@ -167,6 +176,50 @@ For example, suppose you want to show context menus only in Excel versions that ] ``` +### extensions.getStartedMessages.requirements + +The objects in the `extensions.getStartedMessages` array provide information about an Office Add-in that appears in various places in Office, such as the callout that appears in Office when an Office Add-in is installed. There can be up to three objects in the array. If there's more than one, use the `extensions.getStartedMessages.requirements` property to ensure that no more than one of these objects is used in any given Office client. If `extensions.getStartedMessages` is omitted or all of the objects in the array are filtered out, the callout uses the values from the "name.short" and "description.short" manifest properties instead. + +For example, suppose an Excel add-in simplifies the process of adding conditional formatting to ranges. Some of the APIs that the add-in uses were introduced with the **ExcelApi 1.17** requirement set, but the add-in still provides useful functionality that only requires the **ExcelApi 1.6** requirement set. The `extensions.getStartedMessages` array can be configured to provide one description of the add-in for Excel clients that support the requirement sets from **1.6** to **1.16**, but a different description for clients that support **1.17** and later. The following is an example. Note that in this example, if the add-in is configured to be installable on Excel clients that don't support requirement set **1.6**, then on those clients neither of these getStartedMessage objects would be used. Instead, Office would use the "name.short" and "description.short" properties. + +```json +"extensions": [ + ... + { + ... + "getStartedMessages": [ + { + "title": "Contoso Excel Formatting", + "description": "Use conditional formatting with our add-in.", + "learnMoreUrl": "https://contoso.com/simple-conditional-formatting-details.html", + "requirements": { + "capabilities": [ + { + "name": "ExcelApi", + "minVersion": "1.6", + "maxVersion": "1.16" + } + ] + } + }, + { + "title": "Contoso Advanced Excel Formatting", + "description": "Use conditional formatting and dynamic formatting changes with our add-in.", + "learnMoreUrl": "https://contoso.com/advanced-conditional-formatting-details.html", + "requirements": { + "capabilities": [ + { + "name": "ExcelApi", + "minVersion": "1.17" + } + ] + } + } + ] + } +] +``` + ### extensions.ribbons.requirements The "extensions.ribbons" property is used to customize the Office application ribbon when the add-in is installed. The "requirements" subproperty can be used to prevent the customizations in some versions of Office. @@ -230,3 +283,32 @@ The previous example shown in [extensions.autoRunEvents.requirements](#extension ``` Similarly, for the example in [extensions.ribbons.requirements](#extensionsribbonsrequirements), if the action linked to the custom button is the only action configured in a runtime object, then that runtime object should be blocked in the same circumstances in which the ribbon object is blocked. + +### extensions.keyboardShortcuts.requirements (developer preview) + +The `extensions.keyboardShortcuts` property defines custom keyboard shortcuts or key combinations to run specific actions. To learn how to create custom shortcuts, see [Add custom keyboard shortcuts to your Office Add-ins](../design/keyboard-shortcuts.md). + +The "requirements" subproperty can be used to ensure that the custom shortcuts are only available on platforms that support the [SharedRuntime 1.1 API](/javascript/api/requirement-sets/common/shared-runtime-requirement-sets). The following example shows how to configure this in your manifest. + +```json +"extensions": [ + ... + { + ... + "keyboardShortcuts": [ + { + //Insert details of the keyboard shortcut configuration here. + + "requirements" : { + "capabilities": [ + { + "name": "SharedRuntime", + "minVersion": "1.1" + } + ] + } + } + ] + } +] +``` diff --git a/docs/develop/run-code-on-document-open.md b/docs/develop/run-code-on-document-open.md index 17f61e5c2e..500e40f2f7 100644 --- a/docs/develop/run-code-on-document-open.md +++ b/docs/develop/run-code-on-document-open.md @@ -2,7 +2,7 @@ title: Run code in your Office Add-in when the document opens description: Learn how to run code in your Office Add-in add-in when the document opens. ms.topic: how-to -ms.date: 07/11/2023 +ms.date: 09/22/2025 ms.localizationpriority: medium --- @@ -10,7 +10,7 @@ ms.localizationpriority: medium [!include[Shared runtime requirements](../includes/shared-runtime-requirements-note.md)] -You can configure your Office Add-in to load and run code as soon as the document is opened. This is useful if you need to register event handlers, pre-load data for the task pane, synchronize UI, or perform other tasks before the add-in is visible. +You can configure your Office Add-in to load and run code as soon as the document is opened. This is useful if you need to register event handlers, pre-load data for the task pane, synchronize UI, or perform other tasks before the add-in is visible. > [!NOTE] > The configuration is implemented with a method that your code calls at runtime. This means that the add-in *won't* run the *first time* a user opens the document. The add-in must be opened manually for the first time on any document. After the method runs, either in [Office.initialize](/javascript/api/office#office-office-initialize-function(1)), [Office.onReady](/javascript/api/office#office-office-onready-function(1)), or because the user takes a code path that runs it; then whenever the document is reopened, the add-in loads immediately and any code in the `Office.initialize` or `Office.onReady` method runs. @@ -110,3 +110,4 @@ let behavior = await Office.addin.getStartupBehavior(); - [Share data and events between Excel custom functions and task pane tutorial](../tutorials/share-data-and-events-between-custom-functions-and-the-task-pane-tutorial.md) - [Work with Events using the Excel JavaScript API](../excel/excel-add-ins-events.md) - [Runtimes in Office Add-ins](../testing/runtimes.md) +- [Managing trust options for Office Add-ins](../publish/manage-trust-options.md) diff --git a/docs/develop/show-hide-add-in.md b/docs/develop/show-hide-add-in.md index b6a6c2cd38..f7bc0c76bc 100644 --- a/docs/develop/show-hide-add-in.md +++ b/docs/develop/show-hide-add-in.md @@ -1,7 +1,7 @@ ---- +--- title: Show or hide the task pane of your Office Add-in description: Learn how to programmatically hide or show the user interface of an add-in while it runs continuously. -ms.date: 08/15/2022 +ms.date: 02/12/2025 ms.topic: how-to ms.localizationpriority: medium --- @@ -36,7 +36,14 @@ The previous code is a handler that is registered for the [Office.Worksheet.onDe ## Additional details on showing the task pane -When you call `Office.addin.showAsTaskpane()`, Office will display in a task pane the file that you assigned as the resource ID (`resid`) value of the task pane. This `resid` value can be assigned or changed by opening your **manifest.xml** file and locating **\<SourceLocation\>** inside the `<Action xsi:type="ShowTaskpane">` element. +When you call `Office.addin.showAsTaskpane()`, Office will display in a task pane the file that you specified in the manifest. The configuration depends on what type of manifest you're using. + +- **Unified manifest for Microsoft 365**: The URL of the file is assigned as the value of a "runtimes.code.page" property of the runtime object which has an action object of type "openPage". + + [!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] + +- **Add-in only manifest**: The URL of the file is assigned as the resource ID (`resid`) value of the task pane. This `resid` value can be assigned or changed by opening your manifest file and locating `<SourceLocation>` inside the `<Action xsi:type="ShowTaskpane">` element. + (See [Configure your Office Add-in to use a shared runtime](configure-your-add-in-to-use-a-shared-runtime.md) for additional details.) Since `Office.addin.showAsTaskpane()` is an asynchronous method, your code will continue running until the method is complete. Wait for this completion with either the `await` keyword or a `then()` method, depending on which JavaScript syntax you are using. diff --git a/docs/develop/specify-api-requirements-runtime.md b/docs/develop/specify-api-requirements-runtime.md new file mode 100644 index 0000000000..dad2a23ad7 --- /dev/null +++ b/docs/develop/specify-api-requirements-runtime.md @@ -0,0 +1,81 @@ +--- +title: Check for API availability at runtime +description: Learn how to verify at runtime that the Office application supports your add-in's API calls. +ms.topic: best-practice +ms.date: 02/12/2025 +ms.localizationpriority: medium +--- + +# Check for API availability at runtime + +If your add-in uses a specific extensibility feature for some of its functionality, but has other useful functionality that doesn't require the extensibility feature, you should design the add-in so that it's installable on platform and Office version combinations that don't support the extensibility feature. It can provide a valuable, albeit diminished, experience on those combinations. + +When the difference in the two experiences consists entirely of differences in the Office JavaScript Library APIs that are called, and not in any features that are configured in the manifest, then you test at runtime to discover whether the user's Office client supports an [API requirement set](office-versions-and-requirement-sets.md). You can also [test at runtime whether APIs that aren't in a set are supported](#check-for-setless-api-support). + +> [!NOTE] +> To provide alternate experiences with features that require manifest configuration, follow the guidance in [Specify Office hosts and API requirements with the unified manifest](specify-office-hosts-and-api-requirements-unified.md) or [Specify Office applications and API requirements with the add-in only manifest](specify-office-hosts-and-api-requirements.md). + +## Check for requirement set support + +The [isSetSupported](/javascript/api/office/office.requirementsetsupport#office-office-requirementsetsupport-issetsupported-member(1)) method is used to check for requirement set support. Pass the requirement set's name and the minimum version as parameters. If the requirement set is supported, `isSetSupported` returns `true`. The following code shows an example. + +```js +if (Office.context.requirements.isSetSupported("WordApi", "1.2")) { + // Code that uses API members from the WordApi 1.2 requirement set. +} else { + // Provide diminished experience here. + // For example, run alternate code when the user's Word is + // volume-licensed perpetual Word 2016 (which doesn't support WordApi 1.2). +} +``` + +About this code, note: + +- The first parameter is required. It's a string that represents the name of the requirement set. For more information about available requirement sets, see [Office Add-in requirement sets](/javascript/api/requirement-sets/common/office-add-in-requirement-sets). +- The second parameter is optional. It's a string that specifies the minimum requirement set version that the Office application must support in order for the code within the `if` statement to run (for example, "1.9"). If not used, version "1.1" is assumed. + +> [!WARNING] +> When calling the `isSetSupported` method, the value of the second parameter (if specified) should be a string, not a number. The JavaScript parser can't differentiate between numeric values such as 1.1 and 1.10, whereas it can for string values such as "1.1" and "1.10". + +The following table shows the requirement set names for the application-specific API models. + +|Office application|RequirementSetName| +|---|---| +|Excel|ExcelApi| +|OneNote|OneNoteApi| +|Outlook|Mailbox| +|PowerPoint|PowerPointApi| +|Word|WordApi| + +The following is an example of using the method with one of the Common API model requirement sets. + +```js +if (Office.context.requirements.isSetSupported('CustomXmlParts')) { + // Run code that uses API members from the CustomXmlParts requirement set. +} else { + // Run alternate code when the user's Office application doesn't support the CustomXmlParts requirement set. +} +``` + +> [!NOTE] +> The `isSetSupported` method and the requirement sets for these applications are available in the latest Office.js file on the CDN. If you don't use Office.js from the CDN, your add-in might generate exceptions if you are using an old version of the library in which `isSetSupported` is undefined. For more information, see [Use the latest Office JavaScript API library](specify-office-hosts-and-api-requirements-unified.md#use-the-latest-office-javascript-api-library). + +## Check for setless API support + +When your add-in depends on a method that isn't part of a requirement set, called a setless API, use a runtime check to determine whether the method is supported by the Office application, as shown in the following code example. For a complete list of methods that don't belong to a requirement set, see [Office Add-in requirement sets](/javascript/api/requirement-sets/common/office-add-in-requirement-sets#methods-that-arent-part-of-a-requirement-set). + +> [!NOTE] +> We recommend that you limit the use of this type of runtime check in your add-in's code. + +The following code example checks whether the Office application supports `document.setSelectedDataAsync`. + +```js +if (Office.context.document.setSelectedDataAsync) { + // Run code that uses `document.setSelectedDataAsync`. +} +``` + +## See also +- [Office requirement sets availability](office-versions-and-requirement-sets.md#office-requirement-sets-availability) +- [Specify Office hosts and API requirements with the unified manifest](specify-office-hosts-and-api-requirements-unified.md) +- [Specify Office hosts and API requirements with the add-in only manifest](specify-office-hosts-and-api-requirements.md) diff --git a/docs/develop/specify-office-hosts-and-api-requirements-unified.md b/docs/develop/specify-office-hosts-and-api-requirements-unified.md new file mode 100644 index 0000000000..621437312e --- /dev/null +++ b/docs/develop/specify-office-hosts-and-api-requirements-unified.md @@ -0,0 +1,165 @@ +--- +title: Specify Office hosts and API requirements with the unified manifest +description: Learn how to specify in the unified manifest the Office applications and API requirements for your add-in to work as expected. +ms.topic: best-practice +ms.date: 02/12/2025 +ms.localizationpriority: medium +--- + +# Specify Office applications and API requirements with the unified manifest + +> [!NOTE] +> For information about specifying requirements with the add-in only manifest, see [Specify Office hosts and API requirements with the add-in only manifest](specify-office-hosts-and-api-requirements.md). + +Your Office Add-in might depend on a specific Office application (also called an Office host) or on specific members of the Office JavaScript Library (office.js). For example, your add-in might: + +- Run in a single Office application (e.g., Word or Excel), or several applications. +- Make use of Office JavaScript APIs that are only available in some versions of Office. For example, the volume-licensed perpetual version of Excel 2016 doesn't support all Excel-related APIs in the Office JavaScript library. +- Be designed for use only in a mobile form factor. + +In these situations, you need to ensure that your add-in is never installed on Office applications or Office versions in which it cannot run. + +There are also scenarios in which you want to control which features of your add-in are visible to users based on their Office application and Office version. Three examples are: + +- Your add-in has features that are useful in both Word and PowerPoint, such as text manipulation, but it has some additional features that only make sense in PowerPoint, such as slide management features. You need to hide the PowerPoint-only features when the add-in is running in Word. +- Your add-in has a feature that requires an Office JavaScript API method that is supported in some versions of an Office application, such as Microsoft 365 subscription Excel, but isn't supported in others, such as volume-licensed perpetual Excel 2016. But your add-in has other features that require only Office JavaScript API methods that *are* supported in volume-licensed perpetual Excel 2016. In this scenario, you need the add-in to be installable on that version of Excel 2016, but the feature that requires the unsupported method should be hidden from those users. +- Your add-in has features that are supported in desktop Office, but not in mobile Office. + +This article helps you understand how to ensure that your add-in works as expected and reaches the broadest audience possible. + +> [!NOTE] +> For a high-level view of where Office Add-ins are currently supported, see the [Office client application and platform availability for Office Add-ins](/javascript/api/requirement-sets) page. + +> [!TIP] +> Many of the tasks described in this article are done for you, in whole or in part, when you create your add-in project with a tool, such as the [Yeoman generator for Office Add-ins](yeoman-generator-overview.md) or one of the Office Add-in templates in Visual Studio. In such cases, please interpret the task as meaning that you should verify that it has been done. + +## Use the latest Office JavaScript API library + +Your add-in should load the most current version of the Office JavaScript API library from the content delivery network (CDN). To do this, be sure you have the following `<script>` tag in the first HTML file your add-in opens. Using `/1/` in the CDN URL ensures that you reference the most recent version of Office.js. + +```HTML +<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js" type="text/javascript"></script> +``` + +## Specify which Office applications can host your add-in + +To specify the Office applications on which your add-in can be installed, use the [`"extensions.requirements.scopes"`](/microsoft-365/extensibility/schema/requirements-extension-element#scopes) array. Specify any subset of `"mail"`, `"workbook"`, `"document"`, and `"presentation"`. The following table shows which Office application and platform combinations correspond to these values. It also shows what kind of add-in can be installed for each scope. + +| Name | Office client applications | Available add-in types | +|:--------------|:-----------------------------------------------|:-----------------------| +| document | Word on the web, Windows, Mac, iPad | Task pane | +| mail | Outlook on the web, Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic), Android, iOS | Mail | +| presentation | PowerPoint on the web, Windows, Mac, iPad | Task pane, Content | +| workbook | Excel on the web, Windows, Mac, iPad | Task pane, Content | + +> [!NOTE] +> Content add-ins have an `"extensions.contentRuntimes"` property. They can't have an [`"extensions.runtimes"`](/microsoft-365/extensibility/schema/extension-runtimes-array?view=m365-app-prev&preserve-view=true) property so they can't be combined with a Task pane or Mail add-in. For more information about Content add-ins, see [Content Office Add-ins](../design/content-add-ins.md). + +For example, the following JSON specifies that the add-in can install on any release of Excel, which includes Excel on the web, Windows, and iPad, but can't be installed on any other Office application. + +```json +"extensions": [ + { + "requirements": { + "scopes": [ "workbook" ], + }, + ... + } +] +``` + +> [!NOTE] +> Office applications are supported on different platforms and run on desktops, web browsers, tablets, and mobile devices. You usually can't specify which platform can be used to run your add-in. For example, if you specify `"workbook"`, both Excel on the web and on Windows can be used to run your add-in. However, if you specify `"mail"`, your add-in won't run on Outlook mobile clients unless you define the [mobile extension point](/javascript/api/manifest/extensionpoint#mobilemessagereadcommandsurface). + +## Specify which Office APIs your add-in needs + +You can't explicitly specify the Office versions and builds or the platforms on which your add-in should be installable, and you wouldn't want to because you would have to revise your manifest whenever support for the add-in features that your add-in uses is extended to a new version or platform. Instead, specify in the manifest the APIs that your add-in needs. Office prevents the add-in from being installed on combinations of Office version and platform that don't support the APIs and ensures that the add-in won't appear in **My Add-ins**. + +> [!IMPORTANT] +> Only use the `"requirements"` property that is a direct child of [`"extensions"`](/microsoft-365/extensibility/schema/root#extensions) to specify the API members that your add-in must have to be of any significant value at all. If your add-in uses an API for some features, but has other useful features that don't require the API, you should design the add-in so that it's installable on platform and Office version combinations that don't support the API but provides a diminished experience on those combinations. For this purpose, use `"requirements"` properties that aren't direct children of `"extensions"`. For more information, see [Design for alternate experiences](#design-for-alternate-experiences). + +### Requirement sets + +To simplify the process of specifying the APIs that your add-in needs, Office groups most APIs together in [requirement sets](office-versions-and-requirement-sets.md). The APIs in the [Common API Object Model](understanding-the-javascript-api-for-office.md#api-models) are grouped by the development feature that they support. For example, all the APIs connected to table bindings are in the requirement set called "TableBindings 1.1". The APIs in the [Application specific object models](understanding-the-javascript-api-for-office.md#api-models) are grouped by when they were released for use in production add-ins. + +Requirement sets are versioned. For example, the APIs that support [Dialog Boxes](../develop/dialog-api-in-office-add-ins.md) are in the requirement set DialogApi 1.1. When additional APIs that enable messaging from a task pane to a dialog were released, they were grouped into DialogApi 1.2, along with all the APIs in DialogApi 1.1. *Each version of a requirement set is a superset of all earlier versions.* + +Requirement set support varies by Office application, the version of the Office application, and the platform on which it is running. For example, DialogApi 1.2 isn't supported on volume-licensed perpetual versions of Office before Office 2021, but DialogApi 1.1 is supported on all perpetual versions back to Office 2016. You want your add-in to be installable on every combination of platform and Office version that supports the APIs that it uses, so you should always specify in the manifest the *minimum* version of each requirement set that your add-in requires. Details about how to do this are later in this article. + +> [!TIP] +> For more information about requirement set versioning, see [Office requirement sets availability](office-versions-and-requirement-sets.md#office-requirement-sets-availability), and for the complete lists of requirement sets and information about the APIs in each, start with [Office Add-in requirement sets](/javascript/api/requirement-sets/common/office-add-in-requirement-sets). The reference topics for most Office.js APIs also specify the requirement set they belong to (if any). + +### extensions.requirements.capabilities property + +Use the [`"requirements.capabilities"`](/microsoft-365/extensibility/schema/requirements-extension-element-capabilities) property to specify the minimum requirement sets that must be supported by the Office application to install your add-in. If the Office application or platform doesn't support the requirement sets or API members specified in the `"requirements.capabilities"` property, the add-in won't run in that application or platform, and won't display in **My Add-ins**. + +> [!TIP] +> All APIs in the application-specific models are in requirement sets, but some of those in the Common API model aren't. If your add-in requires an API that isn't in any requirement set, you can implement a runtime check for the availability of the API and display a message to the add-in's users if it isn't supported. For more information, see [Check for API availability at runtime](specify-api-requirements-runtime.md). + +The following code example shows how to configure an add-in that is installable in all Office application and platform combinations that support the following: + +- `TableBindings` requirement set, which has a minimum version of "1.1". +- `OOXML` requirement set, which has a minimum version of "1.1". + +```json +"extensions": [ + { + "requirements": { + "capabilities": [ + { + "name": "TableBindings", + "minVersion": "1.1" + }, + { + "name": "OOXML", + "minVersion": "1.1" + } + ], + }, + ... + } +] +``` + +> [!TIP] +> For more information and another example of using the `"extensions.requirements"` property, see the `"extensions.requirements"` section in [Specify Office Add-in requirements in the unified manifest for Microsoft 365](requirements-property-unified-manifest.md#extensionsrequirements). + +### Specify the form factors on which your add-in can be installed + +For an Outlook add-in, you can specify whether the add-in should be installable on desktop (includes tablets) or mobile form factors. To configure this, use the `"extensions.requirements.formFactors"` property. The following example show how to make the Outlook add-in installable on both form factors. + +```json +"extensions": [ + { + "requirements": { + ... + "formFactors": [ + "desktop", + "mobile" + ] + }, + ... + } +] +``` + +## Design for alternate experiences + +The extensibility features that the Office Add-in platform provides can be usefully divided into three kinds: + +- Extensibility features that are available immediately after the add-in is installed. An example of this kind of feature is [Add-in Commands](../design/add-in-commands.md), which are custom ribbon buttons and menus. +- Extensibility features that are available only when the add-in is running and that are implemented with Office.js JavaScript APIs; for example, [Dialog Boxes](../develop/dialog-api-in-office-add-ins.md). +- Extensibility features that are available only at runtime but are implemented with a combination of Office.js JavaScript and manifest configuration. Examples of these are [Excel custom functions](../excel/custom-functions-overview.md), [single sign-on](sso-in-office-add-ins.md), and [custom contextual tabs](../design/contextual-tabs.md). + +If your add-in uses a specific extensibility feature for some of its functionality but has other useful functionality that doesn't require the extensibility feature, you should design the add-in so that it's installable on platform and Office version combinations that don't support the extensibility feature. It can provide a valuable, albeit diminished, experience on those combinations. + +You implement this design differently depending on how the extensibility feature is implemented: + +- For features implemented entirely with JavaScript, see [Check for API availability at runtime](specify-api-requirements-runtime.md). +- For features that require you to configure the manifest, see the "Filter features" section of [Specify Office Add-in requirements in the unified manifest for Microsoft 365](requirements-property-unified-manifest.md#filter-features). + +## See also + +- [Office Add-ins manifest](add-in-manifests.md) +- [Office Add-in requirement sets](/javascript/api/requirement-sets/common/office-add-in-requirement-sets) +- [Specify Office Add-in requirements in the unified manifest for Microsoft 365](requirements-property-unified-manifest.md) diff --git a/docs/develop/specify-office-hosts-and-api-requirements.md b/docs/develop/specify-office-hosts-and-api-requirements.md index b88f0ba38b..e71144ed35 100644 --- a/docs/develop/specify-office-hosts-and-api-requirements.md +++ b/docs/develop/specify-office-hosts-and-api-requirements.md @@ -1,16 +1,19 @@ ---- -title: Specify Office hosts and API requirements +--- +title: Specify Office hosts and API requirements with the add-in only manifest description: Learn how to specify Office applications and API requirements for your add-in to work as expected. ms.topic: best-practice -ms.date: 02/29/2024 +ms.date: 02/12/2025 ms.localizationpriority: medium --- -# Specify Office applications and API requirements +# Specify Office applications and API requirements with the add-in only manifest + +> [!NOTE] +> For information about specifying requirements with the [unified manifest for Microsoft 365](unified-manifest-overview.md), see [Specify Office hosts and API requirements with the unified manifest](specify-office-hosts-and-api-requirements-unified.md). -Your Office Add-in might depend on a specific Office application (also called an Office host) or on specific members of the Office JavaScript API (office.js). For example, your add-in might: +Your Office Add-in might depend on a specific Office application (also called an Office host) or on specific members of the Office JavaScript Library (office.js). For example, your add-in might: -- Run in a single Office application (e.g., Word or Excel), or several applications. +- Run in a single Office application (for example, Word or Excel), or several applications. - Make use of Office JavaScript APIs that are only available in some versions of Office. For example, the volume-licensed perpetual version of Excel 2016 doesn't support all Excel-related APIs in the Office JavaScript library. In these situations, you need to ensure that your add-in is never installed on Office applications or Office versions in which it cannot run. @@ -30,7 +33,7 @@ This article helps you understand which options you should choose to ensure that ## Use the latest Office JavaScript API library -Your add-in should load the most current version of the Office JavaScript API library from the content delivery network (CDN). To do this, be sure you have the following `script` tag in the first HTML file your add-in opens. Using `/1/` in the CDN URL ensures that you reference the most recent version of Office.js. +Your add-in should load the most current version of the Office JavaScript API library from the content delivery network (CDN). To do this, be sure you have the following `<script>` tag in the first HTML file your add-in opens. Using `/1/` in the CDN URL ensures that you reference the most recent version of Office.js. ```HTML <script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js" type="text/javascript"></script> @@ -40,9 +43,9 @@ Your add-in should load the most current version of the Office JavaScript API li By default, an add-in is installable in all Office applications supported by the specified add-in type (that is, Mail, Task pane, or Content). For example, a task pane add-in is installable by default on Access, Excel, OneNote, PowerPoint, Project, and Word. -To ensure that your add-in is installable in a subset of Office applications, use the [Hosts](/javascript/api/manifest/hosts) and [Host](/javascript/api/manifest/host) elements in the manifest. +To ensure that your add-in is installable in only a subset of Office applications, use the [Hosts](/javascript/api/manifest/hosts) and [Host](/javascript/api/manifest/host) elements in the add-in only manifest. -For example, the following **\<Hosts\>** and **\<Host\>** declaration specifies that the add-in can install on any release of Excel, which includes Excel on the web, Windows, and iPad, but cannot be installed on any other Office application. +For example, the following `<Hosts>` and `<Host>` declaration specifies that the add-in can install on any release of Excel, which includes Excel on the web, Windows, and iPad, but can't be installed on any other Office application. ```xml <Hosts> @@ -50,7 +53,7 @@ For example, the following **\<Hosts\>** and **\<Host\>** declaration specifies </Hosts> ``` -The **\<Hosts\>** element can contain one or more **\<Host\>** elements. There should be a separate **\<Host\>** element for each Office application on which the add-in should be installable. The `Name` attribute is required and can be set to one of the following values. +The `<Hosts>` element can contain one or more `<Host>` elements. There should be a separate `<Host>` element for each Office application on which the add-in should be installable. The `Name` attribute is required and can be set to one of the following values. | Name | Office client applications | Available add-in types | |:--------------|:-----------------------------------------------|:-----------------------| @@ -66,7 +69,7 @@ The **\<Hosts\>** element can contain one or more **\<Host\>** elements. There s > Office applications are supported on different platforms and run on desktops, web browsers, tablets, and mobile devices. You usually can't specify which platform can be used to run your add-in. For example, if you specify `Workbook`, both Excel on the web and on Windows can be used to run your add-in. However, if you specify `Mailbox`, your add-in won't run on Outlook mobile clients unless you define the [mobile extension point](/javascript/api/manifest/extensionpoint#mobilemessagereadcommandsurface). > [!NOTE] -> It isn't possible for an add-in manifest to apply to more than one type: Mail, Task pane, or Content. This means that if you want your add-in to be installable on Outlook and on one of the other Office applications, you must create *two* add-ins, one with a Mail type manifest and the other with a Task pane or Content type manifest. +> It isn't possible for an add-in only manifest to apply to more than one type: Mail, Task pane, or Content. This means that if you want your add-in to be installable on Outlook and on one of the other Office applications, you must create *two* add-ins, one with a Mail type manifest and the other with a Task pane or Content type manifest. ## Specify which Office versions and platforms can host your add-in @@ -77,7 +80,7 @@ You can't explicitly specify the Office versions and builds or the platforms on ### Requirement sets -To simplify the process of specifying the APIs that your add-in needs, Office groups most APIs together in *requirement sets*. The APIs in the [Common API Object Model](understanding-the-javascript-api-for-office.md#api-models) are grouped by the development feature that they support. For example, all the APIs connected to table bindings are in the requirement set called "TableBindings 1.1". The APIs in the [Application specific object models](understanding-the-javascript-api-for-office.md#api-models) are grouped by when they were released for use in production add-ins. +To simplify the process of specifying the APIs that your add-in needs, Office groups most APIs together in [requirement sets](office-versions-and-requirement-sets.md). The APIs in the [Common API Object Model](understanding-the-javascript-api-for-office.md#api-models) are grouped by the development feature that they support. For example, all the APIs connected to table bindings are in the requirement set called "TableBindings 1.1". The APIs in the [Application specific object models](understanding-the-javascript-api-for-office.md#api-models) are grouped by when they were released for use in production add-ins. Requirement sets are versioned. For example, the APIs that support [Dialog Boxes](../develop/dialog-api-in-office-add-ins.md) are in the requirement set DialogApi 1.1. When additional APIs that enable messaging from a task pane to a dialog were released, they were grouped into DialogApi 1.2, along with all the APIs in DialogApi 1.1. *Each version of a requirement set is a superset of all earlier versions.* @@ -89,18 +92,16 @@ Requirement set support varies by Office application, the version of the Office > [!NOTE] > Some requirement sets also have manifest elements associated with them. See [Specifying requirements in a VersionOverrides element](#specify-requirements-in-a-versionoverrides-element) for information about when this fact is relevant to your add-in design. -#### APIs not in a requirement set - -All APIs in the application specific models are in requirement sets, but some of those in the Common API model are not. There is also a way that you can specify one of these setless APIs in the manifest when your add-in requires one. Details are later in this article. - ### Requirements element -Use the [Requirements](/javascript/api/manifest/requirements) element and its child elements [Sets](/javascript/api/manifest/sets) and [Methods](/javascript/api/manifest/methods) to specify the minimum requirement sets or API members that must be supported by the Office application to install your add-in. +Use the [Requirements](/javascript/api/manifest/requirements) element and its child element [Sets](/javascript/api/manifest/sets) to specify the minimum requirement sets that must be supported by the Office application to install your add-in. + +All APIs in the application specific models are in requirement sets, but some of those in the Common API model are not. Use the [Methods](/javascript/api/manifest/methods) to specify the setless API members that your add-in requires. You can't use the `<Methods>` element with Outlook add-ins. -If the Office application or platform doesn't support the requirement sets or API members specified in the **\<Requirements\>** element, the add-in won't run in that application or platform, and won't display in **My Add-ins**. +If the Office application or platform doesn't support the requirement sets or API members specified in the `<Requirements>` element, the add-in won't run in that application or platform, and won't display in **My Add-ins**. > [!NOTE] -> The **\<Requirements\>** element is optional for all add-ins, except for Outlook add-ins. When the `xsi:type` attribute of the root `OfficeApp` element is `MailApp`, there must be a **\<Requirements\>** element that specifies the minimum version of the Mailbox requirement set that the add-in requires. For more information, see [Outlook JavaScript API requirement sets](/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets). +> The `<Requirements>` element is optional for all add-ins, except for Outlook add-ins. When the `xsi:type` attribute of the root `OfficeApp` element is `MailApp`, there must be a `<Requirements>` element that specifies the minimum version of the Mailbox requirement set that the add-in requires. For more information, see [Outlook JavaScript API requirement sets](/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets). The following code example shows how to configure an add-in that is installable in all Office applications that support the following: @@ -126,11 +127,11 @@ The following code example shows how to configure an add-in that is installable Note the following about this example. -- The **\<Requirements\>** element contains the **\<Sets\>** and **\<Methods\>** child elements. -- The **\<Sets\>** element can contain one or more **\<Set\>** elements. `DefaultMinVersion` specifies the default `MinVersion` value of all child **\<Set\>** elements. -- A [Set](/javascript/api/manifest/set) element specifies a requirement set that the Office application must support to make the add-in installable. The `Name` attribute specifies the name of the requirement set. The `MinVersion` specifies the minimum version of the requirement set. `MinVersion` overrides the value of the `DefaultMinVersion` attribute in the parent **\<Sets\>**. -- The **\<Methods\>** element can contain one or more [Method](/javascript/api/manifest/method) elements. You can't use the **\<Methods\>** element with Outlook add-ins. -- The **\<Method\>** element specifies an individual method that the Office application must support to make the add-in installable. The `Name` attribute is required and specifies the name of the method qualified with its parent object. +- The `<Requirements>` element contains the `<Sets>` and `<Methods>` child elements. +- The `<Sets>` element can contain one or more `<Set>` elements. `DefaultMinVersion` specifies the default `MinVersion` value of all child `<Set>` elements. +- A [Set](/javascript/api/manifest/set) element specifies a requirement set that the Office application must support to make the add-in installable. The `Name` attribute specifies the name of the requirement set. The `MinVersion` specifies the minimum version of the requirement set. `MinVersion` overrides the value of the `DefaultMinVersion` attribute in the parent `<Sets>`. +- The `<Methods>` element can contain one or more [Method](/javascript/api/manifest/method) elements. You can't use the `<Methods>` element with Outlook add-ins. +- The `<Method>` element specifies an individual method that the Office application must support to make the add-in installable. The `Name` attribute is required and specifies the name of the method qualified with its parent object. ## Design for alternate experiences @@ -138,85 +139,24 @@ The extensibility features that the Office Add-in platform provides can be usefu - Extensibility features that are available immediately after the add-in is installed. You can make use of this kind of feature by configuring a [VersionOverrides](/javascript/api/manifest/versionoverrides) element in the manifest. An example of this kind of feature is [Add-in Commands](../design/add-in-commands.md), which are custom ribbon buttons and menus. - Extensibility features that are available only when the add-in is running and that are implemented with Office.js JavaScript APIs; for example, [Dialog Boxes](../develop/dialog-api-in-office-add-ins.md). -- Extensibility features that are available only at runtime but are implemented with a combination of Office.js JavaScript and configuration in a **\<VersionOverrides\>** element. Examples of these are [Excel custom functions](../excel/custom-functions-overview.md), [single sign-on](sso-in-office-add-ins.md), and [custom contextual tabs](../design/contextual-tabs.md). +- Extensibility features that are available only at runtime but are implemented with a combination of Office.js JavaScript and configuration in a `<VersionOverrides>` element. Examples of these are [Excel custom functions](../excel/custom-functions-overview.md), [single sign-on](sso-in-office-add-ins.md), and [custom contextual tabs](../design/contextual-tabs.md). If your add-in uses a specific extensibility feature for some of its functionality but has other useful functionality that doesn't require the extensibility feature, you should design the add-in so that it's installable on platform and Office version combinations that don't support the extensibility feature. It can provide a valuable, albeit diminished, experience on those combinations. You implement this design differently depending on how the extensibility feature is implemented: -- For features implemented entirely with JavaScript, see [Runtime checks for method and requirement set support](#runtime-checks-for-method-and-requirement-set-support). -- For features that require you to configure a **\<VersionOverrides\>** element, see [Specifying requirements in a VersionOverrides element](#specify-requirements-in-a-versionoverrides-element). - -### Runtime checks for method and requirement set support - -You test at runtime to discover whether the user's Office supports a requirement set with the [isSetSupported](/javascript/api/office/office.requirementsetsupport#office-office-requirementsetsupport-issetsupported-member(1)) method. Pass the requirement set's name and the minimum version as parameters. If the requirement set is supported, `isSetSupported` returns `true`. The following code shows an example. - -```js -if (Office.context.requirements.isSetSupported('WordApi', '1.2')) -{ - // Code that uses API members from the WordApi 1.2 requirement set. -} else { - // Provide diminished experience here. E.g., run alternate code when the user's Word is volume-licensed perpetual Word 2016 (which doesn't support WordApi 1.2). -} -``` - -About this code, note: - -- The first parameter is required. It's a string that represents the name of the requirement set. For more information about available requirement sets, see [Office Add-in requirement sets](/javascript/api/requirement-sets/common/office-add-in-requirement-sets). -- The second parameter is optional. It's a string that specifies the minimum requirement set version that the Office application must support in order for the code within the `if` statement to run (e.g., "**1.9**"). If not used, version "1.1" is assumed. - -> [!WARNING] -> When calling the `isSetSupported` method, the value of the second parameter (if specified) should be a string not a number. The JavaScript parser cannot differentiate between numeric values such as 1.1 and 1.10, whereas it can for string values such as "1.1" and "1.10". - -The following table shows the requirement set names for the application specific API models. - -|Office application|RequirementSetName| -|---|---| -|Excel|ExcelApi| -|OneNote|OneNoteApi| -|Outlook|Mailbox| -|PowerPoint|PowerPointApi| -|Word|WordApi| - -The following is an example of using the method with one of the Common API model requirement sets. - -```js -if (Office.context.requirements.isSetSupported('CustomXmlParts')) -{ - // Run code that uses API members from the CustomXmlParts requirement set. -} -else -{ - // Run alternate code when the user's Office application doesn't support the CustomXmlParts requirement set. -} -``` - -> [!NOTE] -> The `isSetSupported` method and the requirement sets for these applications are available in the latest Office.js file on the CDN. If you don't use Office.js from the CDN, your add-in might generate exceptions if you are using an old version of the library in which `isSetSupported` is undefined. For more information, see [Use the latest Office JavaScript API library](#use-the-latest-office-javascript-api-library). - -When your add-in depends on a method that isn't part of a requirement set, use the runtime check to determine whether the method is supported by the Office application, as shown in the following code example. For a complete list of methods that don't belong to a requirement set, see [Office Add-in requirement sets](/javascript/api/requirement-sets/common/office-add-in-requirement-sets#methods-that-arent-part-of-a-requirement-set). - -> [!NOTE] -> We recommend that you limit the use of this type of runtime check in your add-in's code. - -The following code example checks whether the Office application supports `document.setSelectedDataAsync`. - -```js -if (Office.context.document.setSelectedDataAsync) -{ - // Run code that uses `document.setSelectedDataAsync`. -} -``` +- For features implemented entirely with JavaScript, see [Check for API availability at runtime](specify-api-requirements-runtime.md). +- For features that require you to configure a `<VersionOverrides>` element, see [Specifying requirements in a VersionOverrides element](#specify-requirements-in-a-versionoverrides-element). ### Specify requirements in a VersionOverrides element The [VersionOverrides](/javascript/api/manifest/versionoverrides) element was added to the manifest schema primarily, but not exclusively, to support features that must be available immediately after an add-in is installed, such as add-in commands (custom ribbon buttons and menus). Office must know about these features when it parses the add-in manifest. -Suppose your add-in uses one of these features, but the add-in is valuable, and should be installable, even on Office versions that don't support the feature. In this scenario, identify the feature using a [Requirements](/javascript/api/manifest/requirements) element (and its child [Sets](/javascript/api/manifest/sets) and [Methods](/javascript/api/manifest/methods) elements) that you include as a child of the **\<VersionOverrides\>** element itself instead of as a child of the base `OfficeApp` element. The effect of doing this is that Office will allow the add-in to be installed, but Office will ignore certain of the child elements of the **\<VersionOverrides\>** element on Office versions where the feature isn't supported. +Suppose your add-in uses one of these features, but the add-in is valuable, and should be installable, even on Office versions that don't support the feature. In this scenario, identify the feature using a [Requirements](/javascript/api/manifest/requirements) element (and its child [Sets](/javascript/api/manifest/sets) and [Methods](/javascript/api/manifest/methods) elements) that you include as a child of the `<VersionOverrides>` element itself instead of as a child of the base `OfficeApp` element. The effect of doing this is that Office will allow the add-in to be installed, but Office will ignore certain of the child elements of the `<VersionOverrides>` element on Office versions where the feature isn't supported. -Specifically, the child elements of the **\<VersionOverrides\>** that override elements in the base manifest, such as a **\<Hosts\>** element, are ignored and the corresponding elements of the base manifest are used instead. However, there can be child elements in a **\<VersionOverrides\>** that actually implement additional features rather than override settings in the base manifest. Two examples are the `WebApplicationInfo` and `EquivalentAddins`. These parts of the **\<VersionOverrides\>** will *not* be ignored, assuming the platform and version of Office support the corresponding feature. +Specifically, the child elements of the `<VersionOverrides>` that override elements in the base manifest, such as a `<Hosts>` element, are ignored and the corresponding elements of the base manifest are used instead. However, there can be child elements in a `<VersionOverrides>` that actually implement additional features rather than override settings in the base manifest. Two examples are the `WebApplicationInfo` and `EquivalentAddins`. These parts of the `<VersionOverrides>` will *not* be ignored, assuming the platform and version of Office support the corresponding feature. -For information about the descendent elements of the **\<Requirements\>** element, see [Requirements element](#requirements-element) earlier in this article. +For information about the descendent elements of the `<Requirements>` element, see [Requirements element](#requirements-element) earlier in this article. The following is an example. @@ -240,10 +180,10 @@ The following is an example. ``` > [!WARNING] -> Use great care before including a **\<Requirements\>** element in a **\<VersionOverrides\>**, because on platform and version combinations that don't support the requirement, *none* of the add-in commands will be installed, *even those that invoke functionality that doesn't need the requirement*. Consider, for example, an add-in that has two custom ribbon buttons. One of them calls Office JavaScript APIs that are available in requirement set **ExcelApi 1.4** (and later). The other calls APIs that are only available in **ExcelApi 1.9** (and later). If you put a requirement for **ExcelApi 1.9** in the **\<VersionOverrides\>**, then when 1.9 is not supported *neither* button will appear on the ribbon. A better strategy in this scenario would be to use the technique described in [Runtime checks for method and requirement set support](#runtime-checks-for-method-and-requirement-set-support). The code invoked by the second button first uses `isSetSupported` to check for support of **ExcelApi 1.9**. If it isn't supported, the code gives the user a message saying that this feature of the add-in is not available on their version of Office. +> If your add-in includes [add-in commands](../design/add-in-commands.md), use great care before including a `<Requirements>` element in a `<VersionOverrides>`. On platform and version combinations that don't support the requirement, *none* of the add-in commands will be installed, *even those that invoke functionality that doesn't need the requirement*. Consider, for example, an add-in that has two custom ribbon buttons. One of them calls Office JavaScript APIs that are available in requirement set **ExcelApi 1.4** (and later). The other calls APIs that are only available in **ExcelApi 1.9** (and later). If you put a requirement for **ExcelApi 1.9** in the `<VersionOverrides>`, then when 1.9 isn't supported, *neither* button will appear on the ribbon. A better strategy in this scenario would be to use the technique described in [Check for API availability at runtime](specify-api-requirements-runtime.md). The code invoked by the second button first uses `isSetSupported` to check for support of **ExcelApi 1.9**. If it isn't supported, the code gives the user a message saying that this feature of the add-in isn't available on their version of Office. > [!TIP] -> There's no point to repeating a **Requirement** element in a **\<VersionOverrides\>** that already appears in the base manifest. If the requirement is specified in the base manifest, then the add-in can't install where the requirement isn't supported so Office doesn't even parse the **\<VersionOverrides\>** element. +> There's no point to repeating a `<Requirement>` element in a `<VersionOverrides>` that already appears in the base manifest. If the requirement is specified in the base manifest, then the add-in can't install where the requirement isn't supported so Office doesn't even parse the `<VersionOverrides>` element. ## See also diff --git a/docs/develop/sso-in-office-add-ins.md b/docs/develop/sso-in-office-add-ins.md index f61490fb76..e627b43cef 100644 --- a/docs/develop/sso-in-office-add-ins.md +++ b/docs/develop/sso-in-office-add-ins.md @@ -1,4 +1,4 @@ ---- +--- title: Enable single sign-on (SSO) in an Office Add-in description: Learn the key steps to enable single sign-on (SSO) for your Office Add-in using common Microsoft personal, work, or education accounts. ms.date: 05/06/2024 @@ -69,30 +69,29 @@ For more details about this process, see [Register an Office Add-in that uses SS ### Configure the add-in -Your manifest must provide Office with certain information about how the add-in is registered in Microsoft Entra ID. The configuration depends on which type of manifest the add-in uses. +Your manifest must provide Office with certain information about how the add-in is registered in Microsoft Entra ID. The configuration depends on which type of manifest the add-in uses. # [Unified manifest](#tab/jsonmanifest) -There should be a "webApplicationInfo" property in the root of the manifest. It has a required child "id" property which must be set to the application ID (a GUID) of the add-in in the Microsoft identity platform. For SSO, it must also have a child "resource" property that is set to the URI of the add-in. This is the same **Application ID URI** (including the `api:` protocol) that you set when you registered the add-in with the Microsoft identity platform. The URI must end with the client ID specified in the "webApplicationInfo.id" property. The following is an example: +There should be a [`"webApplicationInfo"`](/microsoft-365/extensibility/schema/root#webApplicationInfo-property) property in the root of the manifest. It has a required child `"id"` property which must be set to the application ID (a GUID) of the add-in in the Microsoft identity platform. For SSO, it must also have a child `"resource"` property that is set to the URI of the add-in. This is the same **Application ID URI** (including the `api:` protocol) that you set when you registered the add-in with the Microsoft identity platform. The URI must end with the client ID specified in the `"webApplicationInfo.id"` property. The following is an example: ```json "webApplicationInfo": { - "id": "a661fed9-f33d-4e95-b6cf-624a34a2f51d", - "resource": "api://addin.contoso.com/a661fed9-f33d-4e95-b6cf-624a34a2f51d" + "id": "a661fed9-f33d-4e95-b6cf-624a34a2f51d", + "resource": "api://addin.contoso.com/a661fed9-f33d-4e95-b6cf-624a34a2f51d" }, ``` > [!NOTE] -> Experienced add-in developers should note that, there is no unified manifest property corresponding to the **\<Scopes\>** element in the add-in only manifest. Microsoft Graph and other API permissions are requested at runtime in your code. - +> Experienced add-in developers should note that, there is no unified manifest property corresponding to the `<Scopes>` element in the add-in only manifest. Microsoft Graph and other API permissions are requested at runtime in your code. # [Add-in only manifest](#tab/xmlmanifest) -- **\<WebApplicationInfo\>** - The parent of the following elements. -- **\<Id\>** - The application (client) ID you received when you registered the add-in with the Microsoft identity platform. For more information, see [Register an Office Add-in that uses SSO with the Microsoft identity platform](register-sso-add-in-aad-v2.md). -- **\<Resource\>** - The URI of the add-in. This is the same URI (including the `api:` protocol) that you used when registering the add-in with the Microsoft identity platform. The domain part of this URI must match the domain, including any subdomains, used in the URLs in the **\<Resources\>** section of the add-in's manifest and the URI must end with the client ID specified in the **\<Id\>** element. -- **\<Scopes\>** - The parent of one or more **\<Scope\>** elements. -- **\<Scope\>** - Specifies a permission that the add-in needs. The `profile` and `openID` permissions are always needed and may be the only permissions needed. If your add-in needs access to Microsoft Graph or other Microsoft 365 resources, you'll need additional **\<Scope\>** elements. For example, for Microsoft Graph permissions you might request the `User.Read` and `Mail.Read` scopes. Libraries that you use in your code to access Microsoft Graph may need additional permissions. For more information, see [Authorize to Microsoft Graph from an Office Add-in](authorize-to-microsoft-graph.md). +- `<WebApplicationInfo>` - The parent of the following elements. +- `<Id>` - The application (client) ID you received when you registered the add-in with the Microsoft identity platform. For more information, see [Register an Office Add-in that uses SSO with the Microsoft identity platform](register-sso-add-in-aad-v2.md). +- `<Resource>` - The URI of the add-in. This is the same URI (including the `api:` protocol) that you used when registering the add-in with the Microsoft identity platform. The domain part of this URI must match the domain, including any subdomains, used in the URLs in the `<Resources>` section of the add-in's manifest and the URI must end with the client ID specified in the `<Id>` element. +- `<Scopes>` - The parent of one or more `<Scope>` elements. +- `<Scope>` - Specifies a permission that the add-in needs. The `profile` and `openID` permissions are always needed and may be the only permissions needed. If your add-in needs access to Microsoft Graph or other Microsoft 365 resources, you'll need additional `<Scope>` elements. For example, for Microsoft Graph permissions you might request the `User.Read` and `Mail.Read` scopes. Libraries that you use in your code to access Microsoft Graph may need additional permissions. For more information, see [Authorize to Microsoft Graph from an Office Add-in](authorize-to-microsoft-graph.md). For Word, Excel, and PowerPoint add-ins, add the markup to the end of the `<VersionOverrides ... xsi:type="VersionOverridesV1_0">` section. For Outlook add-ins, add the markup to the end of the `<VersionOverrides ... xsi:type="VersionOverridesV1_1">` section. @@ -115,7 +114,7 @@ The following is an example of the markup. > If your add-in is deployed by one or more admins to their organizations, adding new scopes to the manifest will require the admin to consent to the updates. Users will be blocked from the add-in until consent is granted. > [!NOTE] -> If you don't follow the format requirements in the manifest for SSO, your add-in will be rejected from AppSource until it meets the required format. +> If you don't follow the format requirements in the manifest for SSO, your add-in will be rejected from Microsoft Marketplace until it meets the required format. --- diff --git a/docs/develop/support-for-task-pane-and-content-add-ins.md b/docs/develop/support-for-task-pane-and-content-add-ins.md index 0c51bd26cd..8fc9bb3e71 100644 --- a/docs/develop/support-for-task-pane-and-content-add-ins.md +++ b/docs/develop/support-for-task-pane-and-content-add-ins.md @@ -1,7 +1,7 @@ --- title: Office JavaScript API support for content and task pane add-ins description: Use the Office JavaScript API to create a task pane or content add-in. -ms.date: 03/21/2023 +ms.date: 02/12/2025 ms.localizationpriority: medium --- @@ -88,9 +88,9 @@ For more details and examples, see [Bind to regions in a document or spreadsheet If your task pane add-in runs in PowerPoint or Word, you can use the [Document.getFileAsync](/javascript/api/office/office.document#office-office-document-getfileasync-member(1)), [File.getSliceAsync](/javascript/api/office/office.file#office-office-file-getsliceasync-member(1)), and [File.closeAsync](/javascript/api/office/office.file#office-office-file-closeasync-member(1)) methods to get an entire presentation or document. -When you call `Document.getFileAsync` you get a copy of the document in a [File](/javascript/api/office/office.file) object. The `File` object provides access to the document in "chunks" represented as [Slice](/javascript/api/office/office.slice) objects. When you call `getFileAsync`, you can specify the file type (text or compressed Open Office XML format), and size of the slices (up to 4MB). To access the contents of the `File` object, you then call `File.getSliceAsync` which returns the raw data in the [Slice.data](/javascript/api/office/office.slice#office-office-slice-data-member) property. If you specified compressed format, you will get the file data as a byte array. If you are transmitting the file to a web service, you can transform the compressed raw data to a base64-encoded string before submission. Finally, when you are finished getting slices of the file, use the `File.closeAsync` method to close the document. +When you call `Document.getFileAsync` you get a copy of the document in a [File](/javascript/api/office/office.file) object. The `File` object provides access to the document in "chunks" represented as [Slice](/javascript/api/office/office.slice) objects. When you call `getFileAsync`, you can specify the file type (text or compressed Open Office XML format), and size of the slices (up to 4MB). To access the contents of the `File` object, you then call `File.getSliceAsync` which returns the raw data in the [Slice.data](/javascript/api/office/office.slice#office-office-slice-data-member) property. If you specified compressed format, you will get the file data as a byte array. If you are transmitting the file to a web service, you can transform the compressed raw data to a Base64-encoded string before submission. Finally, when you are finished getting slices of the file, use the `File.closeAsync` method to close the document. -For more details, see how to [get the whole document from an add-in for PowerPoint or Word](../word/get-the-whole-document-from-an-add-in-for-word.md). +For more details, see how to [get the whole document from an add-in for PowerPoint or Word](../develop/get-the-whole-document-from-an-add-in-for-powerpoint-or-word.md). ## Read and write custom XML parts of a Word document @@ -120,19 +120,38 @@ For more details about working with custom data using the methods of the `Settin ## Permissions model and governance -Your add-in uses the `Permissions` element in its manifest to request permission to access the level of functionality it requires from the Office JavaScript API. For example, if your add-in requires read/write access to the document, its manifest must specify `ReadWriteDocument` as the text value in its `Permissions` element. Because permissions exist to protect a user's privacy and security, as a best practice you should request the minimum level of permissions it needs for its features. The following example shows how to request the **ReadDocument** permission in a task pane's manifest. - -```XML -<?xml version="1.0" encoding="utf-8"?> -<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:type="TaskPaneApp"> -???<!-- Other manifest elements omitted. --> - <Permissions>ReadDocument</Permissions> -??? -</OfficeApp> - -``` +Your add-in uses the app manifest to request permission to access the level of functionality it requires from the Office JavaScript API. The method varies depending on the type of manifest. + +- **Unified manifest for Microsoft 365**: Use the [`"authorization.permissions.resourceSpecific"`](/microsoft-365/extensibility/schema/root-authorization-permissions#resourcespecific) property. For example, if your add-in requires read/write access to the document, its manifest must specify `Document.ReadWrite.User` as the value in its `"authorization.permissions.resourceSpecific.name"` property. The following example requests the **read document** permission, which allows only methods that can read (but not write to) the document. + + ```json + "authorization": { + "permissions": { + "resourceSpecific": [ + ... + { + "name": "Document.Read.User", + "type": "Delegated" + }, + ] + } + }, + ``` + + [!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] + +- **Add-in only manifest**: Use the `Permissions` element in the manifest For example, if your add-in requires read/write access to the document, its manifest must specify `ReadWriteDocument` as the text value in its `Permissions` element. Because permissions exist to protect a user's privacy and security, as a best practice you should request the minimum level of permissions it needs for its features. The following example shows how to request the **read document** permission in a task pane's manifest. + + ```XML + <?xml version="1.0" encoding="utf-8"?> + <OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:type="TaskPaneApp"> + <!-- Other manifest elements omitted. --> + <Permissions>ReadDocument</Permissions> + ... + </OfficeApp> + ``` For more information, see [Requesting permissions for API use in add-ins](requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md). diff --git a/docs/develop/support-ie-11.md b/docs/develop/support-ie-11.md index 63088bc438..fe1f8be134 100644 --- a/docs/develop/support-ie-11.md +++ b/docs/develop/support-ie-11.md @@ -1,7 +1,7 @@ ---- +--- title: Support older Microsoft webviews and Office versions description: Learn how to support support older Microsoft webviews and Office versions in your add-in. -ms.date: 04/04/2024 +ms.date: 01/07/2025 ms.localizationpriority: medium --- @@ -16,8 +16,8 @@ Office Add-ins are web applications that are displayed inside iframes when runni > > We recommend (but don't require) that you support these combinations, at least in a minimal way, by providing users of your add-in a graceful failure message when your add-in is launched in these webviews. Keep these additional points in mind: > -> - Office on the web no longer opens in Internet Explorer or Microsoft Edge Legacy. Consequently, [AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center) doesn't test add-ins in Office on the web on these browsers. -> - AppSource still tests for combinations of platform and Office *desktop* versions that use Trident or EdgeHTML. However, it only issues a warning when the add-in doesn't support these webviews; the add-in isn't rejected by AppSource. +> - Office on the web no longer opens in Internet Explorer or Microsoft Edge Legacy. Consequently, [Microsoft Marketplace](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center) doesn't test add-ins in Office on the web on these browsers. +> - Microsoft Marketplace still tests for combinations of platform and Office *desktop* versions that use Trident or EdgeHTML. However, it only issues a warning when the add-in doesn't support these webviews; the add-in isn't rejected by Microsoft Marketplace. > - The [Script Lab tool](../overview/explore-with-script-lab.md) no longer supports Trident. If you plan to support older versions of Windows and Office, your add-in must work in the embeddable browser controls used by these versions. For example, browser controls based on Internet Explorer 11 (IE11) or Microsoft Edge Legacy (EdgeHTML-based). For information about which combinations of Windows and Office use these browser controls, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). @@ -70,7 +70,7 @@ This JavaScript should be as early in the add-in startup process as possible. Th <title>Contoso Task Pane Add-in - + diff --git a/docs/develop/teams-toolkit-overview.md b/docs/develop/teams-toolkit-overview.md deleted file mode 100644 index 70fbefed84..0000000000 --- a/docs/develop/teams-toolkit-overview.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Create Office Add-in projects using Teams Toolkit -description: Learn how to create Office Add-in projects using Teams Toolkit. -ms.date: 04/12/2024 -ms.localizationpriority: high ---- - -# Create Office Add-in projects with Teams Toolkit - -A primary tool for developing Teams Apps is Teams Toolkit. You can create Office Add-ins with Teams Toolkit, with the following restrictions. - -- Add-ins created with Teams Toolkit use the [unified manifest for Microsoft 365](unified-manifest-overview.md). -- Only Outlook add-ins can be created at this time. We're working hard to enable support in Teams Toolkit for add-ins to other Office applications and platforms. - - [!INCLUDE [non-unified manifest clients note](../includes/non-unified-manifest-clients.md)] - -Install the latest version of Teams Toolkit into Visual Studio Code as described in [Install Teams Toolkit](/microsoftteams/platform/toolkit/install-teams-toolkit?tabs=vscode). - -## Create an Outlook Add-in project - -1. Open Visual Studio Code and select Teams Toolkit icon in the **Activity Bar**. - - :::image type="content" source="../images/teams-toolkit-icon.png" alt-text="Teams Toolkit icon."::: - -1. Select **Create a new app**. -1. In the **New Project** drop down, select **Outlook add-in**. - - :::image type="content" source="../images/teams-toolkit-create-outlook-add-in.png" alt-text="The four options in New Project drop down. The fourth option is called 'Outlook add-in'."::: - -1. In the **App Features Using an Outlook Add-in** drop down, select **Taskpane**. - - :::image type="content" source="../images/teams-toolkit-create-outlook-task-pane-capability.png" alt-text="The two options in the App Features Using an Outlook Add-in drop down. The first option 'Taskpane' is selected."::: - -1. In the **Workspace folder** dialog that opens, select the folder where you want to create the project. -1. Give a name to the project (with no spaces) when prompted. Teams Toolkit will create the project with basic files and scaffolding. It will then open the project *in a second Visual Studio Code window*. Close the original Visual Studio Code window. -1. In the Visual Studio Code **TERMINAL** navigate to the root of the project and run `npm install`. -1. Before you make changes to the project, verify that you can sideload your Outlook add-in from Visual Studio Code. Use the following steps: - 1. Ensure that your account in your Microsoft 365 developer tenancy is also an email account in desktop Outlook. If it isn't, follow the guidance in [Add an email account to Outlook](https://support.microsoft.com/office/add-an-email-account-to-outlook-e9da47c4-9b89-4b49-b945-a204aeea6726). - 1. **Close Outlook desktop**. - 1. In Visual Studio Code, open Teams Toolkit. - 1. In the **ACCOUNTS** section, verify that you're signed into Microsoft 365. - 1. Select **View** | **Run** in Visual Studio Code. In the **RUN AND DEBUG** drop down menu, select the option, **Outlook Desktop (Edge Chromium)**, and then press F5. The project builds and a Node dev-server window opens. This process may take a couple of minutes. Eventually, Outlook desktop will open. - 1. Open the **Inbox** *of your Microsoft 365 account identity* and open any message. A **Contoso Add-in** tab with two buttons will appear on the **Home** ribbon (or the **Message** ribbon, if you have opened the message in its own window). - 1. Click the **Show Taskpane** button and a task pane opens. Click the **Perform an action** button and a small notification appears near the top of the message. - 1. To stop debugging and uninstall the add-in, select **Run** | **Stop Debugging** in Visual Studio Code. - -Now you can change and develop the project. In places where the guidance in the Office Add-ins documentation branches depending on what type of manifest is being used, be sure to follow the guidance for the unified manifest. diff --git a/docs/develop/troubleshoot-sso-in-office-add-ins.md b/docs/develop/troubleshoot-sso-in-office-add-ins.md index 92653f51d1..621eeb4a4f 100644 --- a/docs/develop/troubleshoot-sso-in-office-add-ins.md +++ b/docs/develop/troubleshoot-sso-in-office-add-ins.md @@ -1,7 +1,7 @@ ---- +--- title: Troubleshoot error messages for single sign-on (SSO) description: Guidance about how to troubleshoot problems with single sign-on (SSO) in Office Add-ins, and handle special conditions or errors. -ms.date: 07/08/2024 +ms.date: 06/24/2025 ms.localizationpriority: medium --- @@ -30,7 +30,7 @@ For examples of the error handling described in this section, see: ### 13000 -The [getAccessToken](/javascript/api/office-runtime/officeruntime.auth#office-runtime-officeruntime-auth-getaccesstoken-member(1)) API is not supported by the add-in or the Office version. +The [getAccessToken](/javascript/api/office-runtime/officeruntime.auth#office-runtime-officeruntime-auth-getaccesstoken-member(1)) API isn't supported by the add-in or the Office version. - The version of Office does not support SSO. The required version is Microsoft 365 subscription, in any monthly channel. - The add-in manifest is missing the proper [WebApplicationInfo](/javascript/api/manifest/webapplicationinfo) section. @@ -39,13 +39,13 @@ Your add-in should respond to this error by falling back to an alternate system ### 13001 -The user is not signed into Office. In most scenarios, you should prevent this error from ever being seen by passing the option `allowSignInPrompt: true` in the `AuthOptions` parameter. +The user isn't signed into Office. In most scenarios, you should prevent this error from ever being seen by passing the option `allowSignInPrompt: true` in the `AuthOptions` parameter. -But there may be exceptions. For example, you want the add-in to open with features that require a logged in user; but *only if* the user is *already* logged into Office. If the user is not, you want the add-in to open with an alternate set of features that do not require that the user is signed in. In this case, logic which runs when the add-in launches calls `getAccessToken` without `allowSignInPrompt: true`. Use the 13001 error as the flag to tell the add-in to present the alternate set of features. +But there may be exceptions. For example, you want the add-in to open with features that require a logged in user; but *only if* the user is *already* logged into Office. If the user isn't logged in, you want the add-in to open with an alternate set of features that do not require that the user is signed in. In this case, logic which runs when the add-in launches calls `getAccessToken` without `allowSignInPrompt: true`. Use the 13001 error as the flag to tell the add-in to present the alternate set of features. -Another option is to respond to 13001 by falling back to an alternate system of user authentication. This will sign the user into AAD, but not sign the user into Office. +Another option is to respond to 13001 by falling back to an alternate system of user authentication. This will sign the user into Microsoft Entra ID, but not sign the user into Office. -This error is never seen in **Office on the web**. If the user's cookie expires, **Office on the web** returns error 13006. +This error doesn't typically occur in Office on the web. If the user's cookie expires, Office on the web returns [error 13006](#13006). However, if a user accesses Outlook on the web from Firefox with Enhanced Tracking Protection turned on, they'll encounter error 13001. ### 13002 @@ -60,11 +60,11 @@ User Type not supported. The user isn't signed into Office with a valid Microsof ### 13004 -Invalid Resource. (This error should only be seen in development.) The add-in manifest hasn't been configured correctly. Update the manifest. For more information, see [Validate an Office Add-in's manifest](../testing/troubleshoot-manifest.md). The most common problem is that the **\** element (in the **\** element) has a domain that does not match the domain of the add-in. Although the protocol part of the Resource value should be "api" not "https"; all other parts of the domain name (including port, if any) should be the same as for the add-in. +Invalid Resource. (This error should only be seen in development.) The add-in manifest hasn't been configured correctly. Update the manifest. For more information, see [Validate an Office Add-in's manifest](../testing/troubleshoot-manifest.md). The most common problem is that the `` element (in the `` element) has a domain that does not match the domain of the add-in. Although the protocol part of the Resource value should be "api" not "https"; all other parts of the domain name (including port, if any) should be the same as for the add-in. ### 13005 -Invalid Grant. This usually means that Office has not been pre-authorized to the add-in's web service. For more information, see [Create the service application](sso-in-office-add-ins.md#register-your-add-in-with-the-microsoft-identity-platform) and [Register the add-in with Azure AD v2.0 endpoint](register-sso-add-in-aad-v2.md). This also may happen if the user has not granted your service application permissions to their `profile`, or has revoked consent. Your code should fall back to an alternate system of user authentication. +Invalid Grant. This usually means that Office has not been pre-authorized to the add-in's web service. For more information, see [Create the service application](sso-in-office-add-ins.md#register-your-add-in-with-the-microsoft-identity-platform) and [Register an Office Add-in that uses single sign-on (SSO) with the Microsoft identity platform](register-sso-add-in-aad-v2.md). This also may happen if the user has not granted your service application permissions to their `profile`, or has revoked consent. Your code should fall back to an alternate system of user authentication. Another possible cause, during development, is that your add-in using Internet Explorer, and you are using a self-signed certificate. (To determine which browser or webview is being used by the add-in, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md).) @@ -76,8 +76,15 @@ Client Error. This error is only seen in **Office on the web**. Your code should The Office application was unable to get an access token to the add-in's web service. -- If this error occurs during development, be sure that your add-in registration and add-in manifest specify the `profile` permission (and the `openid` permission, if you are using MSAL.NET). For more information, see [Register the add-in with Azure AD v2.0 endpoint](register-sso-add-in-aad-v2.md). -- In production, an account mismatch could cause this error. For example, if the user attempts to sign in with a personal Microsoft account (MSA) when a Work or school account was expected. For these cases, your code should fall back to an alternate system of user authentication. For more information on account types, see [Identity and account types for single- and multi-tenant apps](/security/zero-trust/develop/identity-supported-account-types) +- If this error occurs during development, be sure that your add-in registration and add-in manifest specify the `profile` permission (and the `openid` permission, if you are using MSAL.NET). For more information, see [Register an Office Add-in that uses single sign-on (SSO) with the Microsoft identity platform](register-sso-add-in-aad-v2.md). +- In production, an account mismatch could cause this error. For example, if the user attempts to sign in with a personal Microsoft account (MSA) when a Work or school account was expected. For these cases, your code should fall back to an alternate system of user authentication. For more information on account types, see [Identity and account types for single- and multi-tenant apps](/security/zero-trust/develop/identity-supported-account-types). +- Make sure your application is enabled for users to sign-in for your organization. + 1. Sign in to the [Microsoft Azure portal](https://portal.azure.com/). + 1. Go to your add-in's app registration. + 1. On the **Overview** page, select **Managed application in local directory**. + :::image type="content" source="../images/azure-portal-managed-application.png" alt-text="The Managed application in local directory option in the App Registration Overview window."::: + 1. Select **Manage** > **Properties**, and ensure that the value of **Enabled for users to sign-in?** is **Yes**. + :::image type="content" source="../images/azure-portal-enable-sign-in.png" alt-text="The option to allow users in the organization to sign-in to an application in the Properties window."::: ### 13008 @@ -91,9 +98,9 @@ The user is running the add-in in Office on Microsoft Edge. The user's Microsoft There are several possible causes. -- The add-in is running on a platform that does not support the `getAccessToken` API. For example, it is not supported on iPad. See also [Identity API requirement sets](/javascript/api/requirement-sets/common/identity-api-requirement-sets). +- The add-in is running on a platform that does not support the `getAccessToken` API. For example, it isn't supported on iPad. See also [Identity API requirement sets](/javascript/api/requirement-sets/common/identity-api-requirement-sets). - The Office document was opened from the **Files** tab of a Teams channel using the **Edit in Teams** option on the **Open** dropdown menu. The `getAccessToken` API isn't supported in this scenario. -- The `forMSGraphAccess` option was passed in the call to `getAccessToken` and the user obtained the add-in from AppSource. In this scenario, the tenant admin has not granted consent to the add-in for the Microsoft Graph scopes (permissions) that it needs. Recalling `getAccessToken` with the `allowConsentPrompt` will not solve the problem because Office is allowed to prompt the user for consent to only the AAD `profile` scope. +- The `forMSGraphAccess` option was passed in the call to `getAccessToken` and the user obtained the add-in from Microsoft Marketplace. In this scenario, the tenant admin has not granted consent to the add-in for the Microsoft Graph scopes (permissions) that it needs. Recalling `getAccessToken` with the `allowConsentPrompt` will not solve the problem because Office is allowed to prompt the user for consent to only the Microsoft Entra ID `profile` scope. Your code should fall back to an alternate system of user authentication. @@ -101,15 +108,15 @@ In development, the add-in is sideloaded in Outlook and the `forMSGraphAccess` o ### 13013 -The `getAccessToken` was called too many times in a short amount of time, so Office throttled the most recent call. This is usually caused by an infinite loop of calls to the method. There are scenarios when recalling the method is advisable. However, your code should use a counter or flag variable to ensure that the method is not recalled repeatedly. If the same "retry" code path is running again, the code should fall back to an alternate system of user authentication. For a code example, see how the `retryGetAccessToken` variable is used in [HomeES6.js](https://github.com/OfficeDev/Office-Add-in-samples/blob/main/Samples/auth/Office-Add-in-ASPNET-SSO/Complete/Office-Add-in-ASPNETCore-WebAPI/wwwroot/js/HomeES6.js) or [ssoAuthES6.js](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Office-Add-in-NodeJS-SSO/Complete/public/javascripts/ssoAuthES6.js). +The `getAccessToken` was called too many times in a short amount of time, so Office throttled the most recent call. This is usually caused by an infinite loop of calls to the method. There are scenarios when recalling the method is advisable. However, your code should use a counter or flag variable to ensure that the method isn't recalled repeatedly. If the same "retry" code path is running again, the code should fall back to an alternate system of user authentication. For a code example, see how the `retryGetAccessToken` variable is used in [HomeES6.js](https://github.com/OfficeDev/Office-Add-in-samples/blob/main/Samples/auth/Office-Add-in-ASPNET-SSO/Complete/Office-Add-in-ASPNETCore-WebAPI/wwwroot/js/HomeES6.js) or [ssoAuthES6.js](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/auth/Office-Add-in-NodeJS-SSO/Complete/public/javascripts/ssoAuthES6.js). ### 50001 -This error (which is not specific to `getAccessToken`) may indicate that the browser has cached an old copy of the office.js files. When you are developing, clear the browser's cache. Another possibility is that the version of Office is not recent enough to support SSO. On Windows, the minimum build is 16.0.12215.20006. On Mac, it's 16.32.19102902. +This error (which isn't specific to `getAccessToken`) may indicate that the browser has cached an old copy of the office.js files. When you're developing, clear the browser's cache. Another possibility is that the version of Office isn't recent enough to support SSO. On Windows, the minimum version is Version 1911 (Build 12215.20006). On Mac, it's Version 16.32 (19102902). In a production add-in, the add-in should respond to this error by falling back to an alternate system of user authentication. For more information, see [Requirements and Best Practices](../develop/sso-in-office-add-ins.md#requirements-and-best-practices). -## Errors on the server-side from Azure Active Directory +## Errors on the server-side from Microsoft Entra ID For samples of the error-handling described in this section, see: @@ -118,15 +125,15 @@ For samples of the error-handling described in this section, see: ### Conditional access / Multifactor authentication errors -In certain configurations of identity in AAD and Microsoft 365, it is possible for some resources that are accessible with Microsoft Graph to require multifactor authentication (MFA), even when the user's Microsoft 365 tenancy does not. When AAD receives a request for a token to the MFA-protected resource, via the on-behalf-of flow, it returns to your add-in's web service a JSON message that contains a `claims` property. The claims property has information about what further authentication factors are needed. +In certain configurations of identity in Microsoft Entra ID and Microsoft 365, it is possible for some resources that are accessible with Microsoft Graph to require multifactor authentication (MFA), even when the user's Microsoft 365 tenancy does not. When Microsoft Entra ID receives a request for a token to the MFA-protected resource, via the on-behalf-of flow, it returns to your add-in's web service a JSON message that contains a `claims` property. The claims property has information about what further authentication factors are needed. Your code should test for this `claims` property. Depending on your add-in's architecture, you may test for it on the client-side, or you may test for it on the server-side and relay it to the client. You need this information in the client because Office handles authentication for SSO add-ins. If you relay it from the server-side, the message to the client can be either an error (such as `500 Server Error` or `401 Unauthorized`) or in the body of a success response (such as `200 OK`). In either case, the (failure or success) callback of your code's client-side AJAX call to your add-in's web API should test for this response. -Regardless of your architecture, if the claims value has been sent from AAD, your code should recall `getAccessToken` and pass the option `authChallenge: CLAIMS-STRING-HERE` in the `options` parameter. When AAD sees this string, it prompts the user for the additional factors and then returns a new access token which will be accepted in the on-behalf-of flow. +Regardless of your architecture, if the claims value has been sent from Microsoft Entra ID, your code should recall `getAccessToken` and pass the option `authChallenge: CLAIMS-STRING-HERE` in the `options` parameter. When Microsoft Entra ID sees this string, it prompts the user for the additional factors and then returns a new access token which will be accepted in the on-behalf-of flow. ### Consent missing errors -If AAD has no record that consent (to the Microsoft Graph resource) was granted to the add-in by the user (or tenant administrator), AAD will send an error message to your web service. Your code must tell the client (in the body of a `403 Forbidden` response, for example). +If Microsoft Entra ID has no record that consent (to the Microsoft Graph resource) was granted to the add-in by the user (or tenant administrator), Microsoft Entra ID will send an error message to your web service. Your code must tell the client (in the body of a `403 Forbidden` response, for example). If the add-in needs Microsoft Graph scopes that can only be consented to by an admin, your code should throw an error. If the only scopes that are needed can be consented to by the user, then your code should fall back to an alternate system of user authentication. @@ -135,7 +142,7 @@ If the add-in needs Microsoft Graph scopes that can only be consented to by an a This kind of error should only be seen in development. - Your server-side code should send a `403 Forbidden` response to the client which should log the error to the console or record it in a log. -- Be sure your add-in manifest [Scopes](/javascript/api/manifest/scopes) section specifies all needed permissions. And be sure your registration of the add-in's web service specifies the same permissions. Check for spelling mistakes too. For more information, see [Register the add-in with Azure AD v2.0 endpoint](register-sso-add-in-aad-v2.md). +- Be sure your add-in manifest [Scopes](/javascript/api/manifest/scopes) section specifies all needed permissions. And be sure your registration of the add-in's web service specifies the same permissions. Check for spelling mistakes too. For more information, see [Register an Office Add-in that uses single sign-on (SSO) with the Microsoft identity platform](register-sso-add-in-aad-v2.md). ### Invalid audience error in the access token for Microsoft Graph diff --git a/docs/develop/trusted-domains.md b/docs/develop/trusted-domains.md index e85886ea87..7cc7bd074f 100644 --- a/docs/develop/trusted-domains.md +++ b/docs/develop/trusted-domains.md @@ -1,13 +1,13 @@ --- title: Wildcard trusted domains description: Learn how to use wildcards to specify trusted domains that aren't listed in the manifest. -ms.date: 11/14/2023 +ms.date: 10/10/2025 ms.localizationpriority: medium --- # Wildcard trusted domains -Besides its own domain, an add-in can access resources in certain other domains such as authentication points for major identity providers and in any domain listed in the manifest. The latter domains are specified in the [AppDomains](/javascript/api/manifest/appdomains) element of the add-in only manifest or the [validDomains](/microsoftteams/platform/resources/schema/manifest-schema-dev-preview#validdomains) property of the unified manifest. Wildcards aren't allowed in the add-in only manifest. They are allowed in the unified manifest because some Teams apps and other Microsoft 365 apps honor them; but Office Add-ins don't honor "validDomains" that contain wildcards. +Besides its own domain, an add-in can access resources in certain other domains such as authentication points for major identity providers and in any domain listed in the manifest. The latter domains are specified in the [AppDomains](/javascript/api/manifest/appdomains) element of the add-in only manifest or the [`"validDomains`"](/microsoft-365/extensibility/schema/root#validdomains) property of the unified manifest. Wildcards aren't allowed in the add-in only manifest. They are allowed in the unified manifest because some Apps for Microsoft 365, including Teams apps, honor them; but Office Add-ins don't honor `"validDomains"` that contain wildcards. Windows administrators can make Office Add-ins, *running on Windows only*, honor domains that include a wildcard by setting the **HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\AllowedAppDomains** registry key with the domain. The following is an example. diff --git a/docs/develop/unified-manifest-overview.md b/docs/develop/unified-manifest-overview.md index 513daa6768..b12b395ecf 100644 --- a/docs/develop/unified-manifest-overview.md +++ b/docs/develop/unified-manifest-overview.md @@ -1,8 +1,8 @@ ---- +--- title: Office Add-ins with the unified app manifest for Microsoft 365 description: Get an overview of the unified app manifest for Microsoft 365 for Office Add-ins and its uses. ms.topic: overview -ms.date: 09/09/2024 +ms.date: 10/10/2025 ms.localizationpriority: high --- @@ -21,61 +21,80 @@ One important improvement is the ability to create a single unit of distribution We've taken an important first step toward these goals by making it possible for you to create Outlook add-ins with a unified manifest for Microsoft 365. -> [!NOTE] -> -> - The unified manifest currently only supports Outlook add-ins and only in Office linked to a Microsoft 365 subscription and installed on Windows, on a mobile device, or in Outlook on the web. We're working on extending support to Excel, PowerPoint, and Word, as well as to Outlook on Mac, and to perpetual versions of Office. -> - The unified manifest requires Office Version 2304 (Build 16320.00000) or later. +[!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] > [!TIP] > Ready to get started with the unified manifest? Begin with [Build an Outlook add-in with the unified manifest for Microsoft 365](../quickstarts/outlook-quickstart-json-manifest.md). ## Key properties of the unified manifest -The main reference documentation for the version of the unified app manifest is at [Unified manifest reference](/microsoftteams/platform/resources/schema/manifest-schema). (For the manifest reference that includes all the latest preview features, see [Public developer preview for the unified manifest](/microsoftteams/platform/resources/schema/manifest-schema-dev-preview).) In this article, we provide a brief description of the meaning of base properties when the Teams App is (or includes) an Office Add-in. This is followed by some basic documentation for the "extensions" property and its descendant properties. There is a full sample manifest for an add-in at [Sample unified manifest](#sample-unified-manifest). +The main reference documentation for the version of the unified app manifest is at [Microsoft 365 app manifest schema reference](/microsoft-365/extensibility/schema). In this article, we provide a brief description of the meaning of base properties when the App for Microsoft 365 is (or includes) an Office Add-in. This is followed by some basic documentation for the [`"extensions"`](/microsoft-365/extensibility/schema/root#extensions) property and its descendant properties. There is a full sample manifest for an add-in at [Sample unified manifest](#sample-unified-manifest). ### Base properties -Each of the base properties listed in the following table has more extensive documentation at [Manifest schema](/microsoftteams/platform/resources/schema/manifest-schema). Base properties not included in this table have no meaning for Office Add-ins. +Each of the base properties listed in the following table has more extensive documentation at [Microsoft 365 app manifest schema](/microsoft-365/extensibility/schema/root). Base properties not included in this table have no meaning for Office Add-ins. |JSON property|Purpose| |:-----|:-----| |"$schema"| Identifies the manifest schema. | -|"manifestVersion"| Version of the manifest schema. | -|"id"| GUID of the Teams app/add-in. | -|"version"| Version of the Teams app/add-in. The format must be `n.n.n` where each `n` can be no more than five digits.| -|"name"| Public short and long names of the Teams app/add-in. The short name appears at the top of an add-in's task pane. | -|"description"| Public short and long descriptions of the Teams app/add-in. | -|"developer"| Information about the developer of the Teams app/add-in. | -|"localizationInfo"| Configures the default locale and other supported locales. | -|"validDomains" | See [Specify safe domains](#specify-safe-domains). | -|"webApplicationInfo"| Identifies the Teams app/add-in's web app as it is known in Azure Active Directory. | -|"authorization"| Identifies any Microsoft Graph permissions that the add-in needs. | +|[`"manifestVersion"`](/microsoft-365/extensibility/schema/root#manifestversion)| Version of the manifest schema. | +|`"id"`| GUID of the App for Microsoft 365. | +|[`"version"`](/microsoft-365/extensibility/schema/root#version)| Version of the App for Microsoft 365. The format must be `n.n.n` where each `n` can be no more than five digits.| +|[`"name"`](/microsoft-365/extensibility/schema/root#name)| Public short and long names of the App for Microsoft 365. The short name appears at the top of an add-in's task pane. | +|[`"description"`](/microsoft-365/extensibility/schema/root#description)| Public short and long descriptions of the App for Microsoft 365. | +|[`"developer"`](/microsoft-365/extensibility/schema/root#developer)| Information about the developer of the App for Microsoft 365. | +|[`"localizationInfo"`](/microsoft-365/extensibility/schema/root#localizationinfo)| Configures the default locale and other supported locales. | +|[`"validDomains"`](/microsoft-365/extensibility/schema/root#validdomains) | See [Specify safe domains](#specify-safe-domains). | +|[`"webApplicationInfo"`](/microsoft-365/extensibility/schema/root#webApplicationInfo-property)| Identifies the App for Microsoft 365's web app as it is known in Microsoft Entra ID. | +|[`"authorization"`](/microsoft-365/extensibility/schema/root#authorization)| Identifies any Microsoft Graph permissions that the add-in needs. | -### "extensions" property +### `"extensions"` property -We're working hard to complete reference documentation for the "extensions" property and its descendant properties. In the meantime, the following provides some basic documentation. Most, but not all, of the properties have an equivalent element (or attribute) in the add-in only manifest for add-ins. For the most part, the description, and restrictions, that apply to the XML element or attribute also apply to its JSON property equivalent in the unified manifest. The tables in the '"extensions" property' section of [Compare the add-in only manifest with the unified manifest for Microsoft 365](json-manifest-overview.md#extensions-property) can help you determine the XML equivalent of a JSON property. +We're working hard to complete reference documentation for the `"extensions"` property and its descendant properties. In the meantime, the following provides some basic documentation. Most, but not all, of the properties have an equivalent element (or attribute) in the add-in only manifest for add-ins. For the most part, the description, and restrictions, that apply to the XML element or attribute also apply to its JSON property equivalent in the unified manifest. The tables in the '`"extensions"` property' section of [Compare the add-in only manifest with the unified manifest for Microsoft 365](json-manifest-overview.md#extensions-property) can help you determine the XML equivalent of a JSON property. > [!NOTE] -> This table contains only some selected representative descendant properties of "extensions". *It isn't an exhaustive list of all child properties of "extensions".* For the full reference of the unified manifest, see [Unified manifest for Microsoft 365](/microsoftteams/platform/resources/schema/manifest-schema). For the manifest reference that includes all the latest preview features, see [Public developer preview for the unified manifest for Microsoft 365](/microsoftteams/platform/resources/schema/manifest-schema-dev-preview). +> This table contains only some selected representative descendant properties of `"extensions"`. *It isn't an exhaustive list of all child properties of `"extensions"`.* For the full reference of the unified manifest, see the [Microsoft 365 app manifest schema reference](/microsoft-365/extensibility/schema). |JSON property|Purpose| -|:-----|:-----|:-----|:-----| -| "requirements.capabilities" | Identifies the [requirement sets](office-versions-and-requirement-sets.md#office-requirement-sets-availability) that the add-in needs to be installable. | -| "requirements.scopes" | Identifies the Office applications in which the add-in can be installed. For example, "mail" means the add-in can be installed in Outlook. | -| "ribbons" | The ribbons that the add-in customizes. | -| "ribbons.contexts" | Specifies the command surfaces that the add-in customizes. For example, "mailRead" or "mailCompose". | -| "ribbons.fixedControls" (developer preview) | Configures and adds the button of an [integrated spam-reporting](../outlook/spam-reporting.md) add-in to the Outlook ribbon. | -| "ribbons.spamPreProcessingDialog" (developer preview) | Configures the preprocessing dialog shown after the button of a spam-reporting add-in is selected from the Outlook ribbon. | -| "ribbons.tabs" | Configures custom ribbon tabs. | -| "alternates" | Specifies backwards compatibility with an equivalent COM add-in, XLL, or both. Also specifies the main icons that are used to represent the add-in on older versions of Office. | -| "runtimes" | Configures the [embedded runtimes](../testing/runtimes.md) that the add-in uses, including various kinds of add-ins that have little or no UI, such as custom function-only add-ins and [function commands](../design/add-in-commands.md#types-of-add-in-commands). | -| "autoRunEvents" | Configures an event handler for a specified event. | +|:-----|:-----| +| [`"requirements.capabilities"`](/microsoft-365/extensibility/schema/requirements-extension-element-capabilities) | Identifies the [requirement sets](office-versions-and-requirement-sets.md#office-requirement-sets-availability) that the add-in needs to be installable. | +| [`"requirements.scopes"`](/microsoft-365/extensibility/schema/requirements-extension-element#scopes) | Identifies the Office applications in which the add-in can be installed. For example, `"mail"` means the add-in can be installed in Outlook. | +| [`"ribbons"`](/microsoft-365/extensibility/schema/element-extensions#ribbons) | The ribbons that the add-in customizes. | +| `"ribbons.contexts"` | Specifies the command surfaces that the add-in customizes. For example, `"mailRead"` or `"mailCompose"`. | +| `"ribbons.fixedControls"` | Configures and adds the button of an [integrated spam-reporting](../outlook/spam-reporting.md) add-in to the Outlook ribbon. | +| `"ribbons.spamPreProcessingDialog"` | Configures the preprocessing dialog shown after the button of a spam-reporting add-in is selected from the Outlook ribbon. | +| `"ribbons.tabs"` | Configures custom ribbon tabs. | +| [`"alternates"`](/microsoft-365/extensibility/schema/element-extensions#alternates) | Specifies backwards compatibility with an equivalent COM add-in, XLL, or both. Also specifies the main icons that are used to represent the add-in on older versions of Office. | +| [`"runtimes"`](/microsoft-365/extensibility/schema/element-extensions#runtimes) | Configures the [embedded runtimes](../testing/runtimes.md) that the add-in uses, including various kinds of add-ins that have little or no UI, such as custom function-only add-ins and [function commands](../design/add-in-commands.md#types-of-add-in-commands). | +| [`"autoRunEvents"`](/microsoft-365/extensibility/schema/element-extensions#autorunevents) | Configures an event handler for a specified event. | +| [`"keyboardShortcuts"`](/microsoft-365/extensibility/schema/element-extensions#keyboardshortcuts) (developer preview) | Defines custom keyboard shortcuts or key combinations to run specific actions. | ## Specify safe domains -There is a "validDomains" array in the manifest file that is used to tell Office which domains your add-in should be allowed to navigate to. As noted in [Specify domains you want to open in the add-in window](add-in-manifests.md#specify-domains-you-want-to-open-in-the-add-in-window), when running in Office on the web, your task pane can be navigated to any URL. However, in desktop platforms, if your add-in tries to go to a URL in a domain other than the domain that hosts the start page, that URL opens in a new browser window outside the add-in pane of the Office application. +There is a `"validDomains"` array in the manifest file that is used to tell Office which domains your add-in should be allowed to navigate to. As noted in [Specify domains you want to open in the add-in window](add-in-manifests.md#specify-domains-you-want-to-open-in-the-add-in-window), when running in Office on the web, your task pane can be navigated to any URL. However, in desktop platforms, if your add-in tries to go to a URL in a domain other than the domain that hosts the start page, that URL opens in a new browser window outside the add-in pane of the Office application. + +To override this behavior in desktop platforms, add each domain you want to open in the add-in window to the list of domains specified in the `"validDomains"` array. If the add-in tries to go to a URL in a domain that is in the list, then it opens in the task pane in both Office on the web and desktop. If it tries to go to a URL that isn't in the list, then in Office on desktop, that URL opens in a new browser window (outside the add-in task pane). + +## Client and platform support -To override this behavior in desktop platforms, add each domain you want to open in the add-in window to the list of domains specified in the "validDomains" array. If the add-in tries to go to a URL in a domain that is in the list, then it opens in the task pane in both Office on the web and desktop. If it tries to go to a URL that isn't in the list, then in Office on desktop, that URL opens in a new browser window (outside the add-in task pane). +Add-ins that use the unified manifest can be installed if the Office platform *directly* supports it. + +To run an add-in on platforms that don't directly support the unified manifest, you must publish the add-in to [Microsoft Marketplace](https://marketplace.microsoft.com/). Then, deploy the add-in in the [Microsoft 365 admin center](../publish/publish.md). This way, an add-in only manifest is generated from the unified manifest and stored. The add-in only manifest is then used to install the add-in on platforms that don't directly support the unified manifest. + +The following tables lists which Office platforms directly support add-ins that use the unified manifest. + +| Client/platform | Support for add-ins with the unified manifest| +| ----- | ----- | +| Office on the web | Directly supported | +| Office on Windows (Version 2304 (Build 16320.00000) or later) connected to a Microsoft 365 subscription | Directly supported | +| [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) | Directly supported | +| Office on Windows (prior to Version 2304 (Build 16320.00000)) connected to a Microsoft 365 subscription | Not directly supported | +| Office on Windows (perpetual versions) | Not directly supported | +| Office on Mac | Not directly supported | +| Office on mobile | Not directly supported | + +> [!NOTE] +> If you're deploying an add-in in the [Microsoft 365 admin center](../publish/publish.md#integrated-apps-portal-in-the-microsoft-365-admin-center) and require it to run on platforms that don't directly support the unified manifest, the add-in must be a published Microsoft Marketplace add-in. Custom add-ins or line-of-business (LOB) add-ins that use the unified manifest can be deployed in the [Integrated apps portal](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps) of the Microsoft 365 admin center, but they won't be installable on Office versions that don't directly support the unified manifest. ## Sample unified manifest @@ -344,7 +363,7 @@ The following is an example of a unified app manifest for an add-in. It doesn't "controls": [ { "id": "msgReadFunctionButton", - "type": "MobileButton", + "type": "mobileButton", "label": "Action 1", "icons": [ { @@ -376,7 +395,7 @@ The following is an example of a unified app manifest for an add-in. It doesn't "controls": [ { "id": "control1", - "type": "MobileButton", + "type": "mobileButton", "label": "Action 1", "icons": [ { @@ -465,4 +484,4 @@ The following is an example of a unified app manifest for an add-in. It doesn't ## See also - [Create add-in commands with the unified manifest for Microsoft 365](create-addin-commands-unified-manifest.md) -- [Manifest schema](/microsoftteams/platform/resources/schema/manifest-schema) +- [Microsoft 365 app manifest schema reference](/microsoft-365/extensibility/schema) diff --git a/docs/develop/usability-testing.md b/docs/develop/usability-testing.md index 5235d116f8..c613b3ca67 100644 --- a/docs/develop/usability-testing.md +++ b/docs/develop/usability-testing.md @@ -1,7 +1,7 @@ ---- +--- title: Usability testing for Office Add-ins description: Learn how to test your add-in design with real users. -ms.date: 09/06/2023 +ms.date: 01/13/2025 ms.localizationpriority: medium --- @@ -20,7 +20,7 @@ These testing services help you to streamline test plan creation and remove the You need only five participants to uncover most usability issues in your design. Incorporate small tests regularly throughout your development cycle to ensure that your product is user-centered. > [!NOTE] -> We recommend that you test the usability of your add-in across multiple platforms. To [publish your add-in to AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center), it must work on all [platforms that support the methods that you define](/javascript/api/requirement-sets). +> We recommend that you test the usability of your add-in across multiple platforms. To [publish your add-in to Microsoft Marketplace](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center), it must work on all [platforms that support the methods that you define](/javascript/api/requirement-sets). ## 1. Sign up for a testing service @@ -45,7 +45,7 @@ Research questions define the objectives of your research and guide your test pl It's important to get data on the entire user journey – from discovering your add-in, to installing and using it. Consider research questions that address the following aspects of the add-in user experience. -- Finding your add-in in AppSource +- Finding your add-in in Microsoft Marketplace - Choosing to install your add-in - First-run experience - Ribbon commands @@ -114,7 +114,7 @@ On average, it takes about 5 minutes to walk users through how to install an add 1. Take a moment to look at the Store page to familiarize yourself with the add-in. 1. Choose **Add** to install the add-in. -You can test a prototype at any level of interaction and visual fidelity. For more complex linking and interactivity, consider a prototyping tool like [InVision](https://www.invisionapp.com). If you just want to test static screens, you can host images online and send participants the corresponding URL, or give them a link to an online PowerPoint presentation. +You can test a prototype at any level of interaction and visual fidelity. For more complex linking and interactivity, consider a prototyping tool like [Figma](https://www.figma.com/). If you just want to test static screens, you can host images online and send participants the corresponding URL, or give them a link to an online PowerPoint presentation. ## 7. Run a pilot test diff --git a/docs/outlook/use-sso-in-event-based-activation.md b/docs/develop/use-sso-in-event-based-activation.md similarity index 60% rename from docs/outlook/use-sso-in-event-based-activation.md rename to docs/develop/use-sso-in-event-based-activation.md index 8c45242a8d..4869495851 100644 --- a/docs/outlook/use-sso-in-event-based-activation.md +++ b/docs/develop/use-sso-in-event-based-activation.md @@ -1,16 +1,16 @@ --- -title: Use single sign-on (SSO) or cross-origin resource sharing (CORS) in your event-based or spam-reporting Outlook add-in -description: Learn how to use SSO or CORS in an Outlook add-in that implements event-based activation or integrated spam reporting. -ms.date: 02/29/2024 +title: Use single sign-on (SSO) or cross-origin resource sharing (CORS) in your event-based or spam-reporting Office Add-in +description: Learn how to use SSO or CORS in an add-in that implements event-based activation or integrated spam reporting. +ms.date: 07/08/2025 ms.localizationpriority: medium --- -# Use single sign-on (SSO) or cross-origin resource sharing (CORS) in your event-based or spam-reporting Outlook add-in +# Use single sign-on (SSO) or cross-origin resource sharing (CORS) in your event-based or spam-reporting Office Add-in -When an Outlook add-in implements event-based activation or integrated spam reporting, the events run in a separate [runtime](../testing/runtimes.md). To configure single sign-on (SSO) or request external data through cross-origin resource sharing (CORS) in these add-ins, you must configure a well-known URI. Through this resource, Office will be able to identify the add-ins, including their JavaScript files, that support SSO or CORS requests. +When an add-in implements event-based activation or integrated spam reporting, the events run in a separate [runtime](../testing/runtimes.md). To configure single sign-on (SSO) or request external data through cross-origin resource sharing (CORS) in these add-ins, you must configure a well-known URI. Through this resource, Office will be able to identify the add-ins, including their JavaScript files, that support SSO or CORS requests. > [!NOTE] -> The steps in this article only apply to Outlook add-ins that run in classic Outlook on Windows. This is because classic Outlook on Windows uses a JavaScript file, while Outlook on Mac, on the web, and [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) use an HTML file that references the same JavaScript file. To learn more, see [Configure your Outlook add-in for event-based activation](autolaunch.md) and [Implement an integrated spam-reporting add-in](spam-reporting.md). +> The steps in this article only apply to add-ins that run on Excel, PowerPoint, or Word on Windows, or classic Outlook on Windows. This is because they use a JavaScript file, while these applications on Mac, on the web, and [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) use an HTML file that references the same JavaScript file. To learn more, see [Activate add-ins with events](../develop/event-based-activation.md) and [Implement an integrated spam-reporting add-in](../outlook/spam-reporting.md). ## List allowed add-ins in a well-known URI @@ -35,10 +35,10 @@ The origin refers to a pattern of scheme + subdomain + domain + port. The name o After you configure the well-known URI, if your add-in implements SSO, you can then call the [getAccessToken() API](/javascript/api/office-runtime/officeruntime.auth) to get an access token with the user's identity. > [!IMPORTANT] -> While `OfficeRuntime.auth.getAccessToken` and `Office.auth.getAccessToken` perform the same functionality of retrieving an access token, we recommend calling `OfficeRuntime.auth.getAccessToken` in your event-based or spam-reporting (preview) add-in. This API is supported in all Outlook client versions that support event-based activation, integrated spam reporting, and SSO. On the other hand, `Office.auth.getAccessToken` is only supported in classic Outlook on Windows starting from Version 2111 (Build 14701.20000). +> While `OfficeRuntime.auth.getAccessToken` and `Office.auth.getAccessToken` perform the same functionality of retrieving an access token, we recommend calling `OfficeRuntime.auth.getAccessToken` in your event-based or spam-reporting add-in. This API is supported in all client versions that support event-based activation, integrated spam reporting, and SSO. On the other hand, `Office.auth.getAccessToken` is only supported in classic Outlook on Windows starting from Version 2111 (Build 14701.20000). ## See also -- [Authenticate a user with a single-sign-on token in an Outlook add-in](authenticate-a-user-with-an-sso-token.md) -- [Configure your Outlook add-in for event-based activation](autolaunch.md) -- [Implement an integrated spam-reporting add-in](spam-reporting.md) +- [Authenticate a user with a single-sign-on token in an Outlook add-in](../outlook/authenticate-a-user-with-an-sso-token.md) +- [Activate add-ins with events](../develop/event-based-activation.md) +- [Implement an integrated spam-reporting add-in](../outlook/spam-reporting.md) diff --git a/docs/develop/use-sso-to-get-office-signed-in-user-token.md b/docs/develop/use-sso-to-get-office-signed-in-user-token.md index c5dbb7b47a..63305293b6 100644 --- a/docs/develop/use-sso-to-get-office-signed-in-user-token.md +++ b/docs/develop/use-sso-to-get-office-signed-in-user-token.md @@ -1,7 +1,7 @@ ---- +--- title: Use SSO to get the identity of the signed-in user description: Call the getAccessToken API to get the ID token with name, email, and additional information about the signed-in user. -ms.date: 06/23/2023 +ms.date: 06/24/2025 ms.localizationpriority: medium --- @@ -44,7 +44,7 @@ To use SSO with Office, you need to create an app registration in the Azure port When you're finished, the entire ID should have the form `api://localhost:[port]/[app-id-guid]`; for example `api://localhost:44355/c6c1f32b-5e55-4997-881a-753cc1d563b7`. -1. Select the **Add a scope** button. In the panel that opens, enter `access_as_user` as the **\** name. +1. Select the **Add a scope** button. In the panel that opens, enter `access_as_user` as the `` name. 1. Set **Who can consent?** to **Admins and users**. @@ -60,7 +60,7 @@ To use SSO with Office, you need to create an app registration in the Azure port 1. Select **Add scope** . > [!NOTE] - > The domain part of the **\** name displayed just below the text field should automatically match the Application ID URI that you set earlier, with `/access_as_user` appended to the end; for example, `api://localhost:6789/c6c1f32b-5e55-4997-881a-753cc1d563b7/access_as_user`. + > The domain part of the `` name displayed just below the text field should automatically match the Application ID URI that you set earlier, with `/access_as_user` appended to the end; for example, `api://localhost:6789/c6c1f32b-5e55-4997-881a-753cc1d563b7/access_as_user`. 1. In the **Authorized client applications** section, enter the following ID to pre-authorize all Microsoft Office application endpoints. @@ -150,11 +150,11 @@ In Visual Studio Code, open the **manifest.xml** file. The XML you inserted contains the following elements and information. -- **\** - The parent of the following elements. -- **\** - The client ID of the add-in This is an application ID that you obtain as part of registering the add-in. See [Register an Office Add-in that uses SSO with the Azure AD v2.0 endpoint](register-sso-add-in-aad-v2.md). -- **\** - The URL of the add-in. This is the same URI (including the `api:` protocol) that you used when registering the add-in in AAD. The domain part of this URI must match the domain, including any subdomains, used in the URLs in the **\** section of the add-in's manifest and the URI must end with the client ID in the **\**. -- **\** - The parent of one or more **\** elements. -- **\** - Specifies a permission that the add-in needs to AAD. The `profile` and `openID` permissions are always needed and may be the only permissions needed, if your add-in doesn't access Microsoft Graph. If it does, you also need **\** elements for the required Microsoft Graph permissions; for example, `User.Read`, `Mail.Read`. Libraries that you use in your code to access Microsoft Graph may need additional permissions. For example, Microsoft Authentication Library (MSAL) for .NET requires the `offline_access` permission. For more information, see [Authorize to Microsoft Graph from an Office Add-in](authorize-to-microsoft-graph.md). +- `` - The parent of the following elements. +- `` - The client ID of the add-in This is an application ID that you obtain as part of registering the add-in. See [Register an Office Add-in that uses single sign-on (SSO) with the Microsoft identity platform](register-sso-add-in-aad-v2.md). +- `` - The URL of the add-in. This is the same URI (including the `api:` protocol) that you used when registering the add-in in Microsoft Entra ID. The domain part of this URI must match the domain, including any subdomains, used in the URLs in the `` section of the add-in's manifest and the URI must end with the client ID in the ``. +- `` - The parent of one or more `` elements. +- `` - Specifies a permission that the add-in needs. The `profile` and `openID` permissions are always needed and may be the only permissions needed, if your add-in doesn't access Microsoft Graph. If it does, you also need `` elements for the required Microsoft Graph permissions; for example, `User.Read`, `Mail.Read`. Libraries that you use in your code to access Microsoft Graph may need additional permissions. For example, Microsoft Authentication Library (MSAL) for .NET requires the `offline_access` permission. For more information, see [Authorize to Microsoft Graph from an Office Add-in](authorize-to-microsoft-graph.md). ## Add the jwt-decode package @@ -326,7 +326,7 @@ The final step is to get the ID token by calling `getAccessToken`. # [Visual Studio 2019](#tab/vs2019) -Choose **Debug** > **Start Debugging**, or press **F5**. +Choose **Debug** > **Start Debugging**, or press F5. # [Yo Office](#tab/yooffice) @@ -347,7 +347,7 @@ The add-in will display the name, email, and ID of the account you signed in wit # [Visual Studio 2019](#tab/vs2019) -Choose **Stop Debugging**, or press **Shift+F5**. +Choose **Stop Debugging**, or press Shift+F5. # [Yo Office](#tab/yooffice) diff --git a/docs/develop/xml-manifest-overview.md b/docs/develop/xml-manifest-overview.md index 2141ffcb10..acdc9f5baf 100644 --- a/docs/develop/xml-manifest-overview.md +++ b/docs/develop/xml-manifest-overview.md @@ -1,14 +1,14 @@ ---- +--- title: Office Add-ins with the add-in only manifest description: Get an overview of the add-in only manifest for Office add-ins and its uses. ms.topic: overview -ms.date: 04/12/2024 +ms.date: 06/24/2025 ms.localizationpriority: high --- # Office Add-ins with the add-in only manifest -This article introduces the XML-formatted add-in only manifest for Office Add-ins. It assumes that you're familiar with the [Office Add-ins manifest](add-in-manifests.md). +This article introduces the XML-formatted add-in only manifest for Office Add-ins. It assumes that you're familiar with the [Office Add-ins manifest](add-in-manifests.md). > [!TIP] > For an overview of the unified manifest for Microsoft 365, see [Office Add-ins with the unified manifest for Microsoft 365](unified-manifest-overview.md). @@ -17,7 +17,7 @@ This article introduces the XML-formatted add-in only manifest for Office Add-in Not all Office clients support the latest features, and some Office users will have an older version of Office. Having schema versions lets developers build add-ins that are backwards compatible, using the newest features where they are available but still functioning on older versions. -The **\** element in the manifest is an example of this. All elements defined inside **\** will override the same element in the other part of the manifest. This means that, whenever possible, Office will use what is in the **\** section to set up the add-in. However, if the version of Office doesn't support a certain version of **\**, Office will ignore it and depend on the information in the rest of the manifest. +The `` element in the manifest is an example of this. All elements defined inside `` will override the same element in the other part of the manifest. This means that, whenever possible, Office will use what is in the `` section to set up the add-in. However, if the version of Office doesn't support a certain version of ``, Office will ignore it and depend on the information in the rest of the manifest. This approach means that developers don't have to create multiple individual manifests, but rather keep everything defined in one file. @@ -26,11 +26,11 @@ The current versions of the schema are: |Version|Description| |:-----|:-----| |v1.0|Supports version 1.0 of the Office JavaScript API. For example, in Outlook add-ins, this supports the read form. | -|v1.1|Supports version 1.1 of the Office JavaScript API and **\**. For example, in Outlook add-ins, this adds support for the compose form.| -|**\** 1.0|Supports later versions of the Office JavaScript API. This supports add-in commands.| -|**\** 1.1|Supported by Outlook only. This version of **\** adds support for newer features, such as [pinnable task panes](../outlook/pinnable-taskpane.md) and mobile add-ins.| +|v1.1|Supports version 1.1 of the Office JavaScript API and ``. For example, in Outlook add-ins, this adds support for the compose form.| +|`` 1.0|Supports later versions of the Office JavaScript API. This supports add-in commands.| +|`` 1.1|Supported by Outlook only. This version of `` adds support for newer features, such as [pinnable task panes](../outlook/pinnable-taskpane.md) and mobile add-ins.| -Even if your add-in manifest uses the **\** element, it is still important to include the v1.1 manifest elements to allow your add-in to work with older clients that do not support **\**. +Even if your add-in manifest uses the `` element, it is still important to include the v1.1 manifest elements to allow your add-in to work with older clients that do not support ``. > [!NOTE] > Office uses a schema to validate manifests. The schema requires that elements in the manifest appear in a specific order. If you include elements out of the required order, you may get errors when sideloading your add-in. See [How to find the proper order of manifest elements](../develop/manifest-element-ordering.md) elements in the required order. @@ -66,7 +66,7 @@ The following table specifies the elements that are required for the three types _\*Added in the Office Add-in Manifest Schema version 1.1._ -_\*\* SupportUrl is only required for add-ins that are distributed through AppSource._ +_\*\* SupportUrl is only required for add-ins that are distributed through Microsoft Marketplace._ @@ -99,7 +99,7 @@ _\*\* SupportUrl is only required for add-ins that are distributed through AppSo ## Root element -The root element for the Office Add-in manifest is **\**. This element also declares the default namespace, schema version and the type of add-in. Place all other elements in the manifest within its open and close tags. The following is an example of the root element. +The root element for the Office Add-in manifest is ``. This element also declares the default namespace, schema version and the type of add-in. Place all other elements in the manifest within its open and close tags. The following is an example of the root element. ```XML ** element like the following: +Office add-ins specify the `` element like the following: ```XML @@ -134,13 +134,13 @@ Office add-ins specify the **\** element like the following: ``` -This is separate from the **\** element inside the **\** element, which is discussed in [Create add-in commands with the add-in only manifest](../develop/create-addin-commands.md). +This is separate from the `` element inside the `` element, which is discussed in [Create add-in commands with the add-in only manifest](../develop/create-addin-commands.md). ## Specify safe domains with the AppDomains element There is an [AppDomains](/javascript/api/manifest/appdomains) element of the add-in only manifest file that is used to tell Office which domains your add-in should be allowed to navigate to. As noted in [Specify domains you want to open in the add-in window](add-in-manifests.md#specify-domains-you-want-to-open-in-the-add-in-window), when running in Office on the web, your task pane can be navigated to any URL. However, in desktop platforms, if your add-in tries to go to a URL in a domain other than the domain that hosts the start page (as specified in the [SourceLocation](/javascript/api/manifest/sourcelocation) element), that URL opens in a new browser window outside the add-in pane of the Office application. -To override this (desktop Office) behavior, add each domain you want to open in the add-in window in the list of domains specified in the **\** element. If the add-in tries to go to a URL in a domain that is in the list, then it opens in the task pane in both Office on the web and desktop. If it tries to go to a URL that isn't in the list, then in desktop Office that URL opens in a new browser window (outside the add-in pane). +To override this (desktop Office) behavior, add each domain you want to open in the add-in window in the list of domains specified in the `` element. If the add-in tries to go to a URL in a domain that is in the list, then it opens in the task pane in both Office on the web and desktop. If it tries to go to a URL that isn't in the list, then in desktop Office that URL opens in a new browser window (outside the add-in pane). The following table describes browser behavior when your add-in attempts to navigate to a URL outside of the add-in's default domain. @@ -150,7 +150,7 @@ The following table describes browser behavior when your add-in attempts to navi |Office 2016 on Windows (volume-licensed perpetual)|No|Link opens in Internet Explorer 11.| |Other clients|No|Link opens in user's default browser.| -The following add-in only manifest example hosts its main add-in page in the `https://www.contoso.com` domain as specified in the **\** element. It also specifies the `https://www.northwindtraders.com` domain in an [AppDomain](/javascript/api/manifest/appdomain) element within the **\** element list. If the add-in goes to a page in the `www.northwindtraders.com` domain, that page opens in the add-in pane, even in Office desktop. +The following add-in only manifest example hosts its main add-in page in the `https://www.contoso.com` domain as specified in the `` element. It also specifies the `https://www.northwindtraders.com` domain in an [AppDomain](/javascript/api/manifest/appdomain) element within the `` element list. If the add-in goes to a page in the `www.northwindtraders.com` domain, that page opens in the add-in pane, even in Office desktop. ```XML @@ -179,7 +179,7 @@ The optional [VersionOverrides](/javascript/api/manifest/versionoverrides) eleme - Customizing the Office ribbon and menus. - Customizing how Office works with the embedded runtimes in which add-ins run. -- Configuring how the add-in interacts with Azure Active Directory and Microsoft Graph for Single Sign-on. +- Configuring how the add-in interacts with Microsoft Entra ID and Microsoft Graph for Single Sign-on. Some descendant elements of `VersionOverrides` have values that override values of the parent `OfficeApp` element. For example, the `Hosts` element in `VersionOverrides` overrides the `Hosts` element in `OfficeApp`. @@ -226,11 +226,11 @@ For an example of a manifest that includes a `VersionOverrides` element, see [Ma ## Requirements -The **\** element specifies the set of APIs available to the add-in. For detailed information about requirement sets, see [Office requirement sets availability](office-versions-and-requirement-sets.md#office-requirement-sets-availability). For example, in an Outlook add-in, the requirement set must be Mailbox and a value of 1.1 or above. +The `` element specifies the set of APIs available to the add-in. For detailed information about requirement sets, see [Office requirement sets availability](office-versions-and-requirement-sets.md#office-requirement-sets-availability). For example, in an Outlook add-in, the requirement set must be Mailbox and a value of 1.1 or above. -The **\** element can also appear in the **\** element, allowing the add-in to specify a different requirement when loaded in clients that support **\**. +The `` element can also appear in the `` element, allowing the add-in to specify a different requirement when loaded in clients that support ``. -The following example uses the **DefaultMinVersion** attribute of the **\** element to require office.js version 1.1 or higher, and the **MinVersion** attribute of the **\** element to require the Mailbox requirement set version 1.1. +The following example uses the **DefaultMinVersion** attribute of the `` element to require office.js version 1.1 or higher, and the **MinVersion** attribute of the `` element to require the Mailbox requirement set version 1.1. ```XML @@ -246,7 +246,7 @@ The following example uses the **DefaultMinVersion** attribute of the **\ ## Localization -Some aspects of the add-in need to be localized for different locales, such as the name, description and the URL that's loaded. These elements can easily be localized by specifying the default value and then locale overrides in the **\** element within the **\** element. The following shows how to override an image, a URL, and a string. +Some aspects of the add-in need to be localized for different locales, such as the name, description and the URL that's loaded. These elements can easily be localized by specifying the default value and then locale overrides in the `` element within the `` element. The following shows how to override an image, a URL, and a string. ```XML @@ -690,6 +690,6 @@ For information about validating a manifest against the [XML Schema Definition ( - [Specify Office applications and API requirements](specify-office-hosts-and-api-requirements.md) - [Localization for Office Add-ins](localization.md) - [Schema reference for XML Office Add-ins manifests](/openspecs/office_file_formats/ms-owemxml/c6a06390-34b8-4b42-82eb-b28be12494a8) -- [Identify an equivalent COM add-in](make-office-add-in-compatible-with-existing-com-add-in.md) +- [Make your Office Add-in compatible with an existing COM or VSTO add-in](make-office-add-in-compatible-with-existing-com-add-in.md) - [Requesting permissions for API use in add-ins](requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md) - [Validate an Office Add-in's manifest](../testing/troubleshoot-manifest.md) diff --git a/docs/develop/yeoman-generator-overview.md b/docs/develop/yeoman-generator-overview.md index 1daecb1f7b..192153ca97 100644 --- a/docs/develop/yeoman-generator-overview.md +++ b/docs/develop/yeoman-generator-overview.md @@ -2,16 +2,16 @@ title: Create Office Add-in projects using the Yeoman Generator description: Learn how to create Office Add-in projects using the Yeoman generator for Office Add-ins. ms.topic: tutorial -ms.date: 04/12/2024 +ms.date: 07/07/2025 ms.localizationpriority: high --- # Create Office Add-in projects using the Yeoman Generator -The [Yeoman Generator for Office Add-ins](https://github.com/OfficeDev/generator-office) (also called "Yo Office") is an interactive Node.js-based command line tool that creates Office Add-in development projects. We recommend that you use this tool to create add-in projects except when you want the server-side code of the add-in to be in a .NET-based language (such as C# or VB.Net) or you want the add-in hosted in Internet Information Server (IIS). In either of the latter two situations, [use Visual Studio to create the add-in](develop-add-ins-visual-studio.md). +The [Yeoman Generator for Office Add-ins](https://github.com/OfficeDev/generator-office) (also called "Yo Office") is an interactive Node.js-based command line tool that creates Office Add-in development projects. These projects are Node.js-based. When you want the server-side code of the add-in to be in a .NET-based language (such as C# or VB.Net) or you want the add-in hosted in Internet Information Server (IIS), [use Visual Studio to create the add-in](develop-add-ins-visual-studio.md). > [!NOTE] -> Office add-ins can also be created with the Teams Toolkit (Prerelease version). For more information about how to do this and the limitations, see [Create Office Add-in projects using the Teams Toolkit (preview)](teams-toolkit-overview.md). +> Office add-ins can also be created with the [Microsoft 365 Agents Toolkit](agents-toolkit-overview.md) or the [Office Add-in Development Kit](development-kit-overview.md). The projects that the tool creates have the following characteristics. @@ -27,7 +27,7 @@ The projects that the tool creates have the following characteristics. > [!TIP] > If you want to deviate from these choices significantly, such as using a different task runner or a different server, we recommend that when you run the tool you choose the [Manifest-only option](#manifest-only-option). -## Install the generator +## Prerequisites >[!NOTE] > If you aren't familiar with Node.js or npm, you should start by [setting up your development environment](../overview/set-up-your-dev-environment.md). @@ -42,21 +42,24 @@ Start the tool with the following command in a system prompt (not a bash window) yo office ``` -A lot needs to load, so it may take 20 seconds before the tool starts. The tool asks you a series of questions. For some, you just type an answer to the prompt. For others, you're given a list of possible answers. If given a list, select one and then select Enter. +A lot needs to load, so it may take 40 seconds before the tool starts. The tool asks you a series of questions. For some, you just type an answer to the prompt. For others, you're given a list of possible answers. If given a list, use the up and down arrow keys to select one and then select Enter. The first question asks you to choose between several types of projects. The options are: - **Office Add-in Task Pane project** +- **Excel, PowerPoint, and/or Word Task Pane with unified manifest for Microsoft 365 (preview)** - **Office Add-in Task Pane project using React framework** - **Excel Custom Functions using a Shared Runtime** - **Excel Custom Functions using a JavaScript-only Runtime** - **Office Add-in Task Pane project supporting single sign-on** +- **Office Add-in Task Pane project supporting Nested App Auth single sign-on (preview)** - **Office Add-in project containing the manifest only** ![The prompt for project type, and the possible answers, in the Yeoman generator.](../images/yo-office-project-type-prompt.png) > [!NOTE] -> The **Office Add-in project containing the manifest only** option produces a project that contains a basic add-in manifest and minimal scaffolding. For more information about the option, see [Manifest-only option](#manifest-only-option). +> - The **Office Add-in project containing the manifest only** option produces a project that contains a basic add-in manifest and minimal scaffolding. For more information about the option, see [Manifest-only option](#manifest-only-option). +> - The **Excel, PowerPoint, and/or Word Task Pane with unified manifest for Microsoft 365 (preview)** option creates a project for Excel, PowerPoint, Word, or all three, that uses the unified manifest for Microsoft 365. For more information about the option, see [Word, PowerPoint, or Excel with unified manifest option](#word-powerpoint-or-excel-with-unified-manifest-option). The next question asks you to choose between **TypeScript** and **JavaScript**. (This question is skipped if you chose the manifest-only option in the preceding question.) @@ -74,7 +77,7 @@ If you choose **Outlook** as the Office application, you get an additional quest [!INCLUDE [non-unified manifest clients note](../includes/non-unified-manifest-clients.md)] -After you've answered this question, the generator creates the project and installs the dependencies. You may see **WARN** messages in the npm output on screen. You can ignore these. You may also see messages that vulnerabilities were found. You can ignore these for now, but you'll eventually need to fix them before your add-in is released to production. For more information about fixing vulnerabilities, open your browser and search for "npm vulnerability". +After you've answered all questions, the generator creates the project and installs the dependencies. You may see **WARN** messages in the npm output on screen. You can ignore these. You may also see messages that vulnerabilities were found. You can ignore these for now, but you'll eventually need to fix them before your add-in is released to production. For more information, see [Warnings and dependencies in the Node.js and npm world](../overview/npm-warnings-advice.md). If the creation is successful, you'll see a **Congratulations!** message in the command window, followed by some suggested next steps. (If you're using the generator as part of a quick start or tutorial, ignore the next steps in the command window and continue with the instructions in the article.) @@ -88,7 +91,7 @@ If the creation is successful, you'll see a **Congratulations!** message in the > When you're ready to install the dependencies, navigate to the root folder of the project in a command prompt and enter `npm install`. > [!WARNING] -> If you choose **Office Add-in Task Pane project supporting single sign-on** and **TypeScript**, and you are using a Node.js version greater than 18.16.0, then a bug in Node.js causes the project file **\\src\middle-tier\ssoauth-helper.ts** to be corrupted. To fix it, copy the contents of the file from the repo, [ssoauth-helper.ts](https://github.com/OfficeDev/Office-Addin-Taskpane-SSO/blob/master/src/middle-tier/ssoauth-helper.ts), over the contents of the file in the generated project. +> If you choose **Office Add-in Task Pane project supporting single sign-on** and **TypeScript**, and you are using a Node.js version greater than 18.16.0, then a bug in Node.js may cause the project file **\\src\middle-tier\ssoauth-helper.ts** to be corrupted. To fix it, copy the contents of the file from the repo, [ssoauth-helper.ts](https://github.com/OfficeDev/Office-Addin-Taskpane-SSO/blob/master/src/middle-tier/ssoauth-helper.ts), over the contents of the file in the generated project. ## Manifest-only option @@ -97,6 +100,10 @@ This option creates only a manifest for an add-in. The resulting project doesn't - You want to use different tools from the ones a Yeoman generator project installs and configures by default. For example, you want to use a different bundler, transpiler, task runner, or development server. - You want to use a web application development framework, other than React, such as Vue. +## Word, PowerPoint, or Excel with unified manifest option + +The unified manifest for Microsoft 365 is in preview for Excel, PowerPoint, and Word add-ins. It should not be used for production add-ins, but you can select this option in Yo Office to create an add-in for one (or all three) of those Office applications. You'll be asked to choose which Office application. You can also choose **All** to create an add-in that is installable on all three Office applications. The project that is created uses TypeScript. + ## Use command line parameters You can also add parameters to the `yo office` command. The two most common are: @@ -108,4 +115,4 @@ For detailed reference about the command line parameters, see the readme for the ## Troubleshooting -If you encounter problems using the tool, your first step should be to reinstall it to be sure that you have the latest version. (See [Install the generator](#install-the-generator) for details.) If doing so doesn't fix the problem, search the [issues of the GitHub repo for the tool](https://github.com/OfficeDev/generator-office/issues) to see if anyone else has encountered the same problem and found a solution. If no one has, [create a new issue](https://github.com/OfficeDev/generator-office/issues/new?assignees=&labels=needs+triage&template=bug_report.md&title=). +If you encounter problems using the tool, your first step should be to reinstall it to be sure that you have the latest version. (See [Prerequisites](#prerequisites) for details.) If doing so doesn't fix the problem, search the [issues of the GitHub repo for the tool](https://github.com/OfficeDev/generator-office/issues) to see if anyone else has encountered the same problem and found a solution. If no one has, [create a new issue](https://github.com/OfficeDev/generator-office/issues/new?assignees=&labels=needs+triage&template=bug_report.md&title=). diff --git a/docs/docfx.json b/docs/docfx.json index 6fef6e8517..08b01ea066 100644 --- a/docs/docfx.json +++ b/docs/docfx.json @@ -48,7 +48,7 @@ "feedback_product_url": "https://aka.ms/office-addins-dev-questions", "open_source_feedback_contributorGuideUrl": "https://github.com/OfficeDev/office-js-docs-pr/blob/main/Contributing.md", "open_source_feedback_issueTitle": "", - "open_source_feedback_issueUrl": "https://github.com/OfficeDev/office-js-docs-pr/issues/new?template=3-customer-feedback.yml", + "open_source_feedback_issueUrl": "https://github.com/OfficeDev/office-js-docs-pr/issues/new?template=3_customer-feedback.yml", "open_source_feedback_productName": "Office Add-ins", "titleSuffix": "Office Add-ins" }, diff --git a/docs/excel/custom-functions-batching.md b/docs/excel/custom-functions-batching.md index a0500a29cf..5008345bd4 100644 --- a/docs/excel/custom-functions-batching.md +++ b/docs/excel/custom-functions-batching.md @@ -1,26 +1,18 @@ --- -ms.date: 09/09/2022 +ms.date: 10/22/2025 description: Batch custom functions together to reduce network calls to a remote service. -title: Batching custom function calls for a remote service +title: Batch custom function calls for a remote service ms.topic: best-practice ms.localizationpriority: medium --- # Batch custom function calls for a remote service -If your custom functions call a remote service you can use a batching pattern to reduce the number of network calls to the remote service. To reduce network round trips you batch all the calls into a single call to the web service. This is ideal when the spreadsheet is recalculated. +Use batching to group calls to a remote service into a single network request. This reduces the number of network round trips to your remote service and helps your worksheet finish recalculating faster. -For example, if someone used your custom function in 100 cells in a spreadsheet, and then recalculated the spreadsheet, your custom function would run 100 times and make 100 network calls. By using a batching pattern, the calls can be combined to make all 100 calculations in a single network call. +Here's a batching example scenario: If 100 cells call the custom function, send one request that lists all 100 operations. The service returns 100 results in a single response. -[!include[Excel custom functions note](../includes/excel-custom-functions-note.md)] - -## View the completed sample - -To view the completed sample, follow this article and paste the code examples into your own project. For example, to create a new custom function project for TypeScript use the [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md), then add all the code from this article to the project. Run the code and try it out. - -Alternatively, download or view the complete sample project at [Custom function batching pattern](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Excel-custom-functions/Batching). If you want to view the code in whole before reading any further, take a look at the [script file](https://github.com/OfficeDev/Office-Add-in-samples/blob/main/Excel-custom-functions/Batching/src/functions/functions.js). - -## Create the batching pattern in this article +## Key points To set up batching for your custom functions you'll need to write three main sections of code. @@ -28,15 +20,24 @@ To set up batching for your custom functions you'll need to write three main sec 2. A [function to make the remote request](#make-the-remote-request) when the batch is ready. 3. [Server code to respond to the batch request](#process-the-batch-call-on-the-remote-service), calculate all of the operation results, and return the values. +[!include[Excel custom functions note](../includes/excel-custom-functions-note.md)] + +## Create the batching pattern in this article + In the following sections, you'll learn how to construct the code one example at a time. It's recommended you create a brand-new custom functions project using the [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md) generator. To create a new project, see [Get started developing Excel custom functions](../quickstarts/excel-custom-functions-quickstart.md). You can use TypeScript or JavaScript. +> [!TIP] +> To view the completed sample, create a new custom functions project with the Yeoman generator for Office Add-ins. Copy and paste the code examples into your project then, run the code and try it out. +> +> Alternatively, download or view the complete sample project at [Custom function batching pattern](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Excel-custom-functions/Batching). If you want to view the entire code before continuing, take a look at the [script file](https://github.com/OfficeDev/Office-Add-in-samples/blob/main/Excel-custom-functions/Batching/src/functions/functions.js). + ## Batch each call to your custom function -Your custom functions work by calling a remote service to perform the operation and calculate the result they need. This provides a way for them to store each requested operation into a batch. Later you'll see how to create a `_pushOperation` function to batch the operations. First, take a look at the following code example to see how to call `_pushOperation` from your custom function. +Your custom functions work by calling a remote service to perform operations and return results. This provides a way for them to store each requested operation into a batch. Later you'll see how to create a `_pushOperation` function to batch the operations. First, review the following code example to see how to call `_pushOperation` from your custom function. In the following code, the custom function performs division but relies on a remote service to do the actual calculation. It calls `_pushOperation` to batch the operation along with other operations to the remote service. It names the operation **div2**. You can use any naming scheme you want for operations as long as the remote service is also using the same scheme (more on the remote service later). Also, the arguments the remote service will need to run the operation are passed. -### Add the div2 custom function +### Add the `div2` custom function Add the following code to your **functions.js** or **functions.ts** file (depending on if you used JavaScript or TypeScript). @@ -176,7 +177,7 @@ Add the following code to your **functions.js** or **functions.ts** file. ```javascript // This function simulates the work of a remote service. Because each service -// differs, you will need to modify this function appropriately to work with the service you are using. +// differs, modify this function as needed to work with the service you are using. // This function takes a batch of argument sets and returns a promise that may contain a batch of values. // NOTE: When implementing this function on a server, also apply an appropriate authentication mechanism // to ensure only the correct callers can access it. @@ -232,6 +233,18 @@ To modify the `_fetchFromRemoteService` function to run in your live remote serv - Apply an appropriate authentication mechanism. Ensure that only the correct callers can access the function. - Place the code in the remote service. +## When to avoid batching + +Batching adds a small delay and some extra code. Avoid batching in the following scenarios. + +| Scenario | Negative impact of batching | Recommendation | +|----------|-------------------|----------------| +| Single or very few calls | Extra wait for timer | Call service directly if list is still empty | +| Very large input data per call | Request might get too large | Limit size or send those calls alone | +| Some calls are much slower than others | One slow call delays faster ones | Group slow types separately | +| Need near-instant result (less than 50 ms) | Timer adds delay | Use a shorter timer or skip batching | +| Server already combines work | No benefit | Skip batching on the client | + ## Next steps Learn about [the various parameters](custom-functions-parameter-options.md) you can use in your custom functions. Or review the basics behind making [a web call through a custom function](custom-functions-web-reqs.md). diff --git a/docs/excel/custom-functions-custom-enums.md b/docs/excel/custom-functions-custom-enums.md new file mode 100644 index 0000000000..a982e6bc1d --- /dev/null +++ b/docs/excel/custom-functions-custom-enums.md @@ -0,0 +1,119 @@ +--- +title: Custom enums for custom functions +description: Create custom enums to use with your custom functions. +ms.date: 06/24/2025 +ms.localizationpriority: medium +--- + +# Create custom enums for your custom functions + +:::image type="content" source="../images/custom-functions-custom-enum-autocomplete.png" alt-text="The members of a custom enum displaying in the Excel AutoComplete menu."::: + +Custom enums give users Excel AutoComplete options for your custom functions. The members in your enum show up in the formula bar as suggestions. The planets in the preceding screenshot are an example of a custom enum that provides a set list. This article describes how to create custom enums and use them as parameters in your custom functions. + +## Define the custom enum + +Define your enum with the JSDoc tag `@customenum`. The corresponding JSON properties are then autogenerated in your custom function metadata. For more information about JSDoc tags and custom functions, see [Basics of JSDoc tags](custom-functions-json-autogeneration.md#basics-of-jsdoc-tags). + +> [!NOTE] +> Custom enums created with the `@customenum` JSDoc tag are only supported in TypeScript. They are not supported in JavaScript. To use custom enums with JavaScript functions, you must manually create your own JSON metadata. To learn more, see [Manually create JSON metadata: enums](custom-functions-json.md#enums). + +The following code snippet shows how to define and use a simple custom enum as a parameter. + +```typescript +/** + * A custom enum with descriptions and tooltips. + * @customenum {string} + */ +enum PLANETS { + /** Mercury is the first planet from the sun. */ + mercury = "Mercury", + + /** Venus is the second planet from the sun. */ + venus = "Venus", + + /** Earth is the third planet from the sun. */ + earth = "Earth", +} + +/** + * A sample function that uses the custom enum as a parameter. + * @customfunction + */ +function getPlanets(value: PLANETS): any { + return value; +} +``` + +## Use a custom enum multiple times + +A custom enum can be reused in multiple functions, and it can be used as multiple parameters of a single function. A function can also have multiple enums as parameters at the same time. An enum parameter can be repeating or optional. + +The following code sample shows a `NUMBERS` enum and a custom function that uses the enum multiple times as an input value. + +```typescript +/** +* Enum of numbers with descriptions and tooltips. +* @customenum {number} +*/ +enum NUMBERS { + /** One */ + One = 1, + + /** Two */ + Two = 2, + + /** Three */ + Three = 3, + + /** Four */ + Four = 4, + + /** Five */ + Five = 5 +} + +/** +* Enter multiple numbers from the NUMBERS enum and get the sum. +* @customfunction +* @param input Enter enum numbers. +* @returns +*/ +function addNumbers(input: NUMBERS[]): any { + const sum = input.reduce((acc, num) => acc + num, 0); + return "Sum: " + sum; +} +``` + +## Localize your custom enums + +Localizing custom enums is similar to [localizing custom functions](custom-functions-naming.md#localize-custom-functions). You must [manually create your JSON metadata](custom-functions-json.md) and then create a new JSON metadata file for each language. + +Note that only the `name` and `tooltip` properties within an enum should be localized to the target language. The `value` property should remain unchanged to avoid the need for handling multiple languages within your function body. + +The following JSON snippet shows the Chinese language localized `values` object for the planet Mercury. + +```json +"enums": [ + { + "id": "PLANETS", + "type": "string", + "values": [ + { + "name": "水星", + "value": "mercury", + "tooltip": "水星是距离太阳最近的行星" + } + ] + } +], +``` + +## Backwards compatibility + +Custom enums offer backwards compatibility. On older versions of Excel, parameters using a custom enum work as standard parameters without displaying in the Excel AutoComplete list. + +## See also + +- [Manually create JSON metadata for custom functions](custom-functions-json.md) +- [Autogenerate JSON metadata for custom functions](custom-functions-json-autogeneration.md) diff --git a/docs/excel/custom-functions-data-types-concepts.md b/docs/excel/custom-functions-data-types-concepts.md index 1909f316b5..f8642272cc 100644 --- a/docs/excel/custom-functions-data-types-concepts.md +++ b/docs/excel/custom-functions-data-types-concepts.md @@ -1,7 +1,7 @@ --- title: Custom functions and data types description: Use Excel data types with your custom functions and Office Add-ins. -ms.date: 10/17/2022 +ms.date: 06/22/2025 ms.topic: overview ms.custom: scenarios:getting-started ms.localizationpriority: medium @@ -9,7 +9,7 @@ ms.localizationpriority: medium # Use data types with custom functions in Excel -Data types expand the Excel JavaScript API to support data types beyond the original four cell value types (string, number, boolean, and error). Data types include support for web images, formatted number values, entities, and arrays within entities. +Data types expand the Excel JavaScript API to support data types beyond the original four cell value types (string, number, boolean, and error). Data types include support for web images, formatted numbers, entities, and arrays within entities. These data types amplify the power of custom functions, because custom functions accept data types as both input and output values. You can generate data types through custom functions, or take existing data types as function arguments into calculations. Once the JSON schema of a data type is set, this schema is maintained throughout the calculations. @@ -28,13 +28,13 @@ Custom functions projects include a JSON metadata file. This JSON metadata file For a full description of the manual JSON metadata creation process, see [Manually create JSON metadata for custom functions](custom-functions-json.md). See [allowCustomDataForDataTypeAny](custom-functions-json.md#allowcustomdatafordatatypeany) for additional details about this property. -## Output a formatted number value +## Output a formatted number -The following code sample shows how to create a [FormattedNumberCellValue](/javascript/api/excel/excel.formattednumbercellvalue) data type with a custom function. The function takes a basic number and a format setting as the input parameters and returns a formatted number value data type as the output. +The following code sample shows how to create a formatted number with a custom function. This uses the [DoubleCellValue](/javascript/api/excel/excel.doublecellvalue) object. The function takes a basic number and a format setting as the input parameters and returns a formatted number as double data type for the output. ```js /** - * Take a number as the input value and return a formatted number value as the output. + * Take a number as the input value and return a double as the output. * @customfunction * @param {number} value * @param {string} format (e.g. "0.00%") @@ -42,7 +42,7 @@ The following code sample shows how to create a [FormattedNumberCellValue](/java */ function createFormattedNumber(value, format) { return { - type: "FormattedNumber", + type: "Double", basicValue: value, numberFormat: format } @@ -57,7 +57,7 @@ The following code sample shows a custom function that takes an [EntityCellValue /** * Accept an entity value data type as a function input. * @customfunction - * @param {any} value + * @param {Excel.EntityCellValue} value * @param {string} attribute * @returns {any} The text value of the entity. */ diff --git a/docs/excel/custom-functions-debugging.md b/docs/excel/custom-functions-debugging.md index 237741fe1a..2a54e8f182 100644 --- a/docs/excel/custom-functions-debugging.md +++ b/docs/excel/custom-functions-debugging.md @@ -1,14 +1,14 @@ --- title: Custom functions debugging in a non-shared runtime -description: Learn how to debug your Excel custom functions that don't use a shared runtime. -ms.date: 01/26/2023 +description: Debug Excel custom functions that don't use a shared runtime. +ms.date: 10/22/2025 ms.topic: troubleshooting ms.localizationpriority: medium --- -# Custom functions debugging +# Custom functions debugging in a non-shared runtime -This article discusses debugging only for custom functions that **don't use a [shared runtime](../testing/runtimes.md#shared-runtime)**. To debug custom functions add-ins that use a shared runtime, see [Overview of debugging Office Add-ins](../testing/debug-add-ins-overview.md). +This article covers debugging only for custom functions that **don't use a [shared runtime](../testing/runtimes.md#shared-runtime)**. For shared runtime scenarios, see [Overview of debugging Office Add-ins](../testing/debug-add-ins-overview.md). [!include[Excel custom functions note](../includes/excel-custom-functions-note.md)] @@ -31,23 +31,20 @@ The process of debugging a custom function for add-ins that don't use a shared r ## Use the browser developer tools to debug custom functions in Excel on the web -You can use the browser developer tools to debug custom functions that don't use a shared runtime in Excel on the web. The following steps work for both Windows and macOS. +Use the browser developer tools to debug custom functions that don't use a shared runtime in Excel on the web. The following steps work for Windows and macOS. ### Run your add-in from Visual Studio Code 1. Open your custom functions root project folder in [Visual Studio Code (VS Code)](https://code.visualstudio.com/). -1. Choose **Terminal** > **Run Task** and type or select **Watch**. This will monitor and rebuild for any file changes. -1. Choose **Terminal** > **Run Task** and type or select **Dev Server**. +1. Choose **Terminal** > **Run Task** and run **Watch**. This will monitor and rebuild for any file changes. +1. Choose **Terminal** > **Run Task** and run **Dev Server**. ### Sideload your add-in 1. Open [Office on the web](https://office.live.com/). 1. Open a new Excel workbook. -1. Select **Home** > **Add-ins**, then select **Get Add-ins**. -1. On the **Office Add-ins** dialog, select the **MY ADD-INS** tab, choose **Manage My Add-ins**, and then **Upload My Add-in**. - - ![The Office Add-ins dialog with a drop-down in the upper right reading "Manage my add-ins" and a drop-down below it with the option "Upload My Add-in".](../images/office-add-ins-my-account.png) - +1. Select **Home** > **Add-ins**, then select **More Settings**. +1. On the **Office Add-ins** dialog, select **Upload My Add-in**. 1. **Browse** to the add-in manifest file, and then select **Upload**. ![The upload add-in dialog with buttons for browse, upload, and cancel.](../images/upload-add-in.png) @@ -57,32 +54,30 @@ You can use the browser developer tools to debug custom functions that don't use ### Start debugging -1. Open developer tools in the browser. For Chrome and most browsers F12 will open the developer tools. -1. In developer tools, open your source code script file using **Cmd+P** or **Ctrl+P** (**functions.js** or **functions.ts**). -1. [Set a breakpoint](https://code.visualstudio.com/Docs/editor/debugging#_breakpoints) in the custom function source code. +1. Open your browser's developer tools. In Chrome and most browsers, press F12 to open the developer tools. +1. In developer tools, open your source code script file using Cmd+P or Ctrl+P (**functions.js** or **functions.ts**). +1. [Set a breakpoint](https://code.visualstudio.com/Docs/editor/debugging#_breakpoints) in the custom function source code. -If you need to change the code you can make edits in VS Code and save the changes. Refresh the browser to see the changes loaded. +If you need to make changes, edit the code in VS Code, save your work, then refresh the workbook page to apply the update. ## Use the command line tools to debug -If you aren't using VS Code, you can use the command line (such as bash, or PowerShell) to run your add-in. You'll need to use the browser developer tools to debug your code in Excel on the web. You cannot debug the desktop version of Excel using the command line. +If you don't use VS Code, run your add-in from the command line using tools such as Bash or PowerShell. To debug your code in Excel on the web, use your browser's developer tools. 1. From the command line run `npm run watch` to watch for and rebuild when code changes occur. -1. Open a second command line window (the first one will be blocked while running the watch.) +1. Open a second command line window (the first one is busy while running the watch.) -1. If you want to start your add-in in the desktop version of Excel, run the following command. - - `npm run start:desktop` +1. If you want to start your add-in in the desktop version of Excel and the "scripts" section of the project's package.json file has a "start:desktop" script, then run `npm run start:desktop`; otherwise, run `npm run start`. Or if you prefer to start your add-in in Excel on the web run the following command. - `npm run start:web -- --document {url}` (where `{url}` is the URL of an Excel file on OneDrive or SharePoint) + `npm run start -- web --document {url}` (where `{url}` is the URL of an Excel file on OneDrive or SharePoint) [!include[Mac command line note](../includes/mac-command-line.md)] - If your add-in doesn't sideload in the document, follow the steps in [Sideload your add-in](#sideload-your-add-in) to sideload your add-in. Then continue to the next section to start debugging. + If your add-in doesn't sideload in the document, follow the steps in [Sideload your add-in](#sideload-your-add-in). Then continue to the next section to start debugging. -1. Open developer tools in the browser. For Chrome and most browsers F12 will open the developer tools. +1. Open your browser's developer tools. In Chrome and most browsers, press F12 to open the developer tools. 1. In developer tools, open your source code script file (**functions.js** or **functions.ts**). Your custom functions code may be located near the end of the file. 1. In the custom function source code, apply a breakpoint by selecting a line of code. @@ -90,17 +85,17 @@ If you need to change the code, you can make edits in VS Code and save the chang ### Commands for building and running your add-in -There are several build tasks available. +Available build tasks: - `npm run watch`: builds for development and automatically rebuilds when a source file is saved - `npm run build-dev`: builds for development once - `npm run build`: builds for production - `npm run dev-server`: runs the web server used for development -You can use the following tasks to start debugging on desktop or online. +Use these tasks to start debugging: -- `npm run start:desktop`: Starts Excel on desktop and sideloads your add-in. -- `npm run start:web -- --document {url}` (where `{url}` is the URL of an Excel file on OneDrive or SharePoint): Starts Excel on the web and sideloads your add-in. +- `npm run start:desktop`: Starts Excel on desktop and sideloads your add-in. If the "start:desktop" script isn't present in the "scripts" section of the project's package.json file, then run `npm run start` instead. +- `npm run start -- web --document {url}` (where `{url}` is the URL of an Excel file on OneDrive or SharePoint): Starts Excel on the web and sideloads your add-in. [!include[Mac command line note](../includes/mac-command-line.md)] diff --git a/docs/excel/custom-functions-errors.md b/docs/excel/custom-functions-errors.md index 0c4f9a18b0..2bb7fb4bd8 100644 --- a/docs/excel/custom-functions-errors.md +++ b/docs/excel/custom-functions-errors.md @@ -1,24 +1,24 @@ --- title: Handle and return errors from your custom function -description: 'Handle and return errors like #NULL! from your custom function.' -ms.date: 08/12/2021 +description: 'Return meaningful Excel errors (like #VALUE! and #N/A) from custom functions and map exceptions to user-friendly messages.' +ms.date: 10/22/2025 ms.localizationpriority: medium --- # Handle and return errors from your custom function -If something goes wrong while your custom function runs, return an error to inform the user. If you have specific parameter requirements, such as only positive numbers, test the parameters and throw an error if they aren't correct. You can also use a [`try...catch`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/try...catch) block to catch any errors that occur while your custom function runs. +When a custom function receives invalid input, can't access a resource, or fails to compute a result, return the most specific Excel error you can. Validate parameters early to fail promptly and use `try...catch` blocks to turn low-level exceptions into clear Excel errors. ## Detect and throw an error -Let's look at a case where you need to ensure that a zip code parameter is in the correct format for the custom function to work. The following custom function uses a regular expression to check the zip code. If the zip code format is correct, then it will look up the city using another function and return the value. If the format isn't valid, the function returns a `#VALUE!` error to the cell. +The following example validates a U.S. ZIP Code with a regular expression before continuing. If the format is invalid, it throws a `#VALUE!` error. ```typescript /** -* Gets a city name for the given U.S. zip code. +* Gets a city name for the given U.S. ZIP Code. * @customfunction * @param {string} zipCode -* @returns The city of the zip code. +* @returns The city of the ZIP Code. */ function getCity(zipCode: string): string { let isValidZip = /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(zipCode); @@ -30,7 +30,7 @@ function getCity(zipCode: string): string { ## The CustomFunctions.Error object -The [CustomFunctions.Error](/javascript/api/custom-functions-runtime/customfunctions.error) object is used to return an error back to the cell. When you create the object, specify which error you want to use by choosing one of the following `ErrorCode` enum values. +The [CustomFunctions.Error](/javascript/api/custom-functions-runtime/customfunctions.error) object returns an error to the cell. Specify which error by choosing an `ErrorCode` value from the following list. |ErrorCode enum value |Excel cell value |Description | |---------------|---------|---------| @@ -59,7 +59,7 @@ throw error; ### Handle errors when working with dynamic arrays -In addition to returning a single error, a custom function can output a dynamic array that includes an error. For example, a custom function could output the array `[1],[#NUM!],[3]`. The following code sample shows how to input three parameters into a custom function, replace one of the input parameters with a `#NUM!` error, and then return a 2-dimensional array with the results of processing each input parameter. +Custom functions can return dynamic arrays that include errors. For example, a custom function could output the array `[1],[#NUM!],[3]`. The following code sample shows how to pass three parameters into a custom function, replace one parameter with a `#NUM!` error, and then return a two-dimensional array with the results for each input. ```js /** @@ -98,9 +98,9 @@ To process inputs that contain errors, a custom function must have the JSON meta ## Use `try...catch` blocks -In general, use [`try...catch`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/try...catch) blocks in your custom function to catch any potential errors that occur. If you don't handle exceptions in your code, they will be returned to Excel. By default, Excel returns `#VALUE!` for unhandled errors or exceptions. +Use [`try...catch`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/try...catch) blocks to catch potential errors and return meaningful error messages to your users. By default, Excel returns `#VALUE!` for unhandled errors or exceptions. -In the following code sample, the custom function makes a fetch call to a REST service. It's possible that the call will fail, for example, if the REST service returns an error or the network goes down. If this happens, the custom function will return `#N/A` to indicate that the web call failed. +In the following code sample, the custom function uses fetch to call a REST service. If the call fails, such as when the REST service returns an error or the network is unavailable, the custom function returns `#N/A` to show that the web call failed. ```typescript /** diff --git a/docs/excel/custom-functions-formula-value-preview.md b/docs/excel/custom-functions-formula-value-preview.md new file mode 100644 index 0000000000..9ec239a3bd --- /dev/null +++ b/docs/excel/custom-functions-formula-value-preview.md @@ -0,0 +1,46 @@ +--- +title: Work with formula value preview mode in your custom functions +description: Work with formula value preview mode in your custom functions +ms.date: 05/15/2025 +ms.localizationpriority: medium +--- + +# Work with formula value preview mode in your custom functions + +You can control how your custom function calculates results when participating in formula value preview mode. Formula value preview mode is a feature that allows end users to select portions of a formula while editing the cell to preview the values. This feature helps users evaluate the formula as they edit it. The following image shows an example of the user editing a formula and selecting the text `A1+A2`. The formula preview mode shows the value `7` above. + +:::image type="content" source="../images/excel-formula-value-preview.png" alt-text="Screenshot of Excel formula editor with A1+A2 selected and a preview value of 7 displayed above the formula editor."::: + +By default, custom functions (for example `=getHousePrice(A1)`) can be previewed by the user. However, the following list shows some scenarios in which you may want to control how your custom function participates in formula value preview mode. + +- Your custom function calls one or more APIs that charge a rate for using them. +- Your custom function accesses one or more scarce resources such as databases. +- Your custom function takes significant time to calculate the result, and it wouldn’t be useful for a user during preview purposes. + +You can change the behavior of your custom function to return a mock value instead. To do this use the `invocation.isInValuePreview` read-only property. The following code sample shows an example custom function named `getHousePrice` that looks up house prices through a monetized API. If `isInValuePreview` is `true`, the custom function returns a mock number to be used and avoids incurring any cost. If `isInValuePreview` is `false`, the custom function calls the API and returns the actual house price value for use in the Excel spreadsheet. + +```javascript +/** + * Get the listing price for a house on the market for the given address. + * @customfunction + * @param address The address of the house. + * @param invocation Custom function handler. + * @returns The price of the house at the address. + */ +export function getHousePrice(address: string, invocation: CustomFunctions.Invocation): number { + // Check if this call is for formula value preview mode. + if (invocation.isInValuePreview) { + // Avoid long-running expensive service calls. + // Return a useable but fake number. + return 450000; + } else { + // Make the actual service calls in this block. + const price = callHouseServiceAPI(address); + return price; + } +} +``` + +## See also + +- [Create custom functions in Excel](custom-functions-overview.md) diff --git a/docs/excel/custom-functions-get-started.md b/docs/excel/custom-functions-get-started.md new file mode 100644 index 0000000000..645fcf787d --- /dev/null +++ b/docs/excel/custom-functions-get-started.md @@ -0,0 +1,159 @@ +--- +description: Tips and best practices for Excel custom functions in your Office Add-ins. +title: Best practices for custom functions in Excel +ms.date: 06/22/2025 +ms.topic: overview +ms.custom: scenarios:getting-started +ms.localizationpriority: medium +--- + +# Best practices for custom functions in Excel + +This article includes tips, best practices, and Office Add-ins ecosystem information for new developers of custom functions add-ins. + +The following diagram illustrates the interaction between a custom function and the two main components involved in custom function add-ins: Excel and external services. + +:::image type="content" source="../images/custom-functions-add-in-components.png" alt-text="The custom functions add-in communicates with both Excel and an external service, but Excel and the external service don't communicate directly with each other."::: + +**Excel** allows you to integrate your own custom functions into the application and run them like built-in functions. + +The **custom functions add-in** defines the logic for your functions and how they interact with Excel and Office JavaScript APIs. To learn how to create a custom functions add-in, see the [custom functions tutorial](../tutorials/excel-tutorial-create-custom-functions.md). + +An **external service** is optional. It can give your add-in capabilities like importing data from outside the workbook. The custom functions add-in specifies how external data is incorporated into the workbook. To learn more, see [Receive and handle data with custom functions](custom-functions-web-reqs.md). + +## Optimize custom functions recalculation efficiency + +In general, custom functions recalculation follows the established pattern of [recalculation in Excel](/office/client-developer/excel/excel-recalculation). When recalculation is triggered, Excel enters a three-stage process: construct a dependency tree, construct a calculation chain, and then recalculate the cells. To optimize recalculation efficiency in your add-in, consider the level of nesting within your custom functions, the Excel calculation mode, and the limitations of volatile functions. + +### Nesting in custom functions + +A custom function can accept another custom function as an argument, making the argument a nested custom function. The recalculation of the outer custom function depends on the result of the nested function, leading to increased time consumption with each additional nested function. Minimize the number of nested levels in your custom functions to improve recalculation efficiency. The following code snippets demonstrate two approaches for adding values in the workbook that produce similar outputs. **Option 1** uses an array to call values as a single parameter, while **Option 2** calls each value as a separate parameter, so **Option 1** is more efficient. + +#### Option 1: Increase efficiency with limited nesting + +> [!NOTE] +> This is the recommended approach. It uses an array to call values as a single parameter and avoid unnecessary nesting, so it's more efficient than **Option 2**. + +```js + /** + * Returns the sum of input numbers. + * @customfunction + */ + function Add(args: number[]): number { + let total = 0; + args.forEach(value => { + total += value; + }); + + return total; + } +``` + +#### Option 2: More nesting is inefficient + +> [!NOTE] +> This approach isn't recommended. **Option 1** and **Option 2** produce similar outputs, but **Option 2** uses more parameters and is less efficient. + +```js + /** + * Returns the sum of two numbers. + * @customfunction + */ + function Add(arg1: number, arg2: number): number { + return arg1 + arg2; + } +``` + +### Excel calculation modes + +Excel has three calculation modes: Automatic, Automatic Except Tables, and Manual. To determine which calculation mode best fits your custom function design, refer to the [Calculation Modes, Commands, Selective Recalculation, and Data Table](/office/client-developer/excel/excel-recalculation#calculation-modes-commands-selective-recalculation-and-data-tables#calculation-modes-commands-selective-recalculation-and-data-tables) section in the main [Excel Recalculation](/office/client-developer/excel/excel-recalculation) article. + +Set the calculation mode for your add-in with the [Excel.CalculationMode enum](/javascript/api/excel/excel.calculationmode) based on your scenario. Note that `automatic` calculation mode may trigger recalculation often and reduce the efficiency of your add-in. + +### Volatile function limitations + +Custom functions allow you to create your own volatile functions, similar to the `NOW` and `TODAY` functions in Excel. During recalculation, Excel evaluates cells that contain volatile functions and all of their dependent cells. As a result, using many volatile functions may slow recalculation time so limit the number of volatile functions in your add-in to optimize efficiency. For additional information, see [Volatile and Non-Volatile Functions](/office/client-developer/excel/excel-recalculation#volatile-and-non-volatile-functions). + +## Design approaches to improve efficiency + +Custom functions add-ins allow for flexible designs, which means that different add-in designs can produce the same output for your end users. + +### Multiple results + +You can return multiple results from your custom function with multiple functions or with one function. + +To return multiple results with one function, use a dynamic array. This is usually the recommended approach because dynamic arrays only require updating a single cell to trigger recalculation for all results. + +:::image type="content" source="../images/custom-functions-dynamic-array.png" alt-text="The output of a dynamic array."::: + +Keep in mind that using dynamic arrays becomes less efficient the larger your dataset is, because each recalculation processes more data. To learn more about dynamic arrays in custom functions, see [Return multiple results from your custom function](custom-functions-dynamic-arrays.md). + +Another way to return multiple results is to use multiple functions and return a single result for each function. A benefit of using multiple functions is that your end user can decide precisely which formula they want to update and then only trigger recalculation for that formula. This is particularly helpful when relying on external services that may respond slowly. + +:::image type="content" source="../images/custom-functions-not-dynamic-array.png" alt-text="The output of multiple functions instead of a dynamic array."::: + +### Complex data structures + +[Data types](custom-functions-data-types-concepts.md) are the best way to handle complex data structures in custom functions add-ins. Data types support [Excel errors](custom-functions-errors.md) and formatted numbers as [doubles](custom-functions-data-types-concepts.md#output-a-formatted-number). Data types also allow for designing [entity value cards](excel-data-types-entity-card.md), extending Excel data beyond the 2-dimensional grid. + +## Improve the user experience of calls to external services + +Custom functions can fetch data from remote locations beyond the workbook, such as the web or a server. For more information about fetching data from an external service, see [Receive and handle data with custom functions](custom-functions-web-reqs.md). To maintain efficiency when calling external services, consider batching external calls, minimizing roundtrip duration for each call, and including messages in your add-in to communicate delays to your end user. + +### Batch custom function remote calls + +If your custom functions call a remote service, use a batching pattern to reduce the number of network calls to the remote service. To learn more, see [Batching custom function calls for a remote service](custom-functions-batching.md). + +### Minimize roundtrip duration + +Remote service connections can have a large impact on custom function performance. To reduce this impact, use these strategies: + +- Server-heavy processing should be handled efficiently in the remote server to shorten the end-to-end latency for a custom function. For example, have parallel computing designed on the server. If your service is deployed on Azure, consider optimization using [high-performance computing on Azure](/azure/architecture/topics/high-performance-computing). +- Reduce the number of service calls by optimizing the add-in flow. For example, only send necessary calls to a remote service. + +### Improve user-perceived performance through add-in user experience (UX) + +While a custom function is calling an external service, the cell with the custom function displays the **#BUSY!** error. If a delay while calling an external service is inevitable, consider providing messages through the add-in task pane to explain the delay to your end users. This information helps manage their expectations. The following image shows an example. + +:::image type="content" source="../images/custom-functions-delay-example.png" alt-text="The delay message says 'There may be a delay. We're getting the data ready for you'."::: + +For more information about how to share data between a custom function and a task pane, see [Share data and events between Excel custom functions and the task pane](../tutorials/share-data-and-events-between-custom-functions-and-the-task-pane-tutorial.md). + +To display a message in the add-in task pane that notifies users of a delay, make the following changes after ensuring that your add-in uses a shared runtime. + +1. In **taskpane.js** add a function that calls the notification. + + ```js + export function showNotification(message){ + const label = document.getElementById("item-subject"); + label.innerHTML = message; + } + ``` + +1. In **function.js**, import the `showNotification` function. + + ```js + export function showNotification(message){ + const label = document.getElementById("item-subject"); + label.innerHTML = message; + } + ``` + +1. In **function.js**, call `showNotification` when running the calculation that may include a delay. + + ```js + export async function longCalculation(param) { + await Office.addin.showAsTaskpane(); + showNotification("It may take some time as we prepare the data."); + // Perform long operation + // ... + // ... + return answer; + } + ``` + +## See also + +- [Receive and handle data with custom functions](custom-functions-web-reqs.md) +- [Batch custom function calls for a remote service](custom-functions-batching.md) +- [Create custom functions in Excel tutorial](../tutorials/excel-tutorial-create-custom-functions.md) diff --git a/docs/excel/custom-functions-json-autogeneration.md b/docs/excel/custom-functions-json-autogeneration.md index 9426190dba..d1a661852d 100644 --- a/docs/excel/custom-functions-json-autogeneration.md +++ b/docs/excel/custom-functions-json-autogeneration.md @@ -1,7 +1,7 @@ --- title: Autogenerate JSON metadata for custom functions description: Use JSDoc tags to dynamically create your custom functions JSON metadata. -ms.date: 07/11/2023 +ms.date: 06/19/2025 ms.localizationpriority: medium --- @@ -23,7 +23,7 @@ The plugin is [CustomFunctionsMetadataPlugin](https://github.com/OfficeDev/Offic 1. Open a Command Prompt or bash shell and, in the root of the project, run `npm install custom-functions-metadata-plugin`. 1. Open the webpack.config.js file and add the following line at the top: `const CustomFunctionsMetadataPlugin = require("custom-functions-metadata-plugin");`. -1. Scroll down to the `plugins` array and add the following to the top of the array. Change the `input` path and filename as needed to match your project, but the `output` value must be "functions.json". If you're using TypeScript, use the \*.ts source file name, *not* the transpiled \*.js file. +1. Scroll down to the `plugins` array and add the following to the top of the array. Change the `input` path and filename as needed to match your project, but the `output` value must be `"functions.json"`. If you're using TypeScript, use the \*.ts source file name, *not* the transpiled \*.js file. ```js new CustomFunctionsMetadataPlugin({ @@ -34,7 +34,7 @@ The plugin is [CustomFunctionsMetadataPlugin](https://github.com/OfficeDev/Offic ### Multiple custom function source files -If, and only if, you have organized your custom functions into multiple source files, there are additional steps. +If, and only if, you have organized your custom functions into multiple source files, there are additional steps. 1. In the webpack.config.js file, replace the string value of `input` with an array of string URLs that point to each of the files. The following is an example: @@ -92,8 +92,12 @@ In the following example, the phrase "Calculates the volume of a sphere." is the The following JSDoc tags are supported in Excel custom functions. - [@cancelable](#cancelable) +- [@capturesCallingObject](#capturesCallingObject) +- [@customenum](#customenum) *{type}* - [@customfunction](#customfunction) *id* *name* +- [@excludeFromAutoComplete](#excludeFromAutoComplete) - [@helpurl](#helpurl) *url* +- [@linkedEntityLoadService](#linkedEntityLoadService) - [@param](#param) *{type}* *name* *description* - [@requiresAddress](#requiresAddress) - [@requiresParameterAddresses](#requiresParameterAddresses) @@ -114,6 +118,20 @@ If the last function parameter is of type `CustomFunctions.CancelableInvocation` A function can't have both `@cancelable` and `@streaming` tags. + + +### @capturesCallingObject + +This tag works with Excel [data types](excel-data-types-overview.md). It specifies that the data type being referenced by the custom function is passed as the first argument to the custom function. For more information, see [Reference the entity value as a calling object](excel-add-ins-dot-functions.md#reference-the-entity-value-as-a-calling-object). + + + +### @customenum + +Syntax: @customenum *{type}* + +This tag indicates that a set of values is a custom enum. For more information, see [Create custom enums for your custom functions](custom-functions-custom-enums.md). + ### @customfunction @@ -183,6 +201,14 @@ In the following example, the phrase "A function that adds two numbers" is the d */ ``` + + +### @excludeFromAutoComplete + +The `@excludeFromAutoComplete` tag ensures that the custom function doesn't appear in the formula AutoComplete menu in Excel. For more information, see [Exclude custom functions from the Excel UI](excel-add-ins-dot-functions.md#exclude-custom-functions-from-the-excel-ui). + +A function can’t have both `@excludeFromAutoComplete` and `@linkedEntityLoadService` tags. + ### @helpurl @@ -202,6 +228,14 @@ In the following example, the `helpurl` is `http://www.contoso.com/weatherhelp`. */ ``` + + +### @linkedEntityLoadService + +The `@linkedEntityLoadService` tag designates that the function is a linked entity load service that returns [linked entity cell values](excel-data-types-linked-entity-cell-values.md) for linked entity IDs requested by Excel. + +A function can’t have both `@excludeFromAutoComplete` and `@linkedEntityLoadService` tags. + ### @param @@ -395,6 +429,22 @@ By specifying a parameter type, Excel will convert values into that type before A single value may be represented using one of the following types: `boolean`, `number`, `string`. +### Cell value type + +Use the `type` subfield `cellValueType` to specify that a custom function accept and return Excel data types. The `type` value must be `any` to use the `cellValueType` subfield. Accepted `cellValueType` values are: + +- `Excel.CellValue` +- `Excel.BooleanCellValue` +- `Excel.DoubleCellValue` +- `Excel.EntityCellValue` +- `Excel.ErrorCellValue` +- `Excel.LinkedEntityCellValue` +- `Excel.LocalImageCellValue` +- `Excel.StringCellValue` +- `Excel.WebImageCellValue` + +For a code sample using the `Excel.EntityCellValue` type, see [Input an entity value](custom-functions-data-types-concepts.md#input-an-entity-value). + ### Matrix type Use a two-dimensional array type to have the parameter or return value be a matrix of values. For example, the type `number[][]` indicates a matrix of numbers and `string[][]` indicates a matrix of strings. diff --git a/docs/excel/custom-functions-json.md b/docs/excel/custom-functions-json.md index a58f673ac0..3201e4b3c2 100644 --- a/docs/excel/custom-functions-json.md +++ b/docs/excel/custom-functions-json.md @@ -1,7 +1,7 @@ ---- +--- title: Manually create JSON metadata for custom functions in Excel description: Define JSON metadata for custom functions in Excel and associate your function ID and name properties. -ms.date: 10/10/2022 +ms.date: 10/27/2025 ms.localizationpriority: medium --- @@ -24,13 +24,13 @@ The following image explains the differences between using `yo office` scaffold ![Image of differences between using the Yeoman generator for Office Add-ins and writing your own JSON.](../images/custom-functions-json.png) > [!NOTE] -> Remember to connect your manifest to the JSON file you create, through the **\** section in your add-in only manifest file if you do not use the [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md). +> Remember to connect your manifest to the JSON file you create, through the `` section in your add-in only manifest file if you do not use the [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md). ## Authoring metadata and connecting to the manifest Create a JSON file in your project and provide all the details about your functions in it, such as the function's parameters. See the [following metadata example](#json-metadata-example) and [the metadata reference](#metadata-reference) for a complete list of function properties. -Ensure your add-in only manifest file references your JSON file in the **\** section, similar to the following example. +Ensure your add-in only manifest file references your JSON file in the `` section, similar to the following example. ```json @@ -110,22 +110,35 @@ The following example shows the contents of a JSON metadata file for an add-in t } }, { - "id": "SECONDHIGHEST", - "name": "SECONDHIGHEST", - "description": "Get the second highest number from a range", - "helpUrl": "http://www.contoso.com/help", - "result": { - "dimensionality": "scalar" - }, - "parameters": [ - { - "name": "range", - "description": "the input range", - "type": "number", - "dimensionality": "matrix" + "id": "GETPLANETS", + "name": "GETPLANETS", + "description": "A function that uses the custom enum as a parameter.", + "parameters": [ + { + "name": "value", + "type": "string", + "customEnumType": "PLANETS" } ] } + ], + "enums": [ + { + "id": "PLANETS", + "type": "string", + "values": [ + { + "name": "Mercury", + "value": "mercury", + "tooltip": "Mercury is the first planet from the sun." + }, + { + "name": "Venus", + "value": "venus", + "tooltip": "Venus is the second planet from the sun." + } + ] + } ] } ``` @@ -137,14 +150,16 @@ The following example shows the contents of a JSON metadata file for an add-in t ### allowCustomDataForDataTypeAny -The `allowCustomDataForDataTypeAny` property is a boolean data type. Setting this value to `true` allows a custom function to accept data types as parameters and return values. To learn more, see [Custom functions and data types](custom-functions-data-types-concepts.md). +The `allowCustomDataForDataTypeAny` property is a Boolean data type. Setting this value to `true` allows a custom function to accept data types as parameters and return values. To learn more, see [Custom functions and data types](custom-functions-data-types-concepts.md). > [!NOTE] > Unlike most of the other JSON metadata properties, `allowCustomDataForDataTypeAny` is a top-level property and contains no sub-properties. See the preceding [JSON metadata code sample](#json-metadata-example) for an example of how to format this property. +If your custom function uses the `cellValueType` [parameter](#parameters), then setting the `allowCustomDataForDataTypeAny` isn't required to accept data types as parameters and return values. + ### allowErrorForDataTypeAny -The `allowErrorForDataTypeAny` property is a boolean data type. Setting the value to `true` allows a custom function to process errors as input values. All parameters with the type `any` or `any[][]` can accept errors as input values when `allowErrorForDataTypeAny` is set to `true`. The default `allowErrorForDataTypeAny` value is `false`. +The `allowErrorForDataTypeAny` property is a Boolean data type. Setting the value to `true` allows a custom function to process errors as input values. All parameters with the type `any` or `any[][]` can accept errors as input values when `allowErrorForDataTypeAny` is set to `true`. The default `allowErrorForDataTypeAny` value is `false`. > [!NOTE] > Unlike the other JSON metadata properties, `allowErrorForDataTypeAny` is a top-level property and contains no sub-properties. See the preceding [JSON metadata code sample](#json-metadata-example) for an example of how to format this property. @@ -156,24 +171,42 @@ The `functions` property is an array of custom function objects. The following t | Property | Data type | Required | Description | | :------------ | :-------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `description` | string | No | The description of the function that end users see in Excel. For example, **Converts a Celsius value to Fahrenheit**. | -| `helpUrl` | string | No | URL that provides information about the function. (It is displayed in a task pane.) For example, `http://contoso.com/help/convertcelsiustofahrenheit.html`. | +| `helpUrl` | string | No | URL that provides information about the function. For example, `http://contoso.com/help/convertcelsiustofahrenheit.html`. | | `id` | string | Yes | A unique ID for the function. This ID can only contain alphanumeric characters and periods and should not be changed after it is set. | | `name` | string | Yes | The name of the function that end users see in Excel. In Excel, this function name is prefixed by the custom functions namespace that's specified in the add-in only manifest file. | | `options` | object | No | Enables you to customize some aspects of how and when Excel executes the function. See [options](#options) for details. | | `parameters` | array | Yes | Array that defines the input parameters for the function. See [parameters](#parameters) for details. | | `result` | object | Yes | Object that defines the type of information that is returned by the function. See [result](#result) for details. | +### enums + +The `enums` property is an array of [enum](https://www.typescriptlang.org/docs/handbook/enums.html) objects. The following table lists the properties of each object. + +> [!TIP] +> To learn about creating custom enums for your custom functions, see [Create custom enums for your custom functions](custom-functions-custom-enums.md). To learn about editing metadata for custom enums, see [Edit custom enums in JSON metadata](#edit-custom-enums-in-json-metadata). + +| Property | Data type | Required | Description | +| :------------ | :-------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `name` | string | Yes | A brief description of the constant. | +| `tooltip` | string | No | Additional information about the constant that can be shown as a tooltip in user interfaces. | +| `value` | string | Yes | The value of the constant. | + ### options The `options` object enables you to customize some aspects of how and when Excel executes the function. The following table lists the properties of the `options` object. | Property | Data type | Required | Description | | :---------------- | :-------- | :------------------------------------- | :---------- | -| `cancelable` | boolean | No

Default value is `false`. | If `true`, Excel calls the `CancelableInvocation` handler whenever the user takes an action that has the effect of canceling the function; for example, manually triggering recalculation or editing a cell that is referenced by the function. Cancelable functions are typically only used for asynchronous functions that return a single result and need to handle the cancellation of a request for data. A function can't use both the `stream` and `cancelable` properties. | -| `requiresAddress` | boolean | No

Default value is `false`. | If `true`, your custom function can access the address of the cell that invoked it. The `address` property of the [invocation parameter](custom-functions-parameter-options.md#invocation-parameter) contains the address of the cell that invoked your custom function. A function can't use both the `stream` and `requiresAddress` properties. | -| `requiresParameterAddresses` | boolean | No

Default value is `false`. | If `true`, your custom function can access the addresses of the function's input parameters. This property must be used in combination with the `dimensionality` property of the [result](#result) object, and `dimensionality` must be set to `matrix`. See [Detect the address of a parameter](custom-functions-parameter-options.md#detect-the-address-of-a-parameter) for more information. | -| `stream` | boolean | No

Default value is `false`. | If `true`, the function can output repeatedly to the cell even when invoked only once. This option is useful for rapidly-changing data sources, such as a stock price. The function should have no `return` statement. Instead, the result value is passed as the argument of the `StreamingInvocation.setResult` callback function. For more information, see [Make a streaming function](custom-functions-web-reqs.md#make-a-streaming-function). | -| `volatile` | boolean | No

Default value is `false`. | If `true`, the function recalculates each time Excel recalculates, instead of only when the formula's dependent values have changed. A function can't use both the `stream` and `volatile` properties. If the `stream` and `volatile` properties are both set to `true`, the volatile property will be ignored. | +| `cancelable` | Boolean | No

Default value is `false`. | If `true`, Excel calls the `CancelableInvocation` handler whenever the user takes an action that has the effect of canceling the function; for example, manually triggering recalculation or editing a cell that is referenced by the function. Cancelable functions are typically only used for asynchronous functions that return a single result and need to handle the cancellation of a request for data. A function can't use both the `stream` and `cancelable` properties. | +| `capturesCallingObject` | Boolean | No

Default value is `false`. | If `true`, the data type being referenced by the custom function is passed as the first argument to the custom function. For more information, see [Reference the entity value as a calling object](excel-add-ins-dot-functions.md#reference-the-entity-value-as-a-calling-object). | +| `excludeFromAutoComplete` | Boolean | No

Default value is `false`. | If `true`, the custom function doesn't appear in the formula AutoComplete menu in Excel. For more information, see [Exclude custom functions from the Excel UI](excel-add-ins-dot-functions.md#exclude-custom-functions-from-the-excel-ui). A function can’t have both `excludeFromAutoComplete` and `linkedEntityLoadService` properties set to `true`. | +| `linkedEntityLoadService` | Boolean | No

Default value is `false`. | If `true`, the custom function provides a load service that returns up-to-date linked entity cell values for any linked entity IDs requested by Excel. A function can’t have both `excludeFromAutoComplete` and `linkedEntityLoadService` properties set to `true`. For more information, see [Linked entity load service function](excel-data-types-linked-entity-cell-values.md#linked-entity-load-service-function). | +| `requiresAddress` | Boolean | No

Default value is `false`. | If `true`, your custom function can access the address of the cell that invoked it. The `address` property of the [invocation parameter](custom-functions-parameter-options.md#invocation-parameter) contains the address of the cell that invoked your custom function. A function can't use both the `stream` and `requiresAddress` properties. | +| `requiresParameterAddresses` | Boolean | No

Default value is `false`. | If `true`, your custom function can access the addresses of the function's input parameters. This property must be used in combination with the `dimensionality` property of the [result](#result) object, and `dimensionality` must be set to `matrix`. See [Detect the address of a parameter](custom-functions-parameter-options.md#detect-the-address-of-a-parameter) for more information. | +| `requiresStreamAddress` | Boolean | No

Default value is `false`. | If `true`, the function can access the address of the cell calling the streaming function. The `address` property of the [invocation parameter](custom-functions-parameter-options.md#invocation-parameter) contains the address of the cell that invoked your streaming function. The function must also have `stream` set to `true`. | +| `requiresStreamParameterAddresses` | Boolean | No

Default value is `false`. | If `true`, the function can access the parameter addresses of the cell calling the streaming function. The `parameterAddresses` property of the [invocation parameter](custom-functions-parameter-options.md#invocation-parameter) contains the parameter addresses for your streaming function. The function must also have `stream` set to `true`. | +| `stream` | Boolean | No

Default value is `false`. | If `true`, the function can output repeatedly to the cell even when invoked only once. This option is useful for rapidly-changing data sources, such as a stock price. The function should have no `return` statement. Instead, the result value is passed as the argument of the `StreamingInvocation.setResult` callback function. For more information, see [Make a streaming function](custom-functions-web-reqs.md#make-a-streaming-function). | +| `volatile` | Boolean | No

Default value is `false`. | If `true`, the function recalculates each time Excel recalculates, instead of only when the formula's dependent values have changed. A function can't use both the `stream` and `volatile` properties. If the `stream` and `volatile` properties are both set to `true`, the volatile property will be ignored. | ### parameters @@ -185,8 +218,24 @@ The `parameters` property is an array of parameter objects. The following table | `dimensionality` | string | No | Must be either `scalar` (a non-array value) or `matrix` (a 2-dimensional array). | | `name` | string | Yes | The name of the parameter. This name is displayed in Excel's IntelliSense. | | `type` | string | No | The data type of the parameter. Can be `boolean`, `number`, `string`, or `any`, which allows you to use of any of the previous three types. If this property is not specified, the data type defaults to `any`. | -| `optional` | boolean | No | If `true`, the parameter is optional. | -|`repeating`| boolean | No | If `true`, parameters populate from a specified array. Note that functions all repeating parameters are considered optional parameters by definition. | +| `cellValueType` | string | No | A subfield of the `type` property. Specifies the Excel data types accepted by the custom function. Accepts the case-insensitive values `cellvalue`, `booleancellvalue`, `doublecellvalue`, `entitycellvalue`, `errorcellvalue`, `linkedentitycellvalue`, `localimagecellvalue`, `stringcellvalue`, and `webimagecellvalue`.

The `type` field must have the value `any` to use the `cellValueType` subfield. | +| `customEnumType` | string | No | The `id` of the enum in the `enums` array. This associates the custom enum with the function and enables Excel to display the enum members in the formula AutoComplete menu. | +| `optional` | Boolean | No | If `true`, the parameter is optional. | +|`repeating`| Boolean | No | If `true`, parameters populate from a specified array. Note that all repeating parameters are considered optional parameters by definition. | + +> [!TIP] +> See the following code snippet for an example of how to format the `cellValueType` parameter in JSON metadata. +> +> ```json +> "parameters": [ +> { +> "name": "range", +> "description": "the input range", +> "type": "any", +> "cellValueType": "webimagecellvalue" +> } +> ] +> ``` ### result @@ -197,7 +246,7 @@ The `result` object defines the type of information that is returned by the func | `dimensionality` | string | No | Must be either `scalar` (a non-array value) or `matrix` (a 2-dimensional array). | | `type` | string | No | The data type of the result. Can be `boolean`, `number`, `string`, or `any` (which allows you to use of any of the previous three types). If this property is not specified, the data type defaults to `any`. | -## Associating function names with JSON metadata +## Associate function names with JSON metadata For a function to work properly, you need to associate the function's `id` property with the JavaScript implementation. Make sure there is an association, otherwise the function won't be registered and isn't useable in Excel. The following code sample shows how to make the association using the `CustomFunctions.associate()` function. The sample defines the custom function `add` and associates it with the object in the JSON metadata file where the value of the `id` property is **ADD**. @@ -275,6 +324,77 @@ The following sample shows the JSON metadata that corresponds to the functions d } ``` +## Edit custom enums in JSON metadata + +Create or edit enum metadata directly with the `enums` property. Each custom enum must have a unique ID value and type value of either `string` or `number`. Mixed type enums are not supported. + +If you manually create the JSON metadata for your custom enum, you can associate those enums with either TypeScript or JavaScript custom functions. To learn more about creating custom enums, see [Create custom enums for your custom functions](custom-functions-custom-enums.md). + +The following JSON snippet shows the metadata for two enums: a `PLANETS` enum that contains the planets Mercury and Venus, and a `DAYS` enum that includes the days Monday and Tuesday. + +```json +"enums": [ + { + "id": "PLANETS", + "type": "string", + "values": [ + { + "name": "Mercury", + "value": "mercury", + "tooltip": "Mercury is the first planet from the sun." + }, + { + "name": "Venus", + "value": "venus", + "tooltip": "Venus is the second planet from the sun." + } + ] + }, + { + "id": "DAYS", + "type": "number", + "values": [ + { + "name": "Monday", + "value": 1, + "tooltip": "Monday is the first working day of a week." + }, + { + "name": "Tuesday", + "value": 2, + "tooltip": "Tuesday is the second working day of a week." + } + ] + } +] +``` + +Each constant in the `values` array of the enum is an object with the following properties. + +- **value**: The value of the constant. +- **name**: A brief description of the constant. +- **tooltip** (Optional): Additional information about the constant that can be shown as a tooltip in user interfaces. + +To associate the custom enum with a function, add the property `customEnumType` to the `parameters` object. The `customEnumType` value should match the `id` of the enum. Note that the `customEnumType` value is not case-sensitive. The following JSON snippet shows a `functions` object associated with the `PLANETS` enum. + +```json +"functions": [ + { + "description": "A function that uses the custom enum as a parameter.", + "id": "GETPLANETS", + "name": "GETPLANETS", + "parameters": [ + { + "name": "value", + "type": "string", + "customEnumType": "PLANETS" + } + ], + "result": {} + } +] +``` + ## Next steps Learn the [best practices for naming your function](custom-functions-naming.md) or discover how to [localize your function](custom-functions-naming.md#localize-custom-functions) using the previously described handwritten JSON method. diff --git a/docs/excel/custom-functions-naming.md b/docs/excel/custom-functions-naming.md index 06053a8020..ea098d5171 100644 --- a/docs/excel/custom-functions-naming.md +++ b/docs/excel/custom-functions-naming.md @@ -1,75 +1,87 @@ --- title: Naming and localization for custom functions in Excel description: Learn requirements for names of Excel custom functions and how to localize custom functions. -ms.date: 02/29/2024 +ms.date: 10/22/2025 ms.localizationpriority: medium --- + # Custom functions naming and localization -This article describes guidelines and best practices for naming custom functions. It also shows how to localize custom function names to languages other than English. +This article provides guidelines and best practices for naming custom functions and explains how to localize them. ## Custom functions naming guidelines -A custom function is identified by an `id` and `name` property in the JSON metadata file. +A custom function is identified by an `id` and a `name` in the JSON metadata. -- The function `id` is used to uniquely identify custom functions in your JavaScript code. -- The function `name` is used as the display name that appears to a user in Excel. +- `id`: Unique identifier used in code. +- `name`: Display name shown to users. It can be localized. [!include[Excel custom functions note](../includes/excel-custom-functions-note.md)] -A function `name` can differ from the function `id`, such as for localization purposes. In general, a function's `name` should stay the same as the `id` if there is no reason for them to differ. - -A function's `name` and `id` share some common requirements. - -- A function's `id` may only use characters A through Z, numbers zero through nine, underscores, and periods. +A function `name` can differ from the `id` for localization. If you don't need localization, it's best to use the same value for both. -- A function's `name` may use any Unicode alphabetic characters, underscores, and periods. +A function's `name` and `id` share some similar rules. -- Both function `name` and `id` must start with a letter and have a minimum limit of three characters. +- Both must start with a letter and be at least three characters. +- `id`: Only A–Z, 0–9, underscore, and period characters are allowed. +- `name`: Any Unicode alphabetic characters, underscore, and period characters are allowed. -Excel uses uppercase letters for built-in function names (such as `SUM`). Use uppercase letters for your custom function's `name` and `id` as a best practice. +Excel displays built-in function names in uppercase letters (for example, `SUM`). Use uppercase for your custom functions to help them blend in naturally. -A function's `name` shouldn't be the same as: +Avoid names that match: -- Any cells between A1 to XFD1048576 or any cells between R1C1 to R1048576C16384. - -- Any Excel 4.0 Macro Function (such as `RUN`, `ECHO`). For a full list of these functions, see [this Excel Macro Functions Reference document](https://www.myonlinetraininghub.com/cdn/files/Excel%204.0%20Macro%20Functions%20Reference.pdf). +- A cell reference (A1 to XFD1048576 or R1C1 to R1048576C16384). +- An Excel 4.0 Macro Function (such as `RUN`, `ECHO`). For a full list of these functions, see [this Excel Macro Functions Reference document](https://www.myonlinetraininghub.com/cdn/files/Excel%204.0%20Macro%20Functions%20Reference.pdf). ## Naming conflicts -If your function `name` is the same as a function `name` in an add-in that already exists, the **#REF!** error will appear in your workbook. +If your function `name` conflicts with one from another add-in, Excel shows the **#REF!** error. -To fix a naming conflict, change the `name` in your add-in and try the function again. You can also uninstall the add-in with the conflicting name. Or, if you're testing your add-in in different environments, try using a different namespace to differentiate your function (such as `NAMESPACE_NAMEOFFUNCTION`). +Fix conflicts by renaming your function or uninstalling the other add-in. For testing in multiple environments, use a short namespace prefix (such as `ADDINNAME_FUNCTIONNAME`). ## Best practices -- Consider adding multiple arguments to a function rather than creating multiple functions with the same or similar names. -- Avoid ambiguous abbreviations in function names. Clarity is more important than brevity. Choose a name like `=INCREASETIME` rather than `=INC`. -- Function names should indicate the action of the function, such as =GETZIPCODE instead of ZIPCODE. -- Consistently use the same verbs for functions which perform similar actions. For example, use `=DELETEZIPCODE` and `=DELETEADDRESS`, rather than `=DELETEZIPCODE` and `=REMOVEADDRESS`. -- When naming a streaming function, consider adding a note to that effect in the description of the function or adding `STREAM` to the end of the function's name. +- Use extra function arguments instead of creating multiple similar function names. For example, `GETNAME(firstName, middleName, lastName)` is more efficient than having separate functions like `GETFIRSTNAME`, `GETMIDDLENAME`, and `GETLASTNAME`. +- Avoid abbreviations that aren’t clear. For example, `INCREASETIME` is easier to understand than `INC`. +- Choose action verbs for function names. Use `GETZIPCODE` instead of just `ZIPCODE`. +- Be consistent. Use the same verb for similar actions, such as `DELETEZIPCODE` and `DELETEADDRESS`. +- For streaming functions, add `STREAM` to the name or include a note in the description. +- Use a short vendor prefix in your function names to avoid conflicts with other add-ins. For example, use `CONTOSO_GETPRICE` or `CONTOSO_TAX_CALC`. [!include[manifest guidance](../includes/manifest-guidance.md)] +## Naming constraints quick reference + +| Guideline | `id` | `name` | Notes | +|--------|------|-------|-------| +| Allowed characters | A–Z 0–9 `_` `.` | Unicode alphabetic characters `_` `.` | Keep `id` simple. Localize `name`. | +| Must start with a letter | Yes | Yes | Avoids cell reference confusion. | +| Minimum length | 3 | 3 | Short names reduce clarity. | +| Capitalization | All uppercase recommended | All uppercase recommended | Matches Excel style. | +| Localizable | No | Yes | Keep `id` stable. Localize `name` as needed. | +| Can mimic cell address | No | No | Prevent address parsing errors. | +| Reserved macro names | Disallowed | Disallowed | Some examples: `RUN`, `ECHO`. | + + ## Localize custom functions -You can localize both your add-in and your custom function names. To do so, provide localized function names in the functions' JSON file and locale information in the add-in only manifest file. +You can localize both your add-in and your custom function names. Add localized function names in your JSON file and set locale overrides in the add-in only manifest. > [!IMPORTANT] > Autogenerated metadata doesn't work for localization so you need to update the JSON file manually. To learn how to do this, see [Manually create JSON metadata for custom functions](custom-functions-json.md). ### Localize function names -To localize your custom functions, create a new JSON metadata file for each language. In each language JSON file, add `name` and `description` properties in the target language. The default file for English is named **functions.json**. Use the locale in the filename for each additional JSON file, such as **functions-de.json** to help identify them. +To localize your custom functions, create a separate JSON metadata file for each language. In each file, add the `name` and `description` properties in the target language. Use **functions.json** for English and include the locale in the filename for other languages, such as **functions-de.json** for German. -The `name` and `description` appear in Excel and are localized. However, the `id` of each function isn't localized. The `id` property is how Excel identifies your function as unique and shouldn't be changed once it is set. +Excel only localizes the `name` and `description` properties. The `id` is not localized and should remain unchanged after it's set. > [!IMPORTANT] -> Avoid giving your functions an `id` or `name` that is a built-in Excel function in another language as this conflicts with localized functions. +> Avoid an `id` or `name` that matches a built-in Excel function in any language. The following JSON shows how to define a function with the `id` property "MULTIPLY". The `name` and `description` property of the function is localized for German. Each parameter `name` and `description` is also localized for German. -```JSON +```json { "id": "MULTIPLY", "name": "SUMME", @@ -89,17 +101,17 @@ The following JSON shows how to define a function with the `id` property "MULTIP "name": "zwei", "description": "Zweite Nummer", "dimensionality": "scalar" - }, - ], + } + ] } ``` Compare the previous JSON with the following JSON for English. -```JSON +```json { "id": "MULTIPLY", - "name": "Multiply", + "name": "MULTIPLY", "description": "Multiplies two numbers", "helpUrl": "http://www.contoso.com/", "result": { @@ -116,14 +128,14 @@ Compare the previous JSON with the following JSON for English. "name": "two", "description": "second number", "dimensionality": "scalar" - }, - ], + } + ] } ``` ### Localize your add-in -After creating a JSON file for each language, update your add-in only manifest file with an override value for each locale that specifies the URL of each JSON metadata file. The following manifest XML shows a default `en-us` locale with an override JSON file URL for `de-de` (Germany). The **functions-de.json** file contains the localized German function names and IDs. +After you create a JSON for each language, add an override to your add-in only manifest that points to the correct file. The following manifest XML shows a default `en-us` locale plus an override JSON file URL for `de-de` (Germany). ```XML en-us diff --git a/docs/excel/custom-functions-overview.md b/docs/excel/custom-functions-overview.md index 51a0901868..bb84f30bb0 100644 --- a/docs/excel/custom-functions-overview.md +++ b/docs/excel/custom-functions-overview.md @@ -1,7 +1,7 @@ ---- +--- description: Create an Excel custom function for your Office Add-in. title: Create custom functions in Excel -ms.date: 03/20/2023 +ms.date: 11/11/2024 ms.topic: overview ms.custom: scenarios:getting-started ms.localizationpriority: high @@ -64,12 +64,17 @@ function add(first, second){ } ``` +> [!TIP] +> In Excel on the web, custom function descriptions and parameter descriptions display inline. This gives users additional information when writing custom functions. Learn how to configure the inline descriptions by exploring any of the [custom functions Script Lab samples](https://github.com/OfficeDev/office-js-snippets/tree/prod/samples/excel/16-custom-functions) in Excel on the web. See the following screenshot for an example. +> +> ![A custom function with inline descriptions displayed in Excel on the web.](../images/custom-functions-inline-description.png) + ### Manifest file The add-in only manifest file for an add-in that defines custom functions (**./manifest.xml** in the project that the [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md) creates) does several things. - Defines the namespace for your custom functions. A namespace prepends itself to your custom functions to help customers identify your functions as part of your add-in. -- Uses **\** and **\** elements that are unique to a custom functions manifest. These elements contain the information about the locations of the JavaScript, JSON, and HTML files. +- Uses `` and `` elements that are unique to a custom functions manifest. These elements contain the information about the locations of the JavaScript, JSON, and HTML files. - Specifies which runtime to use for your custom function. We recommend always using a shared runtime unless you have a specific need for another runtime, because a shared runtime allows for the sharing of data between functions and the task pane. To see a full working manifest from a sample add-in, see the manifest in the [one of our Office Add-in samples Github repositories](https://github.com/OfficeDev/Office-Add-in-samples/blob/main/Samples/excel-shared-runtime-global-state/manifest.xml). diff --git a/docs/excel/custom-functions-parameter-options.md b/docs/excel/custom-functions-parameter-options.md index b3c1418baa..213c281756 100644 --- a/docs/excel/custom-functions-parameter-options.md +++ b/docs/excel/custom-functions-parameter-options.md @@ -1,7 +1,7 @@ --- title: Options for Excel custom functions description: Learn how to use different parameters within your custom functions, such as Excel ranges, optional parameters, invocation context, and more. -ms.date: 07/05/2023 +ms.date: 08/18/2025 ms.localizationpriority: medium --- @@ -123,8 +123,8 @@ For example, suppose that your function returns the second highest value from a * @param {number[][]} values Multiple ranges of values. */ function secondHighest(values) { - let highest = values[0][0], - secondHighest = values[0][0]; + let highest = -Infinity, + secondHighest = -Infinity; for (let i = 0; i < values.length; i++) { for (let j = 0; j < values[i].length; j++) { if (values[i][j] >= highest) { @@ -143,6 +143,9 @@ function secondHighest(values) { A repeating parameter allows a user to enter a series of optional arguments to a function. When the function is called, the values are provided in an array for the parameter. If the parameter name ends with a number, each argument's number will increase incrementally, such as `ADD(number1, [number2], [number3],…)`. This matches the convention used for built-in Excel functions. +> [!NOTE] +> For a custom function that takes multiple parameters, a repeating parameter must be the last input parameter in the function. A repeating parameter cannot be followed by another parameter. Similarly, a function can only have one repeating parameter. + The following function sums the total of numbers, cell addresses, as well as ranges, if entered. ```TS @@ -173,7 +176,7 @@ This function shows `=CONTOSO.ADD([operands], [operands]...)` in the Excel workb ### Repeating single value parameter -A repeating single value parameter allows multiple single values to be passed. For example, the user could enter ADD(1,B2,3). The following sample shows how to declare a single value parameter. +A repeating single value parameter allows multiple single values to be passed. For example, the user could enter **ADD(1,B2,3)**. The following sample shows how to declare a single value parameter. ```JS /** @@ -192,7 +195,7 @@ function addSingleValue(singleValue) { ### Single range parameter -A single range parameter isn't technically a repeating parameter, but is included here because the declaration is very similar to repeating parameters. It would appear to the user as ADD(A2:B3) where a single range is passed from Excel. The following sample shows how to declare a single range parameter. +A single range parameter isn't technically a repeating parameter, but it's included here because the declaration is very similar to repeating parameters. It would appear to the user as **ADD(A2:B3)**, where a single range is passed from Excel. The following sample shows how to declare a single range parameter. ```JS /** @@ -212,15 +215,13 @@ function addSingleRange(singleRange) { ### Repeating range parameter -A repeating range parameter allows multiple ranges or numbers to be passed. For example, the user could enter ADD(5,B2,C3,8,E5:E8). Repeating ranges are usually specified with the type `number[][][]` as they are three-dimensional matrices. For a sample, see the main sample listed for [repeating parameters](#repeating-parameters). - -### Declaring repeating parameters +A repeating range parameter allows multiple ranges or numbers to be passed. For example, the user could enter **ADD(5,B2,C3,8,E5:E8)**. Repeating ranges are usually specified with the type `number[][][]` as they are three-dimensional matrices. For a sample, see the main sample listed for [repeating parameters](#repeating-parameters). -In Typescript, indicate that the parameter is multi-dimensional. For example, `ADD(values: number[])` would indicate a one-dimensional array, `ADD(values:number[][])` would indicate a two-dimensional array, and so on. +### Declare repeating parameters -In JavaScript, use `@param values {number[]}` for one-dimensional arrays, `@param {number[][]}` for two-dimensional arrays, and so on for more dimensions. +To declare a repeating parameter, indicate that the parameter is multi-dimensional. For example in TypeScript, `ADD(values: number[])` would indicate a one-dimensional array, `ADD(values:number[][])` would indicate a two-dimensional array, and so on. In JavaScript, use `@param values {number[]}` for one-dimensional arrays, `@param {number[][]}` for two-dimensional arrays, and so on for more dimensions. -For hand-authored JSON, ensure your parameter is specified as `"repeating": true` in your JSON file, as well as check that your parameters are marked as `"dimensionality": matrix`. +For [manually-created JSON metadata](custom-functions-json.md), ensure that the parameter is specified as `"repeating": true` and `"dimensionality": "matrix"` in your JSON file. ## Invocation parameter diff --git a/docs/excel/custom-functions-runtime.md b/docs/excel/custom-functions-runtime.md index ae3fd2d871..39068f2036 100644 --- a/docs/excel/custom-functions-runtime.md +++ b/docs/excel/custom-functions-runtime.md @@ -1,5 +1,5 @@ --- -ms.date: 06/15/2022 +ms.date: 10/22/2025 description: Understand Excel custom functions that don't use a shared runtime and their specific JavaScript-only runtime. title: JavaScript-only runtime for custom functions ms.localizationpriority: medium @@ -7,7 +7,7 @@ ms.localizationpriority: medium # JavaScript-only runtime for custom functions -Custom functions that don't use a shared runtime use a [JavaScript-only runtime](../testing/runtimes.md#javascript-only-runtime) that is designed to optimize performance of calculations. +Custom functions that don't use a shared runtime rely on a [JavaScript-only runtime](../testing/runtimes.md#javascript-only-runtime). This runtime is optimized for fast calculation but has fewer APIs available. [!include[Excel custom functions note](../includes/excel-custom-functions-note.md)] @@ -59,6 +59,10 @@ function StoreValue(key, value) { } ``` +## Compare with shared runtime + +Need UI integration or Office.js objects and events? Move those functions to a [shared runtime](../testing/runtimes.md#shared-runtime). + ## Next steps Learn how to [debug custom functions](custom-functions-debugging.md). diff --git a/docs/excel/custom-functions-troubleshooting.md b/docs/excel/custom-functions-troubleshooting.md index 7e75a65fe1..78af4cf54c 100644 --- a/docs/excel/custom-functions-troubleshooting.md +++ b/docs/excel/custom-functions-troubleshooting.md @@ -1,10 +1,11 @@ --- -ms.date: 06/09/2022 +ms.date: 08/26/2025 description: Troubleshoot common problems with Excel custom functions. title: Troubleshoot custom functions ms.topic: troubleshooting ms.localizationpriority: medium --- + # Troubleshoot custom functions When developing custom functions, you may encounter errors in the product while creating and testing your functions. @@ -29,17 +30,67 @@ Excel has a number of built-in error messages which are returned to a cell if th Generally, these errors correspond to the errors you might already be familiar with in Excel. The are only a few exceptions specific to custom functions, listed here: -- A `#NAME` error generally means there has been an issue registering your functions. +- A `#NAME?` error generally means there has been an issue registering your functions. For additional information, see [Custom functions showing #NAME? error](#custom-functions-showing-name-error). - A `#N/A` error is also maybe a sign that that function while registered could not be run. This is typically due to a missing `CustomFunctions.associate` command. -- A `#VALUE` error typically indicates an error in the functions' script file. +- A `#VALUE!` error typically indicates an error in the functions' script file. - A `#REF!` error may indicate that your function name is the same as a function name in an add-in that already exists. ## Clear the Office cache Information about custom functions is cached by Office. Sometimes while developing and repeatedly reloading an add-in with custom functions your changes may not appear. You can fix this by clearing the Office cache. For more information, see [Clear the Office cache](../testing/clear-cache.md). +### Clear the custom functions cache when your add-in runs + +There may be times when you need to clear the custom functions cache for an add-in deployed to your end users, so that add-in updates and custom functions setting changes are incorporated at the same time. Without triggering a custom functions cache clear, changes to the **functions.json** and **functions.js** files may take up to 24 hours to reach your end users, while changes to **taskpane.html** reach end users more quickly. + +> [!NOTE] +> Once this setting is turned on for a document, it takes effect the next time the document is opened with the add-in. It doesn't apply immediately after the function is called. + +To ensure that the custom functions cache is cleared by your add-in, add the following code to your **functions.js** file, and then call the `setForceRefreshOn` method in your `Office.onReady` call or other add-in initialization logic. + +> [!IMPORTANT] +> This process for clearing the custom functions cache is only supported for custom functions add-ins that use a [shared runtime](../testing/runtimes.md#shared-runtime). + +```javascript +// To enable custom functions cache clearing, add this method to your functions.js +// file, and then call the `setForceRefreshOn` method in your `Office.onReady` call. +function setForceRefreshOn() { + Office.context.document.settings.set( + 'Office.ForceRefreshCustomFunctionsCache', + true + ); + Office.context.document.settings.saveAsync(); +} +``` + +> [!TIP] +> Frequently refreshing the custom functions cache can impact performance, so clearing the custom functions cache with `setForceRefreshOn` should only be used during add-in development or to resolve bugs. Once a custom functions add-in is stabilized, stop forcing cache refreshes. + +To disable the custom functions cache clear in your add-in, set `Office.ForceRefreshCustomFunctionsCache` to `false` and call the method in your `Office.onReady` call. The following code sample shows an example with a `setForceRefreshOff` method. + +```javascript +// To disable custom functions cache clearing, add this method to your functions.js +// file, and then call the `setForceRefreshOff` method in your `Office.onReady` call. +function setForceRefreshOff() { + Office.context.document.settings.set( + 'Office.ForceRefreshCustomFunctionsCache', + false + ); + Office.context.document.settings.saveAsync(); +} +``` + ## Common problems and solutions +### Custom functions showing #NAME? error + +When opening a workbook that uses a custom functions add-in, sometimes a `#NAME?` error displays in custom function cells instead of the formula result. IntelliSense for custom functions may also not appear in the workbook when authoring new formulas. The likely cause of this issue is that the custom functions add-in hasn't registered successfully. + +To resolve the issue, try the following approaches: + +- Refresh the add-in by selecting your add-in icon. Select **Home** > **Add-ins** > **My Add-ins** and then your add-in icon. +- Follow the guidance to [automatically clear the Office cache when Office opens](../testing/clear-cache.md#automatically-clear-the-cache), and then restart Excel. + ### Can't open add-in from localhost: Use a local loopback exemption If you see the error "We can't open this add-in from localhost," you will need to enable a local loopback exemption. For details on how to do this, see [this Microsoft support article](/office/troubleshoot/office-suite-issues/cannot-open-add-in-from-localhost). @@ -50,7 +101,7 @@ If you see the error "TypeError: Network request failed" in your [runtime log](c ### Ensure promises return -When Excel is waiting for a custom function to complete, it displays #BUSY! in the cell. If your custom function code returns a promise, but the promise does not return a result, Excel will continue showing `#BUSY!`. Check your functions to make sure that any promises are properly returning a result to a cell. +When Excel is waiting for a custom function to complete, it displays `#BUSY!` in the cell. If your custom function code returns a promise, but the promise does not return a result, Excel will continue showing `#BUSY!`. Check your functions to make sure that any promises are properly returning a result to a cell. ### Error: The dev server is already running on port 3000 @@ -77,7 +128,7 @@ function add(first, second) { CustomFunctions.associate("ADD", add); ``` -For more information on this process, see [Associating function names with JSON metadata](../excel/custom-functions-json.md#associating-function-names-with-json-metadata). +For more information on this process, see [Associate function names with JSON metadata](../excel/custom-functions-json.md#associate-function-names-with-json-metadata). ## Known issues diff --git a/docs/excel/excel-add-ins-charts-data-labels.md b/docs/excel/excel-add-ins-charts-data-labels.md new file mode 100644 index 0000000000..5338e9351f --- /dev/null +++ b/docs/excel/excel-add-ins-charts-data-labels.md @@ -0,0 +1,237 @@ +--- +title: Work with data labels in charts using the Excel JavaScript API +description: Code samples demonstrating chart data label tasks using the Excel JavaScript API. +ms.date: 04/14/2025 +ms.localizationpriority: medium +--- + +# Work with data labels in charts using the Excel JavaScript API + +Add data labels to Excel charts to provide a better visualization experience about important aspects of the chart. To learn more about data labels, see [Add or remove data labels in a chart](https://support.microsoft.com/office/add-or-remove-data-labels-in-a-chart-884bf2f1-2e29-454e-8b42-f467c9f4eb2d). + +The following code sample sets up the sample data and **Bicycle Part Production** chart used in this article. + +```javascript +async function setup() { + await Excel.run(async (context) => { + context.workbook.worksheets.getItemOrNullObject("Sample").delete(); + const sheet = context.workbook.worksheets.add("Sample"); + + let salesTable = sheet.tables.add("A1:E1", true); + salesTable.name = "SalesTable"; + + salesTable.getHeaderRowRange().values = [["Product", "Qtr1", "Qtr2", "Qtr3", "Qtr4"]]; + + salesTable.rows.add(null, [ + ["Frames", 5000, 7000, 6544, 5377], + ["Saddles", 400, 323, 276, 1451], + ["Brake levers", 9000, 8766, 8456, 9812], + ["Chains", 1550, 1088, 692, 2553], + ["Mirrors", 225, 600, 923, 344], + ["Spokes", 6005, 7634, 4589, 8765] + ]); + + sheet.activate(); + createChart(context); + }); +} + +async function createChart(context: Excel.RequestContext) { + const worksheet = context.workbook.worksheets.getActiveWorksheet(); + const chart = worksheet.charts.add( + Excel.ChartType.lineMarkers, + worksheet.getRange("A1:E7"), + Excel.ChartSeriesBy.rows + ); + chart.axes.categoryAxis.setCategoryNames(worksheet.getRange("B1:E1")); + chart.name = "PartChart"; + + // Place the chart below sample data. + chart.top = 125; + chart.left = 5; + chart.height = 300; + chart.width = 450; + + chart.title.text = "Bicycle Part Production"; + chart.legend.position = "Bottom"; + + await context.sync(); +} +``` + +This image shows how the chart should display after running the sample code. + +:::image type="content" source="../images/excel-data-labels-starter-chart.png" alt-text="Screenshot of basic line chart with no data labels, showing six different bicycle parts being produced over four quarters."::: + +## Add data labels + +To add data labels to a chart, get the series of data points you want to change, and set the `hasDataLabels` property to `true`. + +```javascript +async function addDataLabels() { + await Excel.run(async (context) => { + const worksheet = context.workbook.worksheets.getActiveWorksheet(); + const chart = worksheet.charts.getItem("PartChart"); + await context.sync(); + + // Get spokes data series. + const series = chart.series.getItemAt(5); + + // Turn on data labels and set location. + series.hasDataLabels = true; + series.dataLabels.position = Excel.ChartDataLabelPosition.top; + await context.sync(); + }); +} +``` + +:::image type="content" source="../images/excel-data-labels-chart.png" alt-text="Screenshot of chart showing data labels that display the amount for each data point."::: + +## Format data label size, shape, and text + +You can change attributes on data labels using the following APIs. + +- Change data label shapes by setting the [geometricShapeType](/javascript/api/excel/excel.chartdatalabel) property. +- Change height and width using the [setWidth and setHeight](/javascript/api/excel/excel.chartdatalabel) methods. +- Change the text using the [text](/javascript/api/excel/excel.chartdatalabel) property. +- Change the text formatting using the [format](/javascript/api/excel/excel.chartdatalabel) property. You can change the [border, fill, and font](/javascript/api/excel/excel.chartdatalabelformat) properties. + +The following code sample shows how to set the shape type, height and width, and font formatting for the data labels. + +```javascript + await Excel.run(async (context) => { + const worksheet = context.workbook.worksheets.getActiveWorksheet(); + const chart = worksheet.charts.getItem("PartChart"); + const series = chart.series.getItemAt(5); + + // Set geometric shape of data labels to cubes. + series.dataLabels.geometricShapeType = Excel.GeometricShapeType.cube; + series.points.load("count"); + await context.sync(); + let pointsLoaded = series.points.count; + + // Change height, width, and font size of all data labels. + for (let j = 0; j < pointsLoaded; j++) { + series.points.getItemAt(j).dataLabel.setWidth(60); + series.points.getItemAt(j).dataLabel.setHeight(30); + series.points.getItemAt(j).dataLabel.format.font.size = 12; + } + + // Set text of a data label. + series.points.getItemAt(2).dataLabel.setWidth(80); + series.points.getItemAt(2).dataLabel.setHeight(50); + series.points.getItemAt(2).dataLabel.text = "Spokes Qtr3: 4589 ↓"; + + await context.sync(); +}); +``` + +In the following screenshot, the chart now includes *count* data labels for the **Spokes** data, with custom text at the third data point. + +:::image type="content" source="../images/excel-data-labels-chart-formats.png" alt-text="Screenshot of chart with data labels set to cubes, new size, and custom text in one of the data labels."::: + +You can also change the formatting of text in a data label. The following code sample shows how to use the [getSubstring](/javascript/api/excel/excel.chartdatalabel) method to get part of data label text and apply font formatting. + +```javascript +await Excel.run(async (context) => { + const worksheet = context.workbook.worksheets.getActiveWorksheet(); + const chart = worksheet.charts.getItem("PartChart"); + const series = chart.series.getItemAt(5); + + // Get the "Spokes" data label. + let label = series.points.getItemAt(2).dataLabel; + label.load(); + await context.sync(); + + // Change border weight of this label. + label.format.border.weight = 2; + // Format "Qtr3" as bold and italicized. + label.getSubstring(7, 4).font.bold = true; + label.getSubstring(7, 4).font.italic = true; + // Format "Spokes" as green. + label.getSubstring(0, 6).font.color = "green"; + // Format "4589" as red. + label.getSubstring(12).font.color = "red"; + // Move label up by 15 points. + label.top = label.top - 15; + + await context.sync(); + }); +``` + +:::image type="content" source="../images/excel-data-labels-chart-substring.png" alt-text="Screenshot of chart showing data label with Spokes set to green, 4589 set to red, and Qtr3 bold and italicized."::: + +## Format leader lines + +Leader lines connect data labels to their respective data points and make it easier to see what they refer to in the chart. Turn leader lines on using the [showLeaderLines](/javascript/api/excel/excel.chartseries) property. You can set the format of leader lines with the [leaderLines.format](/javascript/api/excel/excel.chartleaderlines) property. + +```javascript +await Excel.run(async (context) => { + const worksheet = context.workbook.worksheets.getActiveWorksheet(); + const chart = worksheet.charts.getItem("PartChart"); + const series = chart.series.getItemAt(5); + + // Show leader lines. + series.showLeaderLines = true; + await context.sync(); + + // Format leader lines as dotted orange lines with weight 2. + series.dataLabels.leaderLines.format.line.lineStyle = Excel.ChartLineStyle.dot; + series.dataLabels.leaderLines.format.line.color = "orange"; + series.dataLabels.leaderLines.format.line.weight = 2; +}); +``` + +:::image type="content" source="../images/excel-data-labels-chart-leaderlines.png" alt-text="Screenshot of chart with orange dotted leader lines connecting data labels to their data points."::: + +## Create callouts + +A callout is a data label that connects to the data point using a bubble-shaped pointer. A callout has an anchor which can be moved from the data point to other locations on the chart. + +The following code sample shows how to change data labels in a series to use [Excel.GeometricShapeType.wedgeRectCallout](/javascript/api/excel/excel.geometricshapetype). Note that leader lines are turned off to avoid showing two indicators to the same data label. + +```javascript + await Excel.run(async (context) => { + const worksheet = context.workbook.worksheets.getActiveWorksheet(); + const chart = worksheet.charts.getItem("PartChart"); + const series = chart.series.getItemAt(5); + + // Change to a wedge rectangle style callout. + series.dataLabels.geometricShapeType = Excel.GeometricShapeType.wedgeRectCallout; + series.showLeaderLines = false; + await context.sync(); +}); +``` + +:::image type="content" source="../images/excel-data-labels-chart-callout.png" alt-text="Screenshot of chart with data labels formatted as callouts."::: + +The following code sample shows how to change the anchor location of a data label. + +```javascript +await Excel.run(async (context) => { + const worksheet = context.workbook.worksheets.getActiveWorksheet(); + const chart = worksheet.charts.getItem("PartChart"); + const series = chart.series.getItemAt(5); + + let label = series.points.getItemAt(2).dataLabel; + let point = series.points.getItemAt(2); + label.load(); + await context.sync(); + + let anchor = label.getTailAnchor(); + anchor.load(); + await context.sync(); + + anchor.top = anchor.top - 10; + anchor.left = 40; +}); +``` + +This screenshot demonstrates how the anchor of the third data label is adjusted by the preceding code sample. + +:::image type="content" source="../images/excel-data-labels-chart-anchor-change.png" alt-text="Screenshot of chart with anchor of Spokes data label moved up and left of the original data point location."::: + +## See also + +- [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) +- [Work with charts using the Excel JavaScript API](excel-add-ins-charts.md) diff --git a/docs/excel/excel-add-ins-charts.md b/docs/excel/excel-add-ins-charts.md index 1b717102f5..e7f8974ecf 100644 --- a/docs/excel/excel-add-ins-charts.md +++ b/docs/excel/excel-add-ins-charts.md @@ -1,7 +1,7 @@ --- title: Work with charts using the Excel JavaScript API description: Code samples demonstrating chart tasks using the Excel JavaScript API. -ms.date: 02/15/2022 +ms.date: 04/14/2025 ms.localizationpriority: medium --- @@ -227,7 +227,7 @@ The following screenshot shows the data table that the preceding code sample cre ## Export a chart as an image -Charts can be rendered as images outside of Excel. `Chart.getImage` returns the chart as a base64-encoded string representing the chart as a JPEG image. The following code shows how to get the image string and log it to the console. +Charts can be rendered as images outside of Excel. `Chart.getImage` returns the chart as a Base64-encoded string representing the chart as a JPEG image. The following code shows how to get the image string and log it to the console. ```js await Excel.run(async (context) => { @@ -236,7 +236,7 @@ await Excel.run(async (context) => { await context.sync(); console.log(imageAsString.value); - // Instead of logging, your add-in may use the base64-encoded string to save the image as a file or insert it in HTML. + // Instead of logging, your add-in may use the Base64-encoded string to save the image as a file or insert it in HTML. }); ``` @@ -255,3 +255,4 @@ These parameters determine the size of the image. Images are always proportional ## See also - [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) +- [Work with data labels in charts using the Excel JavaScript API](excel-add-ins-charts-data-labels.md) diff --git a/docs/excel/excel-add-ins-comments.md b/docs/excel/excel-add-ins-comments.md index 18e3bae182..fec06a013d 100644 --- a/docs/excel/excel-add-ins-comments.md +++ b/docs/excel/excel-add-ins-comments.md @@ -1,7 +1,7 @@ --- title: Work with comments using the Excel JavaScript API description: Information on using the APIs to add, remove, and edit comments and comment threads. -ms.date: 02/15/2022 +ms.date: 04/07/2025 ms.localizationpriority: medium --- @@ -15,6 +15,9 @@ In the Excel JavaScript API, a comment includes both the single initial comment Comments within a workbook are tracked by the `Workbook.comments` property. This includes comments created by users and also comments created by your add-in. The `Workbook.comments` property is a [CommentCollection](/javascript/api/excel/excel.commentcollection) object that contains a collection of [Comment](/javascript/api/excel/excel.comment) objects. Comments are also accessible at the [Worksheet](/javascript/api/excel/excel.worksheet) level. The samples in this article work with comments at the workbook level, but they can be easily modified to use the `Worksheet.comments` property. +> [!TIP] +> To learn about adding and editing notes with the Excel JavaScript API, see [Work with notes using the Excel JavaScript API](excel-add-ins-notes.md). + ## Add comments Use the `CommentCollection.add` method to add comments to a workbook. This method takes up to three parameters: diff --git a/docs/excel/excel-add-ins-data-validation.md b/docs/excel/excel-add-ins-data-validation.md index 1761601b6a..fa51d1cdef 100644 --- a/docs/excel/excel-add-ins-data-validation.md +++ b/docs/excel/excel-add-ins-data-validation.md @@ -1,13 +1,13 @@ --- title: Add data validation to Excel ranges -description: Learn how the Excel JavaScript APIs enable your add-in to add automatic data validation to tables, columns, rows, and other ranges in a workbook. -ms.date: 02/16/2022 +description: Use the Excel JavaScript API to programmatically apply and manage data validation rules for ranges, tables, and structured inputs. +ms.date: 09/19/2025 ms.localizationpriority: medium --- # Add data validation to Excel ranges -The Excel JavaScript Library provides APIs to enable your add-in to add automatic data validation to tables, columns, rows, and other ranges in a workbook. To understand the concepts and the terminology of data validation, please see the following articles about how users add data validation through the Excel UI. +Use the Excel JavaScript API to enforce data quality. Apply rules and rely on Excel’s validation UI for prompts and error alerts. This article shows how to define rule types, configure prompts and error alerts, and remove or adjust validation. If you need background on Excel’s built-in validation UI, review these articles. - [Apply data validation to cells](https://support.microsoft.com/office/29fecbcc-d1b9-42c1-9d76-eff3ce5f7249) - [More on data validation](https://support.microsoft.com/office/f38dee73-9900-4ca6-9301-8a5f6e1f0c4c) @@ -15,10 +15,10 @@ The Excel JavaScript Library provides APIs to enable your add-in to add automati ## Programmatic control of data validation -The `Range.dataValidation` property, which takes a [DataValidation](/javascript/api/excel/excel.datavalidation) object, is the entry point for programmatic control of data validation in Excel. There are five properties to the `DataValidation` object: +The `Range.dataValidation` property, which takes a [DataValidation](/javascript/api/excel/excel.datavalidation) object, is the entry point for programmatic control of data validation in Excel. The object has five properties: - `rule` — Defines what constitutes valid data for the range. See [DataValidationRule](/javascript/api/excel/excel.datavalidationrule). -- `errorAlert` — Specifies whether an error pops up if the user enters invalid data, and defines the alert text, title, and style; for example, `information`, `warning`, and `stop`. See [DataValidationErrorAlert](/javascript/api/excel/excel.datavalidationerroralert). +- `errorAlert` — Specifies whether an error pops up if the user enters invalid data, and defines the alert text, title, and style such as `information`, `warning`, and `stop`. See [DataValidationErrorAlert](/javascript/api/excel/excel.datavalidationerroralert). - `prompt` — Specifies whether a prompt appears when the user hovers over the range and defines the prompt message. See [DataValidationPrompt](/javascript/api/excel/excel.datavalidationprompt). - `ignoreBlanks` — Specifies whether the data validation rule applies to blank cells in the range. Defaults to `true`. - `type` — A read-only identification of the validation type, such as WholeNumber, Date, TextLength, etc. It is set indirectly when you set the `rule` property. @@ -26,7 +26,7 @@ The `Range.dataValidation` property, which takes a [DataValidation](/javascript/ > [!NOTE] > Data validation added programmatically behaves just like manually added data validation. In particular, note that data validation is triggered only if the user directly enters a value into a cell or copies and pastes a cell from elsewhere in the workbook and chooses the **Values** paste option. If the user copies a cell and does a plain paste into a range with data validation, validation is not triggered. -## Creating validation rules +## Create validation rules To add data validation to a range, your code must set the `rule` property of the `DataValidation` object in `Range.dataValidation`. This takes a [DataValidationRule](/javascript/api/excel/excel.datavalidationrule) object which has seven optional properties. *No more than one of these properties may be present in any `DataValidationRule` object.* The property that you include determines the type of validation. @@ -38,10 +38,10 @@ The first three `DataValidationRule` properties (i.e., validation rule types) ta - `decimal` — Requires a decimal number in addition to any other validation specified by the `BasicDataValidation` object. - `textLength` — Applies the validation details in the `BasicDataValidation` object to the *length* of the cell's value. -Here is an example of creating a validation rule. Note the following about this code. +The following example creates a validation rule. Key points: -- The `operator` is the binary operator `greaterThan`. Whenever you use a binary operator, the value that the user tries to enter in the cell is the left-hand operand and the value specified in `formula1` is the right-hand operand. So this rule says that only whole numbers that are greater than 0 are valid. -- The `formula1` is a hard-coded number. If you don't know at coding time what the value should be, you can also use an Excel formula (as a string) for the value. For example, "=A3" and "=SUM(A4,B5)" could also be values of `formula1`. +- The `operator` is the binary operator `greaterThan`. Whenever you use a binary operator, the value that the user tries to enter in the cell is the left-hand operand and the value specified in `formula1` is the right-hand operand. This rule says that only whole numbers greater than 0 are valid. +- The `formula1` is a hard-coded number. If you don't know at coding time what the value should be, you can also use an Excel formula as a string (such as "=A3" or "=SUM(A4,B5)"). ```js await Excel.run(async (context) => { @@ -59,9 +59,9 @@ await Excel.run(async (context) => { }); ``` -See [BasicDataValidation](/javascript/api/excel/excel.basicdatavalidation) for a list of the other binary operators. +See [BasicDataValidation](/javascript/api/excel/excel.basicdatavalidation) for other binary operators. -There are also two ternary operators: `between` and `notBetween`. To use these, you must specify the optional `formula2` property. The `formula1` and `formula2` values are the bounding operands. The value that the user tries to enter in the cell is the third (evaluated) operand. The following is an example of using the "Between" operator. +There are also two ternary operators: `between` and `notBetween`. To use these, specify the optional `formula2` property. The `formula1` and `formula2` values are the bounding operands. The value that the user tries to enter in the cell is the third (evaluated) operand. The following is an example of using the "Between" operator. ```js await Excel.run(async (context) => { @@ -106,11 +106,11 @@ await Excel.run(async (context) => { ### List validation rule type -Use the `list` property in the `DataValidationRule` object to specify that the only valid values are those from a finite list. The following is an example. Note the following about this code. +Use the `list` property in the `DataValidationRule` object to constrain values to a finite set. The following code sample demonstrates. Key points: - It assumes that there is a worksheet named "Names" and that the values in the range "A1:A3" are names. -- The `source` property specifies the list of valid values. The string argument refers to a range containing the names. You can also assign a comma-delimited list; for example: "Sue, Ricky, Liz". -- The `inCellDropDown` property specifies whether a drop-down control will appear in the cell when the user selects it. If set to `true`, then the drop-down appears with the list of values from the `source`. +- The `source` property specifies the list of valid values. The string argument refers to a range containing the names. You can also assign a comma-delimited list such as "Sue, Ricky, Liz". +- The `inCellDropDown` property specifies whether a drop-down control appears in the cell when the user selects it. If `true`, the drop-down appears with the list of values from the `source`. ```js await Excel.run(async (context) => { @@ -131,11 +131,12 @@ await Excel.run(async (context) => { ### Custom validation rule type -Use the `custom` property in the `DataValidationRule` object to specify a custom validation formula. The following is an example. Note the following about this code. +Use the `custom` property to specify a custom validation formula. The following is an example. Key points: -- It assumes there is a two-column table with columns **Athlete Name** and **Comments** in the A and B columns of the worksheet. -- To reduce verbosity in the **Comments** column, it makes data that includes the athlete's name invalid. -- `SEARCH(A2,B2)` returns the starting position, in string in B2, of the string in A2. If A2 is not contained in B2, it does not return a number. `ISNUMBER()` returns a boolean. So the `formula` property says that valid data for the **Comment** column is data that does not include the string in the **Athlete Name** column. +- It assumes a there is two-column table with columns **Athlete Name** and **Comments** in the A and B columns of the worksheet. +- To reduce verbosity in the **Comments** column, the rule makes data that includes the athlete's name invalid. +- `SEARCH(A2,B2)` returns the starting position in B2 of the string in A2. If A2 isn't contained in B2, it doesn't return a number. +- `ISNUMBER()` returns a boolean. So the `formula` property says that valid data for **Comments** is data that doesn't include the **Athlete Name** string. ```js await Excel.run(async (context) => { @@ -154,7 +155,7 @@ await Excel.run(async (context) => { ## Create validation error alerts -You can a create custom error alert that appears when a user tries to enter invalid data in a cell. The following is a simple example. Note the following about this code. +Create an error alert to guide the user when invalid data is entered. The following example creates a basic alert. Key points: - The `style` property determines whether the user gets an informational alert, a warning, or a "stop" alert. Only `stop` actually prevents the user from adding invalid data. The pop-ups for `warning` and `information` have options that allow the user enter the invalid data anyway. - The `showAlert` property defaults to `true`. This means that Excel will pop-up a generic alert (of type `stop`) unless you create a custom alert which either sets `showAlert` to `false` or sets a custom message, title, and style. This code sets a custom message and title. @@ -181,7 +182,7 @@ For more information, see [DataValidationErrorAlert](/javascript/api/excel/excel ## Create validation prompts -You can create an instructional prompt that appears when a user hovers over, or selects, a cell to which data validation has been applied. The following is an example. +Create an instructional prompt that appears when the user selects the cell. This example tells the user about the positive number validation before they enter data. ```js await Excel.run(async (context) => { @@ -207,16 +208,21 @@ For more information, see [DataValidationPrompt](/javascript/api/excel/excel.dat To remove data validation from a range, call the [Range.dataValidation.clear()](/javascript/api/excel/excel.datavalidation#excel-excel-datavalidation-clear-member(1)) method. ```js -myrange.dataValidation.clear() +myrange.dataValidation.clear(); ``` -It isn't necessary that the range you clear is exactly the same range as a range on which you added data validation. If it isn't, only the overlapping cells, if any, of the two ranges are cleared. +The range you clear doesn’t need to precisely match the range on which you added data validation. If the two ranges aren't an exact match, only overlapping cells are cleared. > [!NOTE] > Clearing data validation from a range will also clear any data validation that a user has added manually to the range. +## Next steps + +- Combine validation with events: [Events](excel-add-ins-events.md). +- Add [conditional formatting](excel-add-ins-conditional-formatting.md) for stronger visual cues. + ## See also - [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) - [DataValidation Object (JavaScript API for Excel)](/javascript/api/excel/excel.datavalidation) -- [Range Object (JavaScript API for Excel)](/javascript/api/excel/excel.range) +- [Range Object (JavaScript API for Excel)](/javascript/api/excel/excel.range) \ No newline at end of file diff --git a/docs/excel/excel-add-ins-delay-in-cell-edit.md b/docs/excel/excel-add-ins-delay-in-cell-edit.md index 734b17fe57..27152076fe 100644 --- a/docs/excel/excel-add-ins-delay-in-cell-edit.md +++ b/docs/excel/excel-add-ins-delay-in-cell-edit.md @@ -1,17 +1,42 @@ --- title: Delay execution while cell is being edited -description: Learn how to delay the execution of the Excel.run function when a cell is being edited. -ms.date: 02/16/2022 +description: Defer an Excel.run batch until the user leaves cell edit mode instead of failing with an error. +ms.date: 09/19/2025 ms.localizationpriority: medium --- - # Delay execution while cell is being edited -`Excel.run` has an overload that takes in a [Excel.RunOptions](/javascript/api/excel/excel.runoptions) object. This contains a set of properties that affect platform behavior when the function runs. The following property is currently supported. +When a user is actively editing a cell, some add-in operations may fail immediately. Use the `delayForCellEdit` option to queue the batch until the user exits cell edit mode instead of throwing an error. + +`Excel.run` has an overload that takes an [Excel.RunOptions](/javascript/api/excel/excel.runoptions) object. It supports the following property relevant to this scenario. + +- `delayForCellEdit`: When `true`, Excel queues the batch until the user exits cell edit mode. When `false`, the batch fails immediately if the user is editing. The default value is `false`. + +## Behavior comparison + +| User editing? | `delayForCellEdit = false` (default) | `delayForCellEdit = true` | +|---------------|------------------------------------|--------------------------| +| No | Batch runs immediately | Batch runs immediately | +| Yes | Batch fails (`InvalidOperation` error) | Batch waits; then runs after edit is committed or canceled | -- `delayForCellEdit`: Determines whether Excel delays the batch request until the user exits cell edit mode. When `true`, the batch request is delayed and runs when the user exits cell edit mode. When `false`, the batch request automatically fails if the user is in cell edit mode (causing an error to reach the user). The default behavior with no `delayForCellEdit` property specified is equivalent to when it is `false`. +## Example ```js -await Excel.run({ delayForCellEdit: true }, async (context) => { ... }); +await Excel.run({ delayForCellEdit: true }, async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("A1"); + range.values = [["Updated while user was editing elsewhere"]]; + await context.sync(); +}); ``` + +## Guidance + +- Use `delayForCellEdit` only when user-initiated commands may overlap active cell editing, such as with a ribbon button that triggers a bulk update. +- Consider showing a status indicator in your add-in if queued work may be lengthy. +- Avoid chaining multiple long-running delayed batches. This creates a perceived lag for your users. + +## Next steps + +Explore related user-state strategies in [Events](excel-add-ins-events.md), such as reacting to selection changes, and combine with `delayForCellEdit` to improve your add-in's robustness. diff --git a/docs/excel/excel-add-ins-dot-functions.md b/docs/excel/excel-add-ins-dot-functions.md new file mode 100644 index 0000000000..0834c7a5fb --- /dev/null +++ b/docs/excel/excel-add-ins-dot-functions.md @@ -0,0 +1,490 @@ +--- +title: Add reference methods to cell values +description: Learn how to add reference methods to cell values. +ms.date: 08/28/2025 +ms.localizationpriority: medium +--- + +# Add reference methods to cell values + +Add reference methods to cell values to give users access to dynamic calculations based on the cell value. The [`EntityCellValue`](/javascript/api/excel/excel.entitycellvalue) and [`LinkedEntityCellValue`](/javascript/api/excel/excel.linkedentitycellvalue) types support reference methods. For example, add a method to a product entity value that converts its weight to different units. + +The following image shows an example of adding a `ConvertWeight` method to a product entity value representing pancake mix. + +:::image type="content" source="../images/excel-add-in-dot-function.png" alt-text="Excel formula showing =A1.ConvertWeight(ounces)."::: + +The [`DoubleCellValue`](/javascript/api/excel/excel.doublecellvalue), [`BooleanCellValue`](/javascript/api/excel/excel.booleancellvalue), and [`StringCellValue`](/javascript/api/excel/excel.stringcellvalue) types also support reference methods. The following image shows an example of adding a `ConvertToRomanNumeral` method to a double value type. + +:::image type="content" source="../images/excel-add-in-dot-function-roman-numeral.png" alt-text="Excel formula showing =A1.ConvertToRomanNumeral()"::: + +Reference methods don't appear on the data type card. + +:::image type="content" source="../images/excel-add-in-dot-function-data-card.png" alt-text="Data card for the Pancake mix data type, but no reference methods are listed."::: + +## Add a reference method to an entity value + +To add a reference method to an entity value, define it in JSON by using the `Excel.JavaScriptCustomFunctionReferenceCellValue` type. The following code sample shows how to define a simple method that returns the value 27. + +```typescript +const referenceCustomFunctionGet27: Excel.JavaScriptCustomFunctionReferenceCellValue = { + type: Excel.CellValueType.function, + functionType: Excel.FunctionCellValueType.javaScriptReference, + namespace: "CONTOSO", + id: "GET27" +} +``` + +The properties are described in the following table. + +|Property |Description | +|---------|---------| +|**type** | Specifies the type of reference. This property only supports `function` and must be set to `Excel.CellValueType.function`.| +|**functionType** | Specifies the type of function. This property only supports JavaScript reference functions, and must be set to `Excel.FunctionCellValueType.javaScriptReference`.| +|**namespace** | The namespace that contains the custom function. This value must match the namespace specified by the [customFunctions.namespace element](/microsoftteams/platform/resources/schema/manifest-schema-dev-preview) in the unified manifest, or the [Namespace element](/javascript/api/manifest/namespace) in the add-in only manifest.| +|**id** | The name of the custom function to map to this reference method. The name is the uppercase version of the custom function name. | + +When you create the entity value, add the reference method to the properties list. The following code sample shows how to create a simple entity value named `Math` and add a reference method to it. `Get27` is the method name that appears to users (for example: `A1.Get27()`). + +```typescript +function makeMathEntity(value: number){ + const entity: Excel.EntityCellValue = { + type: Excel.CellValueType.entity, + text: "Math value", + properties: { + "value": { + type: Excel.CellValueType.double, + basicValue: value, + numberFormat: "#" + }, + Get27: referenceCustomFunctionGet27 + } + }; + return entity; +} +``` + +The following code sample shows how to create an instance of the `Math` entity and add it to the selected cell. + +```typescript +// Add entity to selected cell. +async function addEntityToCell(){ + const entity: Excel.EntityCellValue = makeMathEntity(10); + await Excel.run( async (context) => { + const cell = context.workbook.getActiveCell(); + cell.valuesAsJson = [[entity]]; + await context.sync(); + }); +} +``` + +Finally, implement the reference method with a custom function. The following code sample shows how to implement the custom function. + +```typescript +/** + * Returns the value 27. + * @customfunction + * @excludeFromAutoComplete + * @returns {number} 27 + */ +function get27() { + return 27; +} +``` + +In the previous code sample, the `@excludeFromAutoComplete` tag ensures the custom function doesn't appear in the Excel UI when a user enters it in a search box. However, a user can still call the custom function separately from an entity value if they enter it directly into a cell. + +When the code runs, it creates a `Math` entity value as shown in the following image. The method appears in formula AutoComplete when the user references the entity value from a formula. + +:::image type="content" source="../images/excel-data-types-reference-method-autocomplete.png" alt-text="Entering 'A1.' in Excel with formula AutoComplete displaying the 'Get27' reference method."::: + +## Add arguments + +If your reference method needs arguments, add them to the custom function. The following code example shows how to add an argument named `x` to a method named `addValue`. The method adds one to the `x` value by calling a custom function named `addValue`. + +```typescript +/** + * Adds a value to 1. + * @customfunction + * @excludeFromAutoComplete + * @param {number} x The value to add to 1. + * @return {number[][]} Sum of x and 1. + */ +function addValue(x): number[][] { + return [[x+1]]; +} +``` + +## Reference the entity value as a calling object + +A common scenario is that your methods need to reference properties on the entity value itself to perform calculations. For example, it's more useful if the `addValue` method adds the argument value to the entity value itself. Specify that the entity value is passed as the first argument by applying the `@capturesCallingObject` tag to the custom function as shown in the following code example. + +```typescript +/** + * Adds x to the calling object. + * @customfunction + * @excludeFromAutoComplete + * @capturesCallingObject + * @param {any} math The math object (calling object). + * @param {number} x The value to add. + * @return {number[][]} Sum. + */ +function addValue(math, x): number[][] { + const result: number = math.properties["value"].basicValue + x; + return [[result]]; +} +``` + +You can use any argument name that conforms to the Excel syntax rules in [Names in formulas](https://support.microsoft.com/office/names-in-formulas-fc2935f9-115d-4bef-a370-3aa8bb4c91f1). Because this is a math entity, the calling object argument is named `math`. The argument name can be used in the calculation. In the previous code sample, it retrieves the `math.[value]` property to perform the calculation. + +The following code sample shows the implementation of the `Contoso.addValue` function. + +```typescript +/** + * Adds x to the calling object. + * @customfunction + * @excludeFromAutoComplete + * @param {any} math The math object (calling object). + * @param {number} x The value to add. + * @return {number[][]} Sum. + */ +function addValue(math, x): number[][] { + const result: number = math.properties["value"].basicValue + x; + return [[result]]; +} +``` + +Note the following about the previous code sample. + +- The `@excludeFromAutoComplete` tag ensures that the custom function doesn't appear in the Excel UI when a user enters it in a search box. However, a user can still call the custom function separately from an entity value if they enter it directly into a cell. +- The calling object is always passed as the first argument and must be of type `any`. In this case, it's named `math` and is used to get the value property from the `math` object. +- It returns a double array of numbers. +- When the user interacts with the reference method in Excel, they don't see the calling object as an argument. + +## Example: Calculate product sales tax + +The following code shows how to implement a custom function that calculates the sales tax for the unit price of a product. + +```typescript +/** + * Calculates the price when a sales tax rate is applied. + * @customfunction + * @excludeFromAutoComplete + * @capturesCallingObject + * @param {any} product The product entity value (calling object). + * @param {number} taxRate The tax rate (0.11 = 11%). + * @return {number[][]} Product unit price with tax rate applied. + */ +function applySalesTax(product, taxRate): number[][] { + const unitPrice: number = product.properties["Unit Price"].basicValue; + const result: number = unitPrice * taxRate + unitPrice; + return [[result]]; +} +``` + +The following code sample shows how to specify the reference method and includes the `id` of the `applySalesTax` custom function. + +```typescript +const referenceCustomFunctionCalculateSalesTax: Excel.JavaScriptCustomFunctionReferenceCellValue = { + type: Excel.CellValueType.function, + functionType: Excel.FunctionCellValueType.javaScriptReference, + namespace: "CONTOSO", + id: "APPLYSALESTAX" +} +``` + +The following code shows how to add the reference method to the `product` entity value. + +```typescript +function makeProductEntity(productID: number, productName: string, price: number) { + const entity: Excel.EntityCellValue = { + type: Excel.CellValueType.entity, + text: productName, + properties: { + "Product ID": { + type: Excel.CellValueType.string, + basicValue: productID.toString() || "" + }, + "Product Name": { + type: Excel.CellValueType.string, + basicValue: productName || "" + }, + "Unit Price": { + type: Excel.CellValueType.formattedNumber, + basicValue: price, + numberFormat: "$* #,##0.00" + }, + applySalesTax: referenceCustomFunctionCalculateSalesTax + }, + }; + return entity; +} +``` + +## Exclude custom functions from the Excel UI + +Use the `@excludeFromAutoComplete` tag in the JSDoc tag of custom functions used by reference methods to indicate that the function be excluded from formula AutoComplete and Formula Builder. This helps prevent users from accidentally using a custom function separately from its entity value. + +> [!NOTE] +> If the function is manually entered correctly in the grid, the function still runs. + +>[!IMPORTANT] +> A function can't have both `@excludeFromAutoComplete` and `@linkedEntityLoadService` tags. + +The `@excludeFromAutoComplete` tag is processed during build to generate a **functions.json** file by the **Custom-Functions-Metadata** package. This package is automatically added to the build process if you create your add-in with the Yeoman generator for Office Add-ins and choose a custom functions template. If you aren't using the **Custom-Functions-Metadata** package, you'll need to add the `excludeFromAutoComplete` property manually to the **functions.json** file. + +The following code sample shows how to manually define the `APPLYSALESTAX` custom function with JSON in the **functions.json** file. The `excludeFromAutoComplete` property is set to `true`. + +```json +{ + "description": "Calculates the price when a sales tax rate is applied.", + "id": "APPLYSALESTAX", + "name": "APPLYSALESTAX", + "options": { + "excludeFromAutoComplete": true, + "capturesCallingObject": true + }, + "parameters": [ + { + "description": "The product entity value (calling object).", + "name": "product", + "type": "any" + }, + { + "description": "The tax rate (0.11 = 11%).", + "name": "taxRate", + "type": "number" + } + ], + "result": { + "dimensionality": "matrix", + "type": "number" + } +}, +``` + +For more information, see [Manually create JSON metadata for custom functions](custom-functions-json.md). + +## Add a function to a basic value type + +To add functions to the basic value types of `Boolean`, `double`, and `string`, use the same process as you would for entity values. The following code sample shows how to create a double basic value with a custom function called `addValue`. The function adds the value `x` to the basic value. + +```typescript +/** + * Adds the value x to the number value. + * @customfunction + * @capturesCallingObject + * @param {any} numberValue The number value (calling object). + * @param {number} x The value to add. + * @return {number[][]} Sum of the number value and x. + */ +export function addValue(numberValue: any, x: number): number[][] { + return [[x+numberValue.basicValue]]; +} + +``` + +The following code sample shows how to define the `addValue` custom function from the preceding sample in JSON and then reference it with a method called `createSimpleNumber`. + +```typescript +const referenceCustomFunctionAddValue: Excel.JavaScriptCustomFunctionReferenceCellValue = { + type: Excel.CellValueType.function, + functionType: Excel.FunctionCellValueType.javaScriptReference, + namespace: "CONTOSO", + id: "ADDVALUE" +} + +async function createSimpleNumber() { + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("A1"); + range.valuesAsJson = [ + [ + { + type: Excel.CellValueType.double, + basicType: Excel.RangeValueType.double, + basicValue: 6.0, + properties: { + addValue: referenceCustomFunctionAddValue + } + } + ] + ]; + await context.sync(); + }); +} +``` + +## Optional arguments + +The following code sample shows how to create a reference method that accepts optional arguments. The reference method is named `generateRandomRange` and it generates a range of random values. + +```typescript +const referenceCustomFunctionOptional: Excel.JavaScriptCustomFunctionReferenceCellValue = { + type: Excel.CellValueType.function, + functionType: Excel.FunctionCellValueType.javaScriptReference, + namespace: "CONTOSO", + id: "GENERATERANDOMRANGE" +} + +function makeProductEntity(productID: number, productName: string, price: number) { + const entity: Excel.EntityCellValue = { + type: Excel.CellValueType.entity, + text: productName, + properties: { + "Product ID": {...}, + "Product Name": {...}, + "Unit Price": {...}, + generateRandomRange: referenceCustomFunctionOptional + }, + }; + return entity; +} +``` + +The following code sample shows the implementation of the reference method as a custom function named `generateRandomRange`. It returns a dynamic array of random values matching the number of `rows` and `columns` specified. The `min` and `max` arguments are optional, and if not specified will default to `1` and `10`. + +```typescript +/** + * Generates a dynamic array of random numbers. + * @customfunction + * @excludeFromAutoComplete + * @param {number} rows Number of rows to generate. + * @param {number} columns Number of columns to generate. + * @param {number} [min] Lowest number that can be generated. Default is 1. + * @param {number} [max] Highest number that can be generated. Default is 10. + * @returns {number[][]} A dynamic array of random numbers. + */ +function generateRandomRange(rows, columns, min, max) { + // Set defaults for any missing optional arguments. + if (min === undefined) min = 1; + if (max === undefined) max = 10; + + let numbers = new Array(rows); + for (let r = 0; r < rows; r++) { + numbers[r] = new Array(columns); + for (let c = 0; c < columns; c++) { + numbers[r][c] = Math.round(Math.random() * (max - min) ) + min; + } + } + return numbers; +} +``` + +When the user enters the custom function in Excel, AutoComplete shows the properties of the function and indicates optional arguments by surrounding them in brackets (`[]`). The following image shows an example of entering optional parameters by using the `generateRandomRange` reference method. + +:::image type="content" source="../images/excel-data-types-reference-method-optional-parameters.png" alt-text="Screenshot of entering generateRandomRange method in Excel."::: + +## Multiple parameters + +Reference methods support multiple parameters, similar to how the Excel `SUM` function supports multiple parameters. The following code sample shows how to create a reference function that concatenates zero or more product names passed in a products array. The function is shown to the user as `concatProductNames([products], ...)`. + +```typescript +/** + * @customfunction + * @excludeFromAutoComplete + * @description Concatenate the names of given products, joined by " | " + * @param {any[]} products - The products to concatenate. + * @returns A string of concatenated product names. + */ +function concatProductNames(products: any[]): string { + return products.map((product) => product.properties["Product Name"].basicValue).join(" | "); +} +``` + +The following code sample shows how to create an entity with the `concatProductNames` reference method. + +```typescript +const referenceCustomFunctionMultiple: Excel.JavaScriptCustomFunctionReferenceCellValue = { + type: Excel.CellValueType.function, + functionType: Excel.FunctionCellValueType.javaScriptReference, + namespace: "CONTOSO", + id: "CONCATPRODUCTNAMES" +} + +function makeProductEntity(productID: number, productName: string, price: number) { + const entity: Excel.EntityCellValue = { + type: Excel.CellValueType.entity, + text: productName, + properties: { + "Product ID": {...}, + "Product Name": {...}, + "Unit Price": {...}, + concatProductNames: referenceCustomFunctionMultiple, + }, + }; + return entity; +} +``` + +The following image shows an example of entering multiple parameters by using the `concatProductNames` reference method. + +:::image type="content" source="../images/excel-data-types-reference-method-repeating-parameters.png" alt-text="Screenshot of entering concatProductNames method in Excel passing A1 and A2 which contain a bicycle and unicycle product entity value."::: + +### Multiple parameters with ranges + +To support passing ranges to your reference method such as **B1:B3**, use a multidimensional array. The following code sample shows how to create a reference function that sums zero or more parameters which can include ranges. + +```typescript +/** + * @customfunction + * @excludeFromAutoComplete + * @description Calculate the sum of arbitrary parameters. + * @param {number[][][]} operands - The operands to sum. + * @returns The sum of all operands. + */ +function sumAll(operands: number[][][]): number { + let total: number = 0; + + operands.forEach(range => { + range.forEach(row => { + row.forEach(num => { + total += num; + }); + }); + }); + + return total; +} +``` + +The following code sample shows how to create an entity with the `sumAll` reference method. + +```typescript +const referenceCustomFunctionRange: Excel.JavaScriptCustomFunctionReferenceCellValue = { + type: Excel.CellValueType.function, + functionType: Excel.FunctionCellValueType.javaScriptReference, + namespace: "CONTOSO", + id: "SUMALL" +} + +function makeProductEntity(productID: number, productName: string, price: number) { + const entity: Excel.EntityCellValue = { + type: Excel.CellValueType.entity, + text: productName, + properties: { + "Product ID": {...}, + "Product Name": {...}, + "Unit Price": {...}, + sumAll: referenceCustomFunctionRange + }, + }; + return entity; +} +``` + +The following image shows an example of entering multiple parameters, including a range parameter, by using the `sumAll` reference method. + +:::image type="content" source="../images/excel-data-types-reference-method-optional-ranges.png" alt-text="Screenshot of entering sumAll method in Excel passing an optional range of B1:B2."::: + +## Support details + +Reference methods are supported in all custom function types, such as [volatile](custom-functions-volatile.md) and [streaming](custom-functions-web-reqs.md#make-a-streaming-function) functions. All custom function return types—matrix, scalar, and error—are supported. + +> [!IMPORTANT] +> A linked entity can't have a custom function that combines both a reference method and a data provider. When you develop linked entities, keep these types of custom functions separate. + +## See also + +- [Create custom functions in Excel](custom-functions-overview.md) +- [Autogenerate JSON metadata for custom functions](custom-functions-json-autogeneration.md) +- [Manually create JSON metadata for custom functions](custom-functions-json.md) diff --git a/docs/excel/excel-add-ins-multiple-ranges.md b/docs/excel/excel-add-ins-multiple-ranges.md index 5782c1cb9c..f79e092dc8 100644 --- a/docs/excel/excel-add-ins-multiple-ranges.md +++ b/docs/excel/excel-add-ins-multiple-ranges.md @@ -1,30 +1,34 @@ --- title: Work with multiple ranges simultaneously in Excel add-ins description: Learn how the Excel JavaScript library enables your add-in to perform operations, and set properties, on multiple ranges simultaneously. -ms.date: 02/16/2022 +ms.date: 09/22/2025 ms.localizationpriority: medium --- # Work with multiple ranges simultaneously in Excel add-ins -The Excel JavaScript library enables your add-in to perform operations, and set properties, on multiple ranges simultaneously. The ranges do not have to be contiguous. In addition to making your code simpler, this way of setting a property runs much faster than setting the same property individually for each of the ranges. +You can apply operations or set properties on several ranges at once, even if they're not contiguous. This makes code shorter and more efficient when compared to accessing each range separately. -## RangeAreas +## Key points + +- Use `RangeAreas` to read or set the same thing on several separate ranges in one call. +- A property is `null` unless all member ranges share the same value. +- Set a property once on the `RangeAreas` object instead of looping, unless each range needs different logic. +- Avoid large `RangeAreas` objects made of many single cells. Narrow first with `getSpecialCells` or other filters. +- Be careful with whole columns or rows. For more details, see [Read or write to an unbounded range](excel-add-ins-ranges-unbounded.md). -A set of (possibly discontiguous) ranges is represented by a [RangeAreas](/javascript/api/excel/excel.rangeareas) object. It has properties and methods similar to the `Range` type (many with the same, or similar, names), but adjustments have been made to: +## RangeAreas -- The data types for properties and the behavior of the setters and getters. -- The data types of method parameters and the method behaviors. -- The data types of method return values. +A [RangeAreas](/javascript/api/excel/excel.rangeareas) object represents a set of ranges that may not touch. It shares many members with `Range`, with a few differences in how values are returned. -Some examples: +Examples: -- `RangeAreas` has an `address` property that returns a comma-delimited string of range addresses, instead of just one address as with the `Range.address` property. -- `RangeAreas` has a `dataValidation` property that returns a `DataValidation` object that represents the data validation of all the ranges in the `RangeAreas`, if it is consistent. The property is `null` if identical `DataValidation` objects are not applied to all the all the ranges in the `RangeAreas`. This is a general, but not universal, principle with the `RangeAreas` object: *If a property does not have consistent values on all the all the ranges in the `RangeAreas`, then it is `null`.* See [Read properties of RangeAreas](#read-properties-of-rangeareas) for more information and some exceptions. -- `RangeAreas.cellCount` gets the total number of cells in all the ranges in the `RangeAreas`. -- `RangeAreas.calculate` recalculates the cells of all the ranges in the `RangeAreas`. -- `RangeAreas.getEntireColumn` and `RangeAreas.getEntireRow` return another `RangeAreas` object that represents all of the columns (or rows) in all the ranges in the `RangeAreas`. For example, if the `RangeAreas` represents "A1:C4" and "F14:L15", then `RangeAreas.getEntireColumn` returns a `RangeAreas` object that represents "A:C" and "F:L". -- `RangeAreas.copyFrom` can take either a `Range` or a `RangeAreas` parameter representing the source ranges of the copy operation. +- `address` returns one comma-delimited string of all addresses. +- `dataValidation` returns a single object only if every range has the same rule, otherwise it returns `null`. +- `cellCount` is the total cells across all ranges. +- `calculate` recalculates all cells in the set. +- `getEntireColumn` and `getEntireRow` return a new `RangeAreas` spanning full columns or rows for each member. +- `copyFrom` accepts either a `Range` or a `RangeAreas` as the source. ### Complete list of Range members that are also available on RangeAreas @@ -78,9 +82,10 @@ The `RangeAreas` type has some properties and methods that are not on the `Range ## Create RangeAreas -You can create `RangeAreas` object in two basic ways: +You can create a `RangeAreas` object in multiple ways. The following list includes some examples. - Call `Worksheet.getRanges()` and pass it a string with comma-delimited range addresses. If any range you want to include has been made into a [NamedItem](/javascript/api/excel/excel.nameditem), you can include the name, instead of the address, in the string. +- Call `Range.getSpecialCells()` and return a `RangeAreas` object with cells of a specific type, such as cells that contain formulas, data validation, or conditional formatting. - Call `Workbook.getSelectedRanges()`. This method returns a `RangeAreas` representing all the ranges that are selected on the currently active worksheet. Once you have a `RangeAreas` object, you can create others using the methods on the object that return `RangeAreas` such as `getOffsetRangeAreas` and `getIntersection`. @@ -89,7 +94,7 @@ Once you have a `RangeAreas` object, you can create others using the methods on > You cannot directly add additional ranges to a `RangeAreas` object. For example, the collection in `RangeAreas.areas` does not have an `add` method. > [!WARNING] -> Do not attempt to directly add or delete members of the the `RangeAreas.areas.items` array. This will lead to undesirable behavior in your code. For example, it is possible to push an additional `Range` object onto the array, but doing so will cause errors because `RangeAreas` properties and methods behave as if the new item isn't there. For example, the `areaCount` property does not include ranges pushed in this way, and the `RangeAreas.getItemAt(index)` throws an error if `index` is larger than `areasCount-1`. Similarly, deleting a `Range` object in the `RangeAreas.areas.items` array by getting a reference to it and calling its `Range.delete` method causes bugs: although the `Range` object *is* deleted, the properties and methods of the parent `RangeAreas` object behave, or try to, as if it is still in existence. For example, if your code calls `RangeAreas.calculate`, Office will try to calculate the range, but will error because the range object is gone. +> Do not attempt to directly add or delete members of the `RangeAreas.areas.items` array. This will lead to undesirable behavior in your code. For example, it is possible to push an additional `Range` object onto the array, but doing so will cause errors because `RangeAreas` properties and methods behave as if the new item isn't there. For example, the `areaCount` property does not include ranges pushed in this way, and the `RangeAreas.getItemAt(index)` throws an error if `index` is larger than `areasCount-1`. Similarly, deleting a `Range` object in the `RangeAreas.areas.items` array by getting a reference to it and calling its `Range.delete` method causes bugs: although the `Range` object *is* deleted, the properties and methods of the parent `RangeAreas` object behave, or try to, as if it is still in existence. For example, if your code calls `RangeAreas.calculate`, Office will try to calculate the range, but will error because the range object is gone. ## Set properties on multiple ranges @@ -112,6 +117,24 @@ This example applies to scenarios in which you can hard code the range addresses - The code runs in the context of a known template. - The code runs in the context of imported data where the schema of the data is known. +## Combine `RangeAreas` with `getSpecialCells` + +Filter a `RangeAreas` down to just the cells that match a criterion, such as formulas, before applying formatting or validation. + +```js +await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Two discontiguous vertical bands. + const targets = sheet.getRanges("A1:A100, C1:C100"); + + // Narrow to only the formula cells within those bands. + const formulaCells = targets.getSpecialCells(Excel.SpecialCellType.formulas); + formulaCells.format.fill.color = "lightYellow"; + await context.sync(); +}); +``` + ## Get special cells from multiple ranges The `getSpecialCells` and `getSpecialCellsOrNullObject` methods on the `RangeAreas` object work analogously to methods of the same name on the `Range` object. These methods return the cells with the specified characteristic from all of the ranges in the `RangeAreas.areas` collection. For more details on special cells, see [Find special cells within a range](excel-add-ins-ranges-special-cells.md). @@ -141,11 +164,11 @@ await Excel.run(async (context) => { }); ``` -Things get more complicated when consistency isn't possible. The behavior of `RangeAreas` properties follows these three principles: +Since property values can differ, keep these simple rules in mind. -- A boolean property of a `RangeAreas` object returns `false` unless the property is true for all the member ranges. -- Non-boolean properties, with the exception of the `address` property, return `null` unless the corresponding property on all the member ranges has the same value. -- The `address` property returns a comma-delimited string of the addresses of the member ranges. +- Boolean properties are `true` only if they're true in all ranges, otherwise they're `false`. +- `address` always returns the comma-delimited addresses string. +- Other properties are `null` unless all ranges share the same value. For example, the following code creates a `RangeAreas` in which only one range is an entire column and only one is filled with pink. The console will show `null` for the fill color, `false` for the `isEntireRow` property, and "Sheet1!F3:F5, Sheet1!H:H" (assuming the sheet name is "Sheet1") for the `address` property. @@ -170,3 +193,4 @@ await Excel.run(async (context) => { - [Fundamental programming concepts with the Excel JavaScript API](../reference/overview/excel-add-ins-reference-overview.md) - [Read or write to a large range using the Excel JavaScript API](excel-add-ins-ranges-large.md) +- [Read or write to an unbounded range using the Excel JavaScript API](excel-add-ins-ranges-unbounded.md) diff --git a/docs/excel/excel-add-ins-notes.md b/docs/excel/excel-add-ins-notes.md new file mode 100644 index 0000000000..edee3f0969 --- /dev/null +++ b/docs/excel/excel-add-ins-notes.md @@ -0,0 +1,111 @@ +--- +title: Work with notes using the Excel JavaScript API +description: Information on using the APIs to add, remove, and edit notes. +ms.date: 06/26/2025 +ms.localizationpriority: medium +--- + +# Work with notes using the Excel JavaScript API + +This article describes how to add, change, and remove notes in a workbook with the Excel JavaScript API. You can learn more about notes from the [Insert comments and notes in Excel](https://support.microsoft.com/office/bdcc9f5d-38e2-45b4-9a92-0b2b5c7bf6f8) article. For information about the differences between notes and comments, see [The difference between threaded comments and notes](https://support.microsoft.com/office/the-difference-between-threaded-comments-and-notes-75a51eec-4092-42ab-abf8-7669077b7be3). + +Notes are tied to an individual cell. Anyone viewing the workbook with sufficient permissions can view a note. Notes in a workbook are tracked by the `Workbook.notes` property. This includes notes created by users and also notes created by your add-in. The `Workbook.notes` property is a [NoteCollection](/javascript/api/excel/excel.notecollection) object that contains a collection of [Note](/javascript/api/excel/excel.note) objects. Notes are also accessible at the [Worksheet](/javascript/api/excel/excel.worksheet) level. + +> [!TIP] +> To learn about adding and editing comments with the Excel JavaScript API, see [Work with comments using the Excel JavaScript API](excel-add-ins-comments.md). + +## Add a note + +Use the `NoteCollection.add` method to add notes to a workbook. This method takes two parameters: + +- `cellAddress`: The cell where the comment is added. This can either be a string or [Range](/javascript/api/excel/excel.range) object. The range must be a single cell. +- `content`: The comment's content, as a string. + +The following code sample shows how to add a note to the selected cell in a worksheet. + +```js +await Excel.run(async (context) => { + // This function adds a note to the selected cell. + const selectedRange = context.workbook.getSelectedRange(); + + // Note that an InvalidArgument error is thrown if multiple cells are selected. + context.workbook.notes.add(selectedRange, "The first note."); + await context.sync(); +}); +``` + +## Change note visibility + +By default, the content of a note is hidden unless a user hovers over the cell with the note or sets the workbook to display notes. To display a note, use the [Note.visible](/javascript/api/excel/excel.note#excel-excel-note-visible-member) property. The following code sample shows how to change the visibility of a note. + +```js +await Excel.run(async (context) => { + // This function sets the note on cell A1 to visible. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const firstNote = sheet.notes.getItem("A1"); + + firstNote.load(); + await context.sync(); + + firstNote.visible = true; +}); +``` + +## Edit the content of a note + +To edit the content of a note, use the [Note.content](/javascript/api/excel/excel.note#excel-excel-note-content-member) property. The following sample shows how to change the content of the first note in the `NoteCollection`. + +```js +await Excel.run(async (context) => { + // This function changes the content in the first note. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const note = sheet.notes.getItemAt(0); + + note.content = "Changing the content of the first note."; + await context.sync(); +}); +``` + +> [!NOTE] +> Use the `Note.authorName` property to get the author of a note. The author name is a read-only property. + +## Change the size of a note + +To make notes larger or smaller, use the [Note.height](/javascript/api/excel/excel.note#excel-excel-note-height-member) and [Note.width](/javascript/api/excel/excel.note#excel-excel-note-width-member) properties. + +The following sample shows how to set the size of the first note in the `NoteCollection`. + +```js +await Excel.run(async (context) => { + // This function changes the height and width of the first note. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const note = sheet.notes.getItemAt(0); + + note.width = 400; + note.height = 200; + + await context.sync(); +}); +``` + +## Delete a note + +To delete a note, use the [Note.delete](/javascript/api/excel/excel.note#excel-excel-note-delete-member(1)) method. The following sample shows how to delete the note attached to cell **A2**. + +```js +await Excel.run(async (context) => { + // This function deletes the note from cell A2. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const note = sheet.notes.getItem("A2"); + + note.delete(); + await context.sync(); +}); +``` + +## See also + +- [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) +- [Work with workbooks using the Excel JavaScript API](excel-add-ins-workbooks.md) +- [Work with comments using the Excel JavaScript API](excel-add-ins-comments.md) +- [Insert comments and notes in Excel](https://support.microsoft.com/office/bdcc9f5d-38e2-45b4-9a92-0b2b5c7bf6f8) diff --git a/docs/excel/excel-add-ins-overview.md b/docs/excel/excel-add-ins-overview.md index ab705b364e..10405467a8 100644 --- a/docs/excel/excel-add-ins-overview.md +++ b/docs/excel/excel-add-ins-overview.md @@ -1,4 +1,4 @@ ---- +--- title: Excel add-ins overview description: Excel add-in allow you to extend Excel application functionality across multiple platforms including Windows, Mac, iPad, and in a browser. ms.date: 03/21/2023 @@ -23,7 +23,7 @@ The Office Add-ins platform provides the framework and Office.js JavaScript APIs - **Cross-platform support**: Excel add-ins run in Office on the web, Windows, Mac, and iPad. - **Centralized deployment**: Admins can quickly and easily deploy Excel add-ins to users throughout an organization. - **Use of standard web technology**: Create your Excel add-in using familiar web technologies such as HTML, CSS, and JavaScript. -- **Distribution via AppSource**: Share your Excel add-in with a broad audience by publishing it to [AppSource](https://appsource.microsoft.com/marketplace/apps?product=office). +- **Distribution via Microsoft Marketplace**: Share your Excel add-in with a broad audience by publishing it to [Microsoft Marketplace](https://marketplace.microsoft.com/marketplace/apps?product=office). > [!NOTE] > Excel add-ins are different from COM and VSTO add-ins, which are earlier Office integration solutions that run only in Office on Windows. Unlike COM add-ins, Excel add-ins don't require you to install any code on a user's device, or within Excel. @@ -47,7 +47,7 @@ The [manifest](../develop/add-in-manifests.md) is a configuration file that defi - How the add-in integrates with Excel, including any custom UI that the add-in creates (ribbon buttons, context menus, and so on). - Permissions that the add-in requires, such as reading and writing to the document. -To enable end users to install and use an Excel add-in, you must publish its manifest either to AppSource or to an add-ins catalog. For details about publishing to AppSource, see [Make your solutions available in AppSource and within Office](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center). +To enable end users to install and use an Excel add-in, you must publish its manifest either to Microsoft Marketplace or to an add-ins catalog. For details about publishing to Microsoft Marketplace, see [Make your solutions available in Microsoft Marketplace and within Office](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center). ## Capabilities of an Excel add-in @@ -91,7 +91,7 @@ Content add-ins are surfaces that you can embed directly into Excel documents. Y ![Content add-in in Excel.](../images/excel-add-in-content-map.png) -For more information about content add-ins, see [Content Office Add-ins](../design/content-add-ins.md). For a sample that implements a content add-in in Excel, see [Excel Content Add-in Humongous Insurance](https://github.com/OfficeDev/Excel-Content-Add-in-Humongous-Insurance) in GitHub. +For more information about content add-ins, see [Content Office Add-ins](../design/content-add-ins.md). For a sample that implements a content add-in in Excel, see [Excel content add-in: Humongous Insurance](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-content-add-in) in GitHub. ## JavaScript APIs to interact with workbook content diff --git a/docs/excel/excel-add-ins-pivottables.md b/docs/excel/excel-add-ins-pivottables.md index 1b854d33b9..519af17324 100644 --- a/docs/excel/excel-add-ins-pivottables.md +++ b/docs/excel/excel-add-ins-pivottables.md @@ -1,16 +1,23 @@ --- title: Work with PivotTables using the Excel JavaScript API -description: Use the Excel JavaScript API to create PivotTables and interact with their components. -ms.date: 03/04/2022 +description: Learn how to create, configure, and filter PivotTables programmatically with the Excel JavaScript API. +ms.date: 09/22/2025 ms.localizationpriority: medium --- # Work with PivotTables using the Excel JavaScript API -PivotTables streamline larger data sets. They allow the quick manipulation of grouped data. The Excel JavaScript API lets your add-in create PivotTables and interact with their components. This article describes how PivotTables are represented by the Office JavaScript API and provides code samples for key scenarios. +Use the PivotTable APIs to summarize data, group fields, filter, and apply calculations in a workbook. -If you are unfamiliar with the functionality of PivotTables, consider exploring them as an end user. -See [Create a PivotTable to analyze worksheet data](https://support.microsoft.com/office/ccd3c4a6-272f-4c97-afbb-d3f27407fcde#ID0EBBD=PivotTables) for a good primer on these tools. +## Key concepts + +- Four hierarchy categories: rows, columns, data, and filters. +- Adding a hierarchy to a new category removes it from the old one. +- `PivotLayout` gives you the output ranges (for example, `getDataBodyRange`). +- Filtering options: code (PivotFilters) or UI (slicers). +- Add multiple hierarchies, then call `context.sync()` once for speed. + +If you're unfamiliar with PivotTables as an end user, review [Create a PivotTable to analyze worksheet data](https://support.microsoft.com/office/ccd3c4a6-272f-4c97-afbb-d3f27407fcde#ID0EBBD=PivotTables). > [!IMPORTANT] > PivotTables created with OLAP are not currently supported. There is also no support for Power Pivot. @@ -21,9 +28,9 @@ See [Create a PivotTable to analyze worksheet data](https://support.microsoft.co The [PivotTable](/javascript/api/excel/excel.pivottable) is the central object for PivotTables in the Office JavaScript API. -- `Workbook.pivotTables` and `Worksheet.pivotTables` are [PivotTableCollections](/javascript/api/excel/excel.pivottablecollection) that contain the [PivotTables](/javascript/api/excel/excel.pivottable) in the workbook and worksheet, respectively. -- A [PivotTable](/javascript/api/excel/excel.pivottable) contains a [PivotHierarchyCollection](/javascript/api/excel/excel.pivothierarchycollection) that has multiple [PivotHierarchies](/javascript/api/excel/excel.pivothierarchy). -- These [PivotHierarchies](/javascript/api/excel/excel.pivothierarchy) can be added to specific hierarchy collections to define how the PivotTable pivots data (as explained in the [following section](#hierarchies)). +- `Workbook.pivotTables` and `Worksheet.pivotTables` are [PivotTableCollections](/javascript/api/excel/excel.pivottablecollection) that contain the [PivotTables](/javascript/api/excel/excel.pivottable) in the workbook and worksheet. +- A [PivotTable](/javascript/api/excel/excel.pivottable) has a [PivotHierarchyCollection](/javascript/api/excel/excel.pivothierarchycollection) with multiple [PivotHierarchies](/javascript/api/excel/excel.pivothierarchy). +- [PivotHierarchies](/javascript/api/excel/excel.pivothierarchy) can be added to specific hierarchy collections to define how the PivotTable pivots data. - A [PivotHierarchy](/javascript/api/excel/excel.pivothierarchy) contains a [PivotFieldCollection](/javascript/api/excel/excel.pivotfieldcollection) that has exactly one [PivotField](/javascript/api/excel/excel.pivotfield). If the design expands to include OLAP PivotTables, this may change. - A [PivotField](/javascript/api/excel/excel.pivotfield) can have one or more [PivotFilters](/javascript/api/excel/excel.pivotfilters) applied, as long as the field's [PivotHierarchy](/javascript/api/excel/excel.pivothierarchy) is assigned to a hierarchy category. - A [PivotField](/javascript/api/excel/excel.pivotfield) contains a [PivotItemCollection](/javascript/api/excel/excel.pivotitemcollection) that has multiple [PivotItems](/javascript/api/excel/excel.pivotitem). @@ -37,9 +44,9 @@ This fruit farm sales data will be used to make a PivotTable. Each column, such ### Hierarchies -PivotTables are organized based on four hierarchy categories: [row](/javascript/api/excel/excel.rowcolumnpivothierarchy), [column](/javascript/api/excel/excel.rowcolumnpivothierarchy), [data](/javascript/api/excel/excel.datapivothierarchy), and [filter](/javascript/api/excel/excel.filterpivothierarchy). +PivotTables have four hierarchy categories: [row](/javascript/api/excel/excel.rowcolumnpivothierarchy), [column](/javascript/api/excel/excel.rowcolumnpivothierarchy), [data](/javascript/api/excel/excel.datapivothierarchy), and [filter](/javascript/api/excel/excel.filterpivothierarchy). -The farm data shown earlier has five hierarchies: **Farms**, **Type**, **Classification**, **Crates Sold at Farm**, and **Crates Sold Wholesale**. Each hierarchy can only exist in one of the four categories. If **Type** is added to column hierarchies, it cannot also be in the row, data, or filter hierarchies. If **Type** is subsequently added to row hierarchies, it is removed from the column hierarchies. This behavior is the same whether hierarchy assignment is done through the Excel UI or the Excel JavaScript APIs. +Our farm data has five hierarchies: **Farms**, **Type**, **Classification**, **Crates Sold at Farm**, and **Crates Sold Wholesale**. Each hierarchy can only exist in one of the four categories. If **Type** is added to column hierarchies, it cannot also be in the row, data, or filter hierarchies. If **Type** is subsequently added to row hierarchies, it is removed from the column hierarchies. This behavior is the same whether hierarchy assignment is done through the Excel UI or the Excel JavaScript APIs. Row and column hierarchies define how data will be grouped. For example, a row hierarchy of **Farms** will group together all the data sets from the same farm. The choice between row and column hierarchy defines the orientation of the PivotTable. @@ -55,7 +62,7 @@ This PivotTable could be generated through the JavaScript API or through the Exc ## Create a PivotTable -PivotTables need a name, source, and destination. The source can be a range address or table name (passed as a `Range`, `string`, or `Table` type). The destination is a range address (given as either a `Range` or `string`). +Provide a name, source, and destination. The source can be a range address or table name (passed as a `Range`, `string`, or `Table` type). The destination is a range address (given as either a `Range` or `string`). The following samples show various PivotTable creation techniques. ### Create a PivotTable with range addresses @@ -112,9 +119,7 @@ await Excel.run(async (context) => { ## Add rows and columns to a PivotTable -Rows and columns pivot the data around those fields' values. - -Adding the **Farm** column pivots all the sales around each farm. Adding the **Type** and **Classification** rows further breaks down the data based on what fruit was sold and whether it was organic or not. +Rows and columns define how data is grouped. Adding the **Farm** column groups all the sales around each farm. Adding the **Type** and **Classification** rows further breaks down the data based on what fruit was sold and whether it was organic or not. ![A PivotTable with a Farm column and Type and Classification rows.](../images/excel-pivots-table-rows-and-columns.png) @@ -238,7 +243,7 @@ await Excel.run(async (context) => { ### Other PivotLayout functions -By default, PivotTables adjust row and column sizes as needed. This is done when the PivotTable is refreshed. `PivotLayout.autoFormat` specifies that behavior. Any row or column size changes made by your add-in persist when `autoFormat` is `false`. Additionally, the default settings of a PivotTable keep any custom formatting in the PivotTable (such as fills and font changes). Set `PivotLayout.preserveFormatting` to `false` to apply the default format when refreshed. +By default, PivotTables adjust row and column sizes as needed. This occurs when the PivotTable is refreshed. `PivotLayout.autoFormat` specifies that behavior. Any row or column size changes made by your add-in persist when `autoFormat` is `false`. Additionally, the default settings of a PivotTable keep any custom formatting in the PivotTable (such as fills and font changes). Set `PivotLayout.preserveFormatting` to `false` to apply the default format when refreshed. A `PivotLayout` also controls header and total row settings, how empty data cells are displayed, and [alt text](https://support.microsoft.com/topic/44989b2a-903c-4d9a-b742-6a75b451c669) options. The [PivotLayout](/javascript/api/excel/excel.pivotlayout) reference provides a complete list of these features. @@ -417,7 +422,7 @@ await Excel.run(async (context) => { #### Create a slicer -You can create a slicer in a workbook or worksheet by using the `Workbook.slicers.add` method or `Worksheet.slicers.add` method. Doing so adds a slicer to the [SlicerCollection](/javascript/api/excel/excel.slicercollection) of the specified `Workbook` or `Worksheet` object. The `SlicerCollection.add` method has three parameters: +Create a slicer in a workbook or worksheet with the `slicers.add` method. This adds a slicer to the [SlicerCollection](/javascript/api/excel/excel.slicercollection) of the specified `Workbook` or `Worksheet` object. The `SlicerCollection.add` method has three parameters: - `slicerSource`: The data source on which the new slicer is based. It can be a `PivotTable`, `Table`, or string representing the name or ID of a `PivotTable` or `Table`. - `sourceField`: The field in the data source by which to filter. It can be a `PivotField`, `TableColumn`, or string representing the name or ID of a `PivotField` or `TableColumn`. @@ -467,7 +472,7 @@ await Excel.run(async (context) => { #### Style and format a slicer -You add-in can adjust a slicer's display settings through `Slicer` properties. The following code sample sets the style to **SlicerStyleLight6**, sets the text at the top of the slicer to **Fruit Types**, places the slicer at the position **(395, 15)** on the drawing layer, and sets the slicer's size to **135x150** pixels. +Adjust a slicer's display settings with `Slicer` properties. The following code sample sets the style to **SlicerStyleLight6**, sets the text at the top of the slicer to **Fruit Types**, places the slicer at the position **(395, 15)** on the drawing layer, and sets the slicer's size to **135x150** pixels. ```js await Excel.run(async (context) => { diff --git a/docs/excel/excel-add-ins-ranges-checkboxes.md b/docs/excel/excel-add-ins-ranges-checkboxes.md new file mode 100644 index 0000000000..85f2306c5e --- /dev/null +++ b/docs/excel/excel-add-ins-ranges-checkboxes.md @@ -0,0 +1,83 @@ +--- +title: Add checkboxes using the Excel JavaScript API +description: Learn how to add checkboxes using the Excel JavaScript API. +ms.date: 04/08/2025 +ms.localizationpriority: medium +--- + +# Add checkboxes using the Excel JavaScript API + +This article provides code samples that add, edit, and remove checkboxes from a range with the Excel JavaScript API. For the complete list of properties and methods that the `Range` object supports, see [Excel.Range class](/javascript/api/excel/excel.range). + +To use checkboxes, make sure that your range contains Boolean values, like **TRUE** or **FALSE**. Only Boolean values can be replaced with checkboxes using the Excel JavaScript API. + +The following screenshot shows an example of checkboxes in a table. The table lists a variety of items, and the checkboxes indicate whether or not the items are types of fruit. + +:::image type="content" source="../images/excel-range-checkbox-table.png" alt-text="A table with checkboxes in the second column."::: + +> [!NOTE] +> To experiment with the code snippets in this article in a complete sample, open [Script Lab](../overview/explore-with-script-lab.md) in Excel and select [Checkboxes](https://github.com/OfficeDev/office-js-snippets/blob/prod/samples/excel/42-range/range-cell-control.yaml) in our **Samples** library. + +## Add checkboxes + +To add checkboxes to a range, use the [`Range.control`](/javascript/api/excel/excel.range#excel-excel-range-control-member) property to access the [`CellControl`](/javascript/api/excel/excel.cellcontrol) type, and set the `CellControlType` enum value to `checkbox`. Only Boolean values, like **TRUE** or **FALSE**, display as checkboxes in your range. The following code sample shows how to add checkboxes to the **Analysis** column of a table named **FruitTable**. + +```js +await Excel.run(async (context) => { + // This code sample shows how to add checkboxes to a table. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Get the "Analysis" column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Change the Boolean values in the range to checkboxes. + range.control = { + type: Excel.CellControlType.checkbox + }; + await context.sync(); +}); +``` + +## Change the value of a checkbox + +To select or clear a checkbox with the Excel JavaScript API, change the Boolean value in that cell. Use `Range.values` to change the value of a cell. The following code sample shows how to set the value of a cell to **TRUE**. Note that if the cell doesn't already display a checkbox, then the code sample simply changes the Boolean value of the cell. + +```js +await Excel.run(async (context) => { + // This code sample shows how to change the value of cell B3. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("B3"); + + range.values = [["TRUE"]]; + await context.sync(); +}); +``` + +## Remove checkboxes + +To remove checkboxes from a range and return the values to simple Booleans, use the [`Range.control`](/javascript/api/excel/excel.range#excel-excel-range-control-member) property to access the [`CellControl`](/javascript/api/excel/excel.cellcontrol) type, and set the `CellControlType` enum value to `empty`. The following code sample shows how to remove checkboxes from the **Analysis** column of a table named **FruitTable**. + +```js +await Excel.run(async (context) => { + // This code sample shows how to remove checkboxes from a table. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Get the "Analysis" column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Change the checkboxes to Boolean values. + range.control = { + type: Excel.CellControlType.empty + }; + await context.sync(); +}); +``` + +> [!NOTE] +> To remove all content from a range, use the [`Range.clearOrResetContents`](/javascript/api/excel/excel.range#excel-excel-range-clearorresetcontents-member(1)) method. + +## See also + +- [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) +- [Work with cells using the Excel JavaScript API](excel-add-ins-cells.md) +- [Insert a range using the Excel JavaScript API](excel-add-ins-ranges-insert.md) diff --git a/docs/excel/excel-add-ins-ranges-large.md b/docs/excel/excel-add-ins-ranges-large.md index b2f68d1ba0..ed565fc3c2 100644 --- a/docs/excel/excel-add-ins-ranges-large.md +++ b/docs/excel/excel-add-ins-ranges-large.md @@ -1,28 +1,47 @@ --- title: Read or write to large ranges using the Excel JavaScript API -description: Learn how to read or write to large ranges with the Excel JavaScript API. -ms.date: 04/02/2021 +description: Learn strategies to efficiently read or write large Excel ranges with the Excel JavaScript API, without hitting resource limits. +ms.date: 09/22/2025 ms.topic: best-practice ms.localizationpriority: medium --- # Read or write to a large range using the Excel JavaScript API -This article describes how to handle reading and writing to large ranges with the Excel JavaScript API. +Use these patterns to read or write large ranges, while avoiding resource limit errors. -## Run separate read or write operations for large ranges +- Split big ranges into smaller blocks. Don't load or write everything at once. +- Load only what you need (for example, just `values` instead of `values,numberFormat,formulas`). +- Use `getSpecialCells` and `RangeAreas` to work with scattered cells instead of a large range. +- If you encounter a limit error, retry with a smaller block size. +- Apply formatting after the data is in place. -If a range contains a large number of cells, values, number formats, or formulas, it may not be possible to run API operations on that range. The API will always make a best attempt to run the requested operation on a range (i.e., to retrieve or write the specified data), but attempting to perform read or write operations for a large range may result in an API error due to excessive resource utilization. To avoid such errors, we recommend that you run separate read or write operations for smaller subsets of a large range, instead of attempting to run a single read or write operation on a large range. +## When to split a large range -For details on the system limitations, see the "Excel add-ins" section of [Resource limits and performance optimization for Office Add-ins](../concepts/resource-limits-and-performance-optimization.md#excel-add-ins). +| Scenario | Sign you should split the range | Approach | +|----------|----------------------|----------| +| Reading millions of cells | Timeout or resource error | Read in row or column blocks. Start with 5k–20k rows. | +| Writing a large result set | Single `values` write fails | Write in row blocks (with same column count for each block). | +| Sparse updates | Many distant cells | Build combined address string with `getRanges` and `RangeAreas`. | +| Writing data and formatting | Formatting slows Excel | Write values first, format afterward. | -### Conditional formatting of ranges +## Defer formatting & calculations -Ranges can have formats applied to individual cells based on conditions. For more information about this, see [Apply conditional formatting to Excel ranges](excel-add-ins-conditional-formatting.md). +Formatting and calculation-heavy operations, such as conditional formats or formula writes, add time on large areas. Consider: + +- First write raw values (plain numbers or text), then add formulas or formats in a second pass. +- Use `setDirty` only on necessary recalculation scopes. +- Limit conditional formats to used rows instead of entire column references (such as `A2:A5000` instead of `A:A`) with `getUsedRange`. + +## Next steps + +- Learn about related [resource limits and performance optimization](../concepts/resource-limits-and-performance-optimization.md#excel-add-ins). +- Handle large but sparse selections with [multiple ranges](excel-add-ins-multiple-ranges.md). +- Compare with patterns for [unbounded ranges](excel-add-ins-ranges-unbounded.md). +- Explore special cell targeting in [find special cells](excel-add-ins-ranges-special-cells.md). ## See also - [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) - [Work with cells using the Excel JavaScript API](excel-add-ins-cells.md) -- [Read or write to an unbounded range using the Excel JavaScript API](excel-add-ins-ranges-unbounded.md) -- [Work with multiple ranges simultaneously in Excel add-ins](excel-add-ins-multiple-ranges.md) +- [Apply conditional formatting to Excel ranges](excel-add-ins-conditional-formatting.md) diff --git a/docs/excel/excel-add-ins-ranges-precedents-dependents.md b/docs/excel/excel-add-ins-ranges-precedents-dependents.md index 2194db3e55..a624663115 100644 --- a/docs/excel/excel-add-ins-ranges-precedents-dependents.md +++ b/docs/excel/excel-add-ins-ranges-precedents-dependents.md @@ -1,18 +1,27 @@ --- title: Work with formula precedents and dependents using the Excel JavaScript API description: Learn how to use the Excel JavaScript API to retrieve formula precedents and dependents. -ms.date: 05/30/2024 +ms.date: 09/22/2025 ms.localizationpriority: medium --- # Get formula precedents and dependents using the Excel JavaScript API -Excel formulas often contain references to other cells in the same worksheet or workbook. These cross-cell references are known as "precedents" and "dependents". A precedent is a cell that provides data to a formula. A dependent is a cell that contains a formula which refers to other cells. To learn more about features in the Excel UI related to precedents and dependents, such as **Trace Precedents** and **Trace Dependents**, see [Display the relationships between formulas and cells](https://support.microsoft.com/office/a59bef2b-3701-46bf-8ff1-d3518771d507). +Excel formulas often refer to other cells. Those input cells are the formula's "precedents". Any formula cell that depends on other cells is a "dependent" of those cells. To learn more about the related Excel UI features, see [Display the relationships between formulas and cells](https://support.microsoft.com/office/a59bef2b-3701-46bf-8ff1-d3518771d507). -A precedent cell may have its own precedent cells. Every precedent cell in this chain of precedents is still a precedent of the original cell. The same relationship exists for dependents. Any cell affected by another cell is a dependent of that cell. A "direct precedent" is the first preceding group of cells in this sequence, similar to the concept of parents in a parent-child relationship. A "direct dependent" is the first dependent group of cells in a sequence, similar to children in a parent-child relationship. +Chains of precedents and dependents can form. A precedent can itself have precedents, and so on. The same idea applies to dependents. A "direct precedent" or "direct dependent" is only the first level: the cells a formula points to, or the cells that point straight to a formula. This article provides code samples that retrieve the precedents and dependents of formulas using the Excel JavaScript API. For the complete list of properties and methods that the `Range` object supports, see [Range Object (JavaScript API for Excel)](/javascript/api/excel/excel.range). +## Key points + +- Use `getPrecedents` or `getDependents` to get all related cells. Use `getDirectPrecedents` or `getDirectDependents` to get only the first level. +- Both APIs return a `WorkbookRangeAreas` object. It groups addresses by worksheet. Look in each `areas.items` list for the individual `Range` objects. +- Very large sets, such as thousands of cells, can be slow. Start with the direct methods or narrow the selection first. +- These APIs do not cross workbook boundaries. +- If there are no related cells, an `ItemNotFound` error is thrown. Catch it and show a friendly message. +- If you highlight cells, give users a way to clear the formatting. + ## Get the precedents of a formula Locate a formula's precedent cells with [Range.getPrecedents](/javascript/api/excel/excel.range#excel-excel-range-getprecedents-member(1)). `Range.getPrecedents` returns a `WorkbookRangeAreas` object. This object contains the addresses of all the precedents in the workbook. It has a separate `RangeAreas` object for each worksheet containing at least one formula precedent. To learn more about the `RangeAreas` object, see [Work with multiple ranges simultaneously in Excel add-ins](excel-add-ins-multiple-ranges.md). @@ -65,7 +74,7 @@ await Excel.run(async (context) => { ``` > [!NOTE] -> The `Range.getPrecedents` and `Range.getDirectPrecedents` methods return an `ItemNotFound` error if no precedent cells are found. +> The `Range.getPrecedents` and `Range.getDirectPrecedents` methods return an `ItemNotFound` error if no precedent cells are found. Catch this and provide a user-friendly message. ## Get the dependents of a formula @@ -119,7 +128,7 @@ await Excel.run(async (context) => { ``` > [!NOTE] -> The `Range.getDependents` and `Range.getDirectDependents` methods return an `ItemNotFound` error if no dependent cells are found. +> The `Range.getDependents` and `Range.getDirectDependents` methods return an `ItemNotFound` error if no dependent cells are found. Catch this and provide a user-friendly message. ## See also diff --git a/docs/excel/excel-add-ins-ranges-remove-duplicates.md b/docs/excel/excel-add-ins-ranges-remove-duplicates.md index f868e56e36..f67f79175f 100644 --- a/docs/excel/excel-add-ins-ranges-remove-duplicates.md +++ b/docs/excel/excel-add-ins-ranges-remove-duplicates.md @@ -1,17 +1,26 @@ --- title: Remove duplicates using the Excel JavaScript API description: Learn how to use the Excel JavaScript API to remove duplicates. -ms.date: 02/17/2022 +ms.date: 09/22/2025 ms.localizationpriority: medium --- # Remove duplicates using the Excel JavaScript API -This article provides a code sample that removes duplicate entries in a range using the Excel JavaScript API. For the complete list of properties and methods that the `Range` object supports, see [Excel.Range class](/javascript/api/excel/excel.range). +This article shows how to remove duplicate rows within a range using the [Range.removeDuplicates](/javascript/api/excel/excel.range#excel-excel-range-removeduplicates-member(1)) method. For the full list of range members, see [Excel.Range class](/javascript/api/excel/excel.range). + +## Key points + +- It works only inside the supplied `range`. +- Column indexes are zero-based and relative to the range. +- Set `includeHeader: true` to skip the first row when checking duplicates. +- Empty cells count like any other value. Two empty cells can be duplicates. +- It compares stored cell values, not formula logic. +- It returns `RemoveDuplicatesResult` with `removed` and `uniqueRemaining` counts. ## Remove rows with duplicate entries -The [Range.removeDuplicates](/javascript/api/excel/excel.range#excel-excel-range-removeduplicates-member(1)) method removes rows with duplicate entries in the specified columns. The method goes through each row in the range from the lowest-valued index to the highest-valued index in the range (from top to bottom). A row is deleted if a value in its specified column or columns appeared earlier in the range. Rows in the range below the deleted row are shifted up. `removeDuplicates` does not affect the position of cells outside of the range. +The `removeDuplicates` method removes rows with duplicate entries in the specified columns. The method goes through each row in the range from the lowest-valued index to the highest-valued index in the range (from top to bottom). A row is deleted if a value in its specified column or columns appeared earlier in the range. Rows in the range below the deleted row are shifted up. `removeDuplicates` doesn't affect the position of cells outside of the range. `removeDuplicates` takes in a `number[]` representing the column indices which are checked for duplicates. This array is zero-based and relative to the range, not the worksheet. The method also takes in a boolean parameter that specifies whether the first row is a header. When `true`, the top row is ignored when considering duplicates. The `removeDuplicates` method returns a `RemoveDuplicatesResult` object that specifies the number of rows removed and the number of unique rows remaining. diff --git a/docs/excel/excel-add-ins-ranges-set-get.md b/docs/excel/excel-add-ins-ranges-set-get.md index c899d27a2f..3ca93a9f48 100644 --- a/docs/excel/excel-add-ins-ranges-set-get.md +++ b/docs/excel/excel-add-ins-ranges-set-get.md @@ -55,7 +55,7 @@ In the following screenshot, the used range is the table with values in each cel ### Select the cell at the edge of the current used range -The following code sample shows how use the `Range.getRangeEdge` method to select the cell at the furthest edge of the current used range, in the direction up. This action matches the result of using the Ctrl+Up arrow key keyboard shortcut while a range is selected. +The following code sample shows how use the `Range.getRangeEdge` method to select the cell at the furthest edge of the current used range, in the direction up. This action matches the result of using the Ctrl+Up arrow key keyboard shortcut while a range is selected. ```js await Excel.run(async (context) => { @@ -94,7 +94,7 @@ The following screenshot shows the same table as the preceding screenshot, with ### Select all cells from current range to furthest edge of used range -The following code sample shows how use the `Range.getExtendedRange` method to to select all the cells from the currently selected range to the furthest edge of the used range, in the direction down. This action matches the result of using the Ctrl+Shift+Down arrow key keyboard shortcut while a range is selected. +The following code sample shows how use the `Range.getExtendedRange` method to to select all the cells from the currently selected range to the furthest edge of the used range, in the direction down. This action matches the result of using the Ctrl+Shift+Down arrow key keyboard shortcut while a range is selected. ```js await Excel.run(async (context) => { diff --git a/docs/excel/excel-add-ins-ranges-special-cells.md b/docs/excel/excel-add-ins-ranges-special-cells.md index cb02df5803..9854470110 100644 --- a/docs/excel/excel-add-ins-ranges-special-cells.md +++ b/docs/excel/excel-add-ins-ranges-special-cells.md @@ -1,13 +1,23 @@ --- title: Find special cells within a range using the Excel JavaScript API description: Learn how to use the Excel JavaScript API to find special cells, such as cells with formulas, errors, or numbers. -ms.date: 02/17/2022 +ms.date: 09/19/2025 ms.localizationpriority: medium --- # Find special cells within a range using the Excel JavaScript API -This article provides code samples that find special cells within a range using the Excel JavaScript API. For the complete list of properties and methods that the `Range` object supports, see [Excel.Range class](/javascript/api/excel/excel.range). +Use the Excel JavaScript API to quickly locate cells with formulas, constants, errors, or other characteristics so you can audit, refactor, or apply formatting efficiently. This article shows how to use `Range.getSpecialCells` and `Range.getSpecialCellsOrNullObject`, when to choose each, and how to further narrow results with cell value types. For the full set of properties and methods that the `Range` object supports, see [Excel.Range class](/javascript/api/excel/excel.range). + +## Quick reference + +| Goal | Use this method | If target might not exist | Result type | Error behavior | +|------|-----------------|---------------------------|-------------|----------------| +| Require at least one matching cell | `getSpecialCells` | N/A | `RangeAreas` | Throws `ItemNotFound` if none exist | +| Optionally act only if matches exist | `getSpecialCellsOrNullObject` | Check `isNullObject` after `context.sync()` | `RangeAreas` proxy | No error, returns `isNullObject = true` | + +> [!TIP] +> Treat `getSpecialCells` like an assertion. Use `getSpecialCellsOrNullObject` when the absence of matches is a valid result, not an error. ## Find ranges with special cells @@ -21,10 +31,10 @@ getSpecialCells(cellType: Excel.SpecialCellType, cellValueType?: Excel.SpecialCe getSpecialCellsOrNullObject(cellType: Excel.SpecialCellType, cellValueType?: Excel.SpecialCellValueType): Excel.RangeAreas; ``` -The following code sample uses the `getSpecialCells` method to find all the cells with formulas. About this code, note: +The following code sample uses `getSpecialCells` to find all cells with formulas. Please note: -- It limits the part of the sheet that needs to be searched by first calling `Worksheet.getUsedRange` and calling `getSpecialCells` for only that range. -- The `getSpecialCells` method returns a `RangeAreas` object, so all of the cells with formulas will be colored pink even if they are not all contiguous. +- The search scope is restricted for better performance by calling `worksheet.getUsedRange()` first. +- `getSpecialCells` returns a single `RangeAreas` object, so non‑contiguous matches can be formatted in one operation. ```js await Excel.run(async (context) => { @@ -62,7 +72,7 @@ await Excel.run(async (context) => { }); ``` -For simplicity, all other code samples in this article use the `getSpecialCells` method instead of `getSpecialCellsOrNullObject`. +For simplicity, the remaining samples in this article use `getSpecialCells`. ## Narrow the target cells with cell value types @@ -76,14 +86,16 @@ The `Range.getSpecialCells()` and `Range.getSpecialCellsOrNullObject()` methods The `Excel.SpecialCellValueType` enum has these four basic types (in addition to the other combined values described later in this section): - `Excel.SpecialCellValueType.errors` -- `Excel.SpecialCellValueType.logical` (which means boolean) +- `Excel.SpecialCellValueType.logical` (which means Boolean) - `Excel.SpecialCellValueType.numbers` - `Excel.SpecialCellValueType.text` -The following code sample finds special cells that are numerical constants and colors those cells pink. About this code, note: +The next sample finds numerical constants and colors them pink. -- It only highlights cells that have a literal number value. It won't highlight cells that have a formula (even if the result is a number) or a boolean, text, or error state cells. -- To test the code, be sure the worksheet has some cells with literal number values, some with other kinds of literal values, and some with formulas. +Key points: + +- Only literal numeric constants are targeted (not formulas that evaluate to numbers, nor Booleans, text, or error cells). +- To test, populate the sheet with literal number values, other kinds of literal values, and formulas. ```js await Excel.run(async (context) => { @@ -100,7 +112,7 @@ await Excel.run(async (context) => { ### Test for multiple cell value types -Sometimes you need to operate on more than one cell value type, such as all text-valued and all boolean-valued (`Excel.SpecialCellValueType.logical`) cells. The `Excel.SpecialCellValueType` enum has values with combined types. For example, `Excel.SpecialCellValueType.logicalText` targets all boolean and all text-valued cells. `Excel.SpecialCellValueType.all` is the default value, which does not limit the cell value types returned. The following code sample colors all cells with formulas that produce number or boolean value. +Sometimes you need to operate on more than one cell value type, such as all text-valued and all Boolean-valued (`Excel.SpecialCellValueType.logical`) cells. The `Excel.SpecialCellValueType` enum has values with combined types. For example, `Excel.SpecialCellValueType.logicalText` targets all Boolean and all text-valued cells. `Excel.SpecialCellValueType.all` is the default value, which does not limit the cell value types returned. The following code sample colors all cells with formulas that produce number or Boolean value. ```js await Excel.run(async (context) => { @@ -115,9 +127,12 @@ await Excel.run(async (context) => { }); ``` +## Next steps + +- Combine special-cell queries with [string search](excel-add-ins-ranges-string-match.md) for richer auditing. +- Apply formatting, comments, or data validation to the resulting [RangeAreas](excel-add-ins-multiple-ranges.md) object. + ## See also - [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) - [Work with cells using the Excel JavaScript API](excel-add-ins-cells.md) -- [Find a string using the Excel JavaScript API](excel-add-ins-ranges-string-match.md) -- [Work with multiple ranges simultaneously in Excel add-ins](excel-add-ins-multiple-ranges.md) diff --git a/docs/excel/excel-add-ins-ranges-unbounded.md b/docs/excel/excel-add-ins-ranges-unbounded.md index b9d3482783..f1449e140b 100644 --- a/docs/excel/excel-add-ins-ranges-unbounded.md +++ b/docs/excel/excel-add-ins-ranges-unbounded.md @@ -1,15 +1,23 @@ --- title: Read or write to an unbounded range using the Excel JavaScript API -description: Learn how to use the Excel JavaScript API to read or write to an unbounded range. -ms.date: 02/17/2022 +description: Understand what unbounded ranges are, why cell-level operations return null or fail, and how to safely work with entire rows or columns by narrowing scope. +ms.date: 09/22/2025 ms.localizationpriority: medium --- # Read or write to an unbounded range using the Excel JavaScript API -This article describes how to read and write to an unbounded range with the Excel JavaScript API. For the complete list of properties and methods that the `Range` object supports, see [Excel.Range class](/javascript/api/excel/excel.range). +Use these guidelines to understand how entire-column and entire-row addresses behave, and apply patterns that reduce errors and memory usage. For the complete list of properties and methods that the `Range` object supports, see [Excel.Range class](/javascript/api/excel/excel.range). -An unbounded range address is a range address that specifies either entire columns or entire rows. For example: +## Key points + +- "Unbounded" means entire columns (like `A:F`) or entire rows (such as `2:2`). +- Cell-level properties (like `values`, `text`, `numberFormat`, or `formulas`) come back as `null` for unbounded reads. +- You can't set cell-level properties on an unbounded range. This returns an error. +- Narrow to the used cells first with `getUsedRange()`. +- Prefer explicit bounds (like `A1:F5000`) for faster calculation speeds and lower memory use. + +The following are examples of unbounded ranges. - Range addresses comprised of entire columns. - `C:C` @@ -20,18 +28,25 @@ An unbounded range address is a range address that specifies either entire colum ## Read an unbounded range -When the API makes a request to retrieve an unbounded range (for example, `getRange('C:C')`), the response will contain `null` values for cell-level properties such as `values`, `text`, `numberFormat`, and `formula`. Other properties of the range, such as `address` and `cellCount`, will contain valid values for the unbounded range. +When you request an unbounded range (for example, `getRange('C:C')`), the response returns `null` for cell-level properties like `values`, `text`, `numberFormat`, and `formula`. Other properties (`address`, `cellCount`) are still valid. ## Write to an unbounded range -You cannot set cell-level properties such as `values`, `numberFormat`, and `formula` on an unbounded range because the input request is too large. For example, the following code example is not valid because it attempts to specify `values` for an unbounded range. The API returns an error if you attempt to set cell-level properties for an unbounded range. +You can't set cell-level properties like `values`, `numberFormat`, or `formula` on an unbounded range because the request is too large. For example, the next code sample fails because it sets `values` for an unbounded range. ```js -// Note: This code sample attempts to specify `values` for an unbounded range, which is not a valid request. The sample will return an error. -let range = context.workbook.worksheets.getActiveWorksheet().getRange('A:B'); -range.values = 'Due Date'; +// Invalid: Attempting to write cell-level data to unbounded columns. +let range = context.workbook.worksheets.getActiveWorksheet().getRange("A:B"); +range.values = [["Due Date"]]; // This throws an error. ``` +## Next steps + +- Learn strategies for [large bounded ranges](excel-add-ins-ranges-large.md). +- Combine multiple explicit ranges with [multiple ranges](excel-add-ins-multiple-ranges.md). +- Optimize performance with [resource limits guidance](../concepts/resource-limits-and-performance-optimization.md#excel-add-ins). +- Identify specific cells using [special cells](excel-add-ins-ranges-special-cells.md). + ## See also - [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) diff --git a/docs/excel/excel-add-ins-shapes.md b/docs/excel/excel-add-ins-shapes.md index 1fce516e1e..feab15048c 100644 --- a/docs/excel/excel-add-ins-shapes.md +++ b/docs/excel/excel-add-ins-shapes.md @@ -1,7 +1,7 @@ --- title: Work with shapes using the Excel JavaScript API description: Learn how Excel defines shapes as any object that sits on the drawing layer of Excel. -ms.date: 02/17/2022 +ms.date: 04/14/2025 ms.localizationpriority: medium --- @@ -51,7 +51,7 @@ await Excel.run(async (context) => { ### Images -JPEG, PNG, and SVG images can be inserted into a worksheet as shapes. The `ShapeCollection.addImage` method takes a base64-encoded string as an argument. This is either a JPEG or PNG image in string form. `ShapeCollection.addSvg` also takes in a string, though this argument is XML that defines the graphic. +JPEG, PNG, and SVG images can be inserted into a worksheet as shapes. The `ShapeCollection.addImage` method takes a Base64-encoded string as an argument. This is either a JPEG or PNG image in string form. `ShapeCollection.addSvg` also takes in a string, though this argument is XML that defines the graphic. The following code sample shows an image file being loaded by a [FileReader](https://developer.mozilla.org/docs/Web/API/FileReader) as a string. The string has the metadata "base64," removed before the shape is created. @@ -135,6 +135,27 @@ await Excel.run(async (context) => { }); ``` +## Get the active shape + +Get the active shape by using either of the following methods. + +- [Workbook.getActiveShape](/javascript/api/excel/excel.workbook) +- [Workbook.getActiveShapeOrNullObject](/javascript/api/excel/excel.workbook) + +The following code sample shows how to get the active shape in a workbook and increase its height by 10%. + +```javascript + await Excel.run(async (context) => { + const shape = context.workbook.getActiveShapeOrNullObject(); + if (shape !== null) { + shape.load("height"); + await context.sync(); + shape.height = shape.height + shape.height * 0.1; + await context.sync(); + } + }); +``` + ## Text in shapes Geometric Shapes can contain text. Shapes have a `textFrame` property of type [TextFrame](/javascript/api/excel/excel.textframe). The `TextFrame` object manages the text display options (such as margins and text overflow). `TextFrame.textRange` is a [TextRange](/javascript/api/excel/excel.textrange) object with the text content and font settings. @@ -216,7 +237,7 @@ await Excel.run(async (context) => { ## Export shapes as images -Any `Shape` object can be converted to an image. [Shape.getAsImage](/javascript/api/excel/excel.shape#excel-excel-shape-getasimage-member(1)) returns base64-encoded string. The image's format is specified as a [PictureFormat](/javascript/api/excel/excel.pictureformat) enum passed to `getAsImage`. +Any `Shape` object can be converted to an image. [Shape.getAsImage](/javascript/api/excel/excel.shape#excel-excel-shape-getasimage-member(1)) returns Base64-encoded string. The image's format is specified as a [PictureFormat](/javascript/api/excel/excel.pictureformat) enum passed to `getAsImage`. ```js await Excel.run(async (context) => { @@ -227,7 +248,7 @@ await Excel.run(async (context) => { await context.sync(); console.log(stringResult.value); - // Instead of logging, your add-in may use the base64-encoded string to save the image as a file or insert it in HTML. + // Instead of logging, your add-in may use the Base64-encoded string to save the image as a file or insert it in HTML. }); ``` diff --git a/docs/excel/excel-add-ins-troubleshooting.md b/docs/excel/excel-add-ins-troubleshooting.md index 6191ed4b6c..59499d48d6 100644 --- a/docs/excel/excel-add-ins-troubleshooting.md +++ b/docs/excel/excel-add-ins-troubleshooting.md @@ -1,12 +1,12 @@ --- -title: Troubleshooting Excel add-ins -description: Learn how to troubleshoot development errors in Excel add-ins. -ms.date: 02/17/2022 +title: Troubleshoot Excel add-ins +description: 'Diagnose and resolve common Excel add-in errors: workbook focus changes, API limitations, and known issues.' +ms.date: 09/22/2025 ms.topic: troubleshooting-error-codes ms.localizationpriority: medium --- -# Troubleshooting Excel add-ins +# Troubleshoot Excel add-ins This article discusses troubleshooting issues that are unique to Excel. Please use the feedback tool at the bottom of the page to suggest other issues that can be added to the article. @@ -38,11 +38,11 @@ The following APIs are affected by this workbook switch. > [!NOTE] > This only applies to multiple Excel workbooks open on Windows or Mac. -## Coauthoring +## Coauthoring and merge conflicts See [Coauthoring in Excel add-ins](co-authoring-in-excel-add-ins.md) for patterns to use with events in a coauthoring environment. The article also discusses potential merge conflicts when using certain APIs, such as [`TableRowCollection.add`](/javascript/api/excel/excel.tablerowcollection#excel-excel-tablerowcollection-add-member(1)). -## Known Issues +## Known issues ### Binding events return temporary `Binding` objects @@ -85,10 +85,6 @@ The [useStandardHeight](/javascript/api/excel/excel.cellpropertiesformat#excel-e On all platforms, the [useStandardHeight](/javascript/api/excel/excel.cellpropertiesformat#excel-excel-cellpropertiesformat-usestandardheight-member) and [useStandardWidth](/javascript/api/excel/excel.cellpropertiesformat#excel-excel-cellpropertiesformat-usestandardwidth-member) properties of `CellPropertiesFormat` are only intended to be set to `true`. Setting these properties to `false` has no effect. -### Range `getImage` method unsupported on Excel for Mac - -The Range [getImage](/javascript/api/excel/excel.range#excel-excel-range-getimage-member(1)) method isn't currently supported in Excel for Mac. See [OfficeDev/office-js Issue #235](https://github.com/OfficeDev/office-js/issues/235) for the current status. - ### Range return character limit The [Worksheet.getRange(address)](/javascript/api/excel/excel.worksheet#excel-excel-worksheet-getrange-member(1)) and [Worksheet.getRanges(address)](/javascript/api/excel/excel.worksheet#excel-excel-worksheet-getranges-member(1)) methods have an address string limit of 8192 characters. When this limit is exceeded, the address string is truncated to 8192 characters. diff --git a/docs/excel/excel-add-ins-undo-capabilities.md b/docs/excel/excel-add-ins-undo-capabilities.md new file mode 100644 index 0000000000..ec59e6a2c4 --- /dev/null +++ b/docs/excel/excel-add-ins-undo-capabilities.md @@ -0,0 +1,140 @@ +--- +title: Undo capabilities with the Excel JavaScript API +description: Learn how to preserve the undo stack in your Excel add-ins. +ms.date: 09/09/2025 +ms.localizationpriority: medium +--- + +# Undo support with the Excel JavaScript API + +Excel add-ins support undo behavior. This preserves both actions performed by Excel JavaScript APIs and actions performed by the user in Excel. These actions are saved in the *undo stack* for an individual user, allowing the user to step back through their actions when desired. + +## Undo grouping + +The Excel JavaScript API also supports undo grouping. This allows you to group multiple API calls into a single undoable action for your add-in user. For example, if your add-in needs to make several different updates across multiple worksheets in response to a single user command, you can wrap all those updates in a single group. This is done with the `mergeUndoGroup` property provided to the `Excel.run` function. + +If an API within the group doesn't offer undo support, the `UndoNotSupported` error is thrown to let you know that the operation can’t be grouped. Your add-in should gracefully handle this error and present a reasonable message to the user. + +The following code sample shows how to merge multiple actions with `mergeUndoGroup` set to `true`. + +> [!IMPORTANT] +> Ensure that all grouped API calls support undo to avoid errors. See [Unsupported APIs](#unsupported-apis) for more information. + +```js +await Excel.run({ mergeUndoGroup: true }, async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + let range = sheet.getRange("A1"); + range.values = [["123"]]; + + await context.sync(); + + range = sheet.getRange("B2"); + range.values = [["456"]]; + + await context.sync(); +}); +``` + +## Unsupported APIs + +Most Excel JavaScript APIs do support undo actions. However, see the following table for a list of APIs that do not support undo behavior. + +> [!TIP] +> If you call an unsupported API in your add-in, the user’s undo stack is cleared starting from that API call, and a user cannot undo actions past that point. + +| API | Supported in Excel on the web | Supported in Excel on Windows and Excel on Mac | Notes | +|:--------------|:------|:--------|:----------| +| `AllowEditRange.address` | No | No | *None* | +| `AllowEditRange.delete` | No | No | *None* | +| `AllowEditRange.pauseProtection` | No | No | *None* | +| `AllowEditRange.setPassword` | No | No | *None* | +| `AllowEditRange.title` | No | No | *None* | +| `AllowEditRangeCollection.add` | No | No | *None* | +| `AllowEditRangeCollection.pauseProtection` | No | No | *None* | +| `Chart.categoryLabelLevel` | No | No | *None* | +| `Chart.seriesNameLevel` | No | No | *None* | +| `ChartPivotOptions.showAxisFieldButtons` | No | Yes | *None* | +| `ChartPivotOptions.showLegendFieldButtons` | No | Yes | *None* | +| `ChartPivotOptions.showReportFilterFieldButtons` | No | Yes | *None* | +| `ChartPivotOptions.showValueFieldButtons` | No | Yes | *None* | +| `ChartTrendlineLabel.formula` | No | Yes | *None* | +| `DataConnectionCollection.refreshAll` | No | No | *None* | +| `DocumentProperties.author​` | No | Yes | *None* | +| `DocumentProperties.category` | No | Yes | *None* | +| `DocumentProperties.comments` | No | Yes | *None* | +| `DocumentProperties.company` | No | Yes | *None* | +| `DocumentProperties.keywords` | No | Yes | *None* | +| `DocumentProperties.manager` | No | Yes | *None* | +| `DocumentProperties.revisionNumber` | No | Yes | *None* | +| `DocumentProperties.subject` | No | Yes | *None* | +| `DocumentProperties.title` | No | Yes | *None* | +| `LinkedWorkbook.refresh` | No | No | *None* | +| `LinkedWorkbookCollection.refreshAll` | No | No | *None* | +| `NamedItem.comment` | No | Yes | *None* | +| `PivotTableStyle.delete` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `PivotTableStyle.duplicate` | No | Yes | *None* | +| `PivotTableStyle.name` | No | Yes | *None* | +| `PivotTableStyleCollection.add` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `PivotTableStyleCollection.setDefault` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `Query.delete` | No | Yes | API supports undo in Excel on Windows and Mac but doesn't support redo. | +| `Query.refresh` | No | Yes | API supports undo Excel on Windows and Mac but doesn't support redo. | +| `QueryCollection.refreshAll` | No | Yes | API supports undo Excel on Windows and Mac but doesn't support redo. | +| `Slicer.name` | No | Yes | *None* | +| `Slicer.nameInFormula` | No | Yes | *None* | +| `SlicerStyle.delete` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `SlicerStyle.duplicate` | No | Yes | *None* | +| `SlicerStyle.name` | No | Yes | *None* | +| `SlicerStyleCollection.add` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `SlicerStyleCollection.setDefault` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `Style.addIndent` | No | Yes | *None* | +| `Style.autoIndent` | No | Yes | *None* | +| `Style.formulaHidden` | No | Yes | *None* | +| `Style.horizontalAlignment` | No | Yes | *None* | +| `Style.includeAlignment` | No | Yes | *None* | +| `Style.includeBorder` | No | Yes | *None* | +| `Style.includeFont` | No | Yes | *None* | +| `Style.includeNumber` | No | Yes | *None* | +| `Style.includePatterns` | No | Yes | *None* | +| `Style.includeProtection` | No | Yes | *None* | +| `Style.indentLevel` | No | Yes | *None* | +| `Style.locked` | No | Yes | *None* | +| `Style.numberFormat` | No | Yes | *None* | +| `Style.numberFormatLocal` | No | Yes | *None* | +| `Style.orientation` | No | Yes | *None* | +| `Style.readingOrder` | No | Yes | *None* | +| `Style.shrinkToFit` | No | Yes | *None* | +| `Style.textOrientation` | No | Yes | *None* | +| `Style.verticalAlignment` | No | Yes | *None* | +| `Style.wrapText` | No | Yes | *None* | +| `TableStyle.delete` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `TableStyle.duplicate` | No | Yes | *None* | +| `TableStyle.name` | No | Yes | *None* | +| `TableStyleCollection.add` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `TableStyleCollection.setDefault` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `TimelineStyle.delete` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `TimelineStyle.duplicate` | No | Yes | *None* | +| `TimelineStyle.name` | No | Yes | *None* | +| `TimelineStyleCollection.add` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `TimelineStyleCollection.setDefault` | No | Yes | API does **not** support co-authoring undo in Excel on Windows and Mac. | +| `Workbook.close` | No | No | *None* | +| `Workbook.insertWorksheetsFromBase64` | No | No | *None* | +| `Workbook.save` | No | No | *None* | +| `WorkbookProtection.protect` | No | No | *None* | +| `WorkbookProtection.unprotect` | No | No | *None* | +| `Worksheet.copy` | No | No | *None* | +| `Worksheet.delete` | No | No | *None* | +| `Worksheet.name` | Yes | No | *None* | +| `Worksheet.standardWidth` | No | Yes | *None* | +| `Worksheet.position` | Yes | No | *None* | +| `Worksheet.visibility​` | Yes | No | *None* | +| `WorksheetCollection.addFromBase64` | No | No | *None* | +| `WorksheetProtection.pauseProtection` | No | No | *None* | +| `WorksheetProtection.protect` | No | No | *None* | +| `WorksheetProtection.resumeProtection` | No | No | *None* | +| `WorksheetProtection.setPassword` | No | No | *None* | +| `WorksheetProtection.unprotect` | No | No | *None* | +| `WorksheetProtection.updateOptions` | No | No | *None* | + +## See also + +- [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) \ No newline at end of file diff --git a/docs/excel/excel-add-ins-workbooks.md b/docs/excel/excel-add-ins-workbooks.md index 7cf112e6d8..e882110669 100644 --- a/docs/excel/excel-add-ins-workbooks.md +++ b/docs/excel/excel-add-ins-workbooks.md @@ -43,9 +43,9 @@ Your add-in can create a new workbook, separate from the Excel instance in which Excel.createWorkbook(); ``` -The `createWorkbook` method can also create a copy of an existing workbook. The method accepts a base64-encoded string representation of an .xlsx file as an optional parameter. The resulting workbook will be a copy of that file, assuming the string argument is a valid .xlsx file. +The `createWorkbook` method can also create a copy of an existing workbook. The method accepts a Base64-encoded string representation of an .xlsx file as an optional parameter. The resulting workbook will be a copy of that file, assuming the string argument is a valid .xlsx file. -You can get your add-in's current workbook as a base64-encoded string by using [file slicing](/javascript/api/office/office.document#office-office-document-getfileasync-member(1)). The [FileReader](https://developer.mozilla.org/docs/Web/API/FileReader) class can be used to convert a file into the required base64-encoded string, as demonstrated in the following example. +You can get your add-in's current workbook as a Base64-encoded string by using [file slicing](/javascript/api/office/office.document#office-office-document-getfileasync-member(1)). The [FileReader](https://developer.mozilla.org/docs/Web/API/FileReader) class can be used to convert a file into the required Base64-encoded string, as demonstrated in the following example. ```js // Retrieve the external workbook file and set up a `FileReader` object. @@ -54,7 +54,7 @@ let reader = new FileReader(); reader.onload = (function (event) { Excel.run(function (context) { - // Remove the metadata before the base64-encoded string. + // Remove the metadata before the Base64-encoded string. let startIndex = reader.result.toString().indexOf("base64,"); let externalWorkbook = reader.result.toString().substr(startIndex + 7); @@ -63,13 +63,13 @@ reader.onload = (function (event) { }); }); -// Read the file as a data URL so we can parse the base64-encoded string. +// Read the file as a data URL so we can parse the Base64-encoded string. reader.readAsDataURL(myFile.files[0]); ``` ### Insert a copy of an existing workbook into the current one -The previous example shows a new workbook being created from an existing workbook. You can also copy some or all of an existing workbook into the one currently associated with your add-in. A [Workbook](/javascript/api/excel/excel.workbook) has the `insertWorksheetsFromBase64` method to insert copies of the target workbook's worksheets into itself. The other workbook's file is passed as a base64-encoded string, just like the `Excel.createWorkbook` call. +The previous example shows a new workbook being created from an existing workbook. You can also copy some or all of an existing workbook into the one currently associated with your add-in. A [Workbook](/javascript/api/excel/excel.workbook) has the `insertWorksheetsFromBase64` method to insert copies of the target workbook's worksheets into itself. The other workbook's file is passed as a Base64-encoded string, just like the `Excel.createWorkbook` call. ```TypeScript insertWorksheetsFromBase64(base64File: string, options?: Excel.InsertWorksheetOptions): OfficeExtension.ClientResult; @@ -78,7 +78,7 @@ insertWorksheetsFromBase64(base64File: string, options?: Excel.InsertWorksheetOp > [!IMPORTANT] > The `insertWorksheetsFromBase64` method is supported for Excel on the web, on Windows, and on Mac. It's not supported for iOS. Additionally, in Excel on the web, this method doesn't support source worksheets with PivotTable, Chart, Comment, or Slicer elements. If those objects are present, the `insertWorksheetsFromBase64` method returns the `UnsupportedFeature` error in Excel on the web. -The following code sample shows how to insert worksheets from another workbook into the current workbook. This code sample first processes a workbook file with a [`FileReader`](https://developer.mozilla.org/docs/Web/API/FileReader) object and extracts a base64-encoded string, and then it inserts this base64-encoded string into the current workbook. The new worksheets are inserted after the worksheet named **Sheet1**. Note that `[]` is passed as the parameter for the [InsertWorksheetOptions.sheetNamesToInsert](/javascript/api/excel/excel.insertworksheetoptions#excel-excel-insertworksheetoptions-sheetnamestoinsert-member) property. This means that all the worksheets from the target workbook are inserted into the current workbook. +The following code sample shows how to insert worksheets from another workbook into the current workbook. This code sample first processes a workbook file with a [`FileReader`](https://developer.mozilla.org/docs/Web/API/FileReader) object and extracts a Base64-encoded string, and then it inserts this Base64-encoded string into the current workbook. The new worksheets are inserted after the worksheet named **Sheet1**. Note that `[]` is passed as the parameter for the [InsertWorksheetOptions.sheetNamesToInsert](/javascript/api/excel/excel.insertworksheetoptions#excel-excel-insertworksheetoptions-sheetnamestoinsert-member) property. This means that all the worksheets from the target workbook are inserted into the current workbook. ```js // Retrieve the external workbook file and set up a `FileReader` object. @@ -87,7 +87,7 @@ let reader = new FileReader(); reader.onload = (event) => { Excel.run((context) => { - // Remove the metadata before the base64-encoded string. + // Remove the metadata before the Base64-encoded string. let startIndex = reader.result.toString().indexOf("base64,"); let externalWorkbook = reader.result.toString().substr(startIndex + 7); @@ -107,7 +107,7 @@ reader.onload = (event) => { }); }; -// Read the file as a data URL so we can parse the base64-encoded string. +// Read the file as a data URL so we can parse the Base64-encoded string. reader.readAsDataURL(myFile.files[0]); ``` diff --git a/docs/excel/excel-add-ins-worksheet-display.md b/docs/excel/excel-add-ins-worksheet-display.md new file mode 100644 index 0000000000..784be6628c --- /dev/null +++ b/docs/excel/excel-add-ins-worksheet-display.md @@ -0,0 +1,114 @@ +--- +title: Adjust worksheet display settings +description: How to adjust some worksheet display settings to make reports easier to read. +ms.date: 04/03/2025 +ms.localizationpriority: medium +--- + +# Adjust worksheet display settings + +Excel is often used for reporting scenarios where you want to share worksheet data with others. Your Office Add-in can reduce visual clutter and help focus attention by controlling the appearance of the worksheet. The Office JavaScript API supports changing several visual aspects of the worksheet. + +## Page layout and print settings + +Add-ins have access to page layout settings at a worksheet level. These control how the sheet is printed. A `Worksheet` object has three layout-related properties: `horizontalPageBreaks`, `verticalPageBreaks`, and `pageLayout`. + +`Worksheet.horizontalPageBreaks` and `Worksheet.verticalPageBreaks` are [PageBreakCollection](/javascript/api/excel/excel.pagebreakcollection) objects. These are collections of [PageBreak](/javascript/api/excel/excel.pagebreak) objects, which specify ranges where manual page breaks are inserted. The following code sample adds a horizontal page break before row **21**. + +```js +await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + sheet.horizontalPageBreaks.add("A21:E21"); // The page break precedes this range. + await context.sync(); +}); +``` + +`Worksheet.pageLayout` is a [PageLayout](/javascript/api/excel/excel.pagelayout) object. This object contains layout and print settings that aren't dependent on any printer-specific implementation. These settings include margins, orientation, page numbering, title rows, and print area. +The following code sample centers the page (both vertically and horizontally), sets a title row to be printed at the top of every page, and sets the printed area to a subsection of the worksheet. + +```js +await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Center the page in both directions. + sheet.pageLayout.centerHorizontally = true; + sheet.pageLayout.centerVertically = true; + + // Set the first row as the title row for every page. + sheet.pageLayout.setPrintTitleRows("$1:$1"); + + // Limit the area to be printed to the range "A1:D100". + sheet.pageLayout.setPrintArea("A1:D100"); + + await context.sync(); +}); +``` + +## Turn data type icons on or off (preview) + +> [!NOTE] +> [!INCLUDE [Information about using preview APIs](../includes/using-excel-preview-apis.md)] + +Data types can display an icon next to the value in the cell. When you have large tables with many data types, the icons may add visual clutter. + +:::image type="content" source="../images/data-types-icon-table.png" alt-text="An Excel table with three data types showing the same icon next to each data type."::: + +Use the [Worksheet.showDataTypeIcons](/javascript/api/excel/excel.worksheet#excel-excel-worksheet-showdatatypeicons-member) property to toggle data type icons on or off. For more information about data types and their icons, see [Overview of data types in Excel add-ins](excel-data-types-overview.md). The `showDataTypeIcons` property performs the same action as the user toggling data type icons by using the **View** > **Data Type Icons** checkbox. The visibility settings for data type icons are saved with the worksheet and are seen by anyone co-authoring at the time they are changed. + +The following code sample shows how to turn off data type icons on a worksheet. + +```js +await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + sheet.showDataTypeIcons = false; + await context.sync(); +}); +``` + +> [!NOTE] +> If a linked data type displays a **?** icon, this can’t be toggled on or off. Excel needs the user to disambiguate the cell value to find the correct data type. For more information, see [Excel data types: Stocks and geography](https://support.microsoft.com/office/61a33056-9935-484f-8ac8-f1a89e210877). + +## Show or hide the worksheet gridlines (preview) + +> [!NOTE] +> [!INCLUDE [Information about using preview APIs](../includes/using-excel-preview-apis.md)] + +Gridlines are the faint lines that appear between cells on a worksheet. These can be distracting if you use shapes, icons, or have specific line and border formats on data. + +:::image type="content" source="../images/excel-gridlines.png" alt-text="An infographic where the gridlines are distracting."::: + +Turn the gridlines on or off with the [Worksheet.showGridlines](/javascript/api/excel/excel.worksheet#excel-excel-worksheet-showgridlines-member) property. This is the same as using the **View** > **Gridlines** checkbox in the Excel UI. The visibility settings for gridlines are saved with the worksheet and are seen by anyone co-authoring at the time they are changed. + +The following example shows how to turn off gridlines on a worksheet. + +```js +await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + sheet.showGridlines = false; + await context.sync(); +}); +``` + +## Toggle headings (preview) + +> [!NOTE] +> [!INCLUDE [Information about using preview APIs](../includes/using-excel-preview-apis.md)] + +Headings are the Excel row numbers that appear on the left side of the worksheet (1, 2, 3) and the column letters that appear at the top of the worksheet (A, B, C). The user may not want these in their report. + +:::image type="content" source="../images/excel-heading-label.png" alt-text="A spreadsheet section highlighting the column heading A and the row heading 2."::: + +Turn the headings on or off with the [Worksheet.showHeadings](/javascript/api/excel/excel.worksheet#excel-excel-worksheet-showheadings-member) property. This is the same as using the **View** > **Headings** checkbox in the Excel UI. The following example shows how to turn headings off on a worksheet. + +```js +await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + sheet.showHeadings = false; + await context.sync(); +}); +``` + +## See also + +- [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) +- [Work with worksheets using the Excel JavaScript API](excel-add-ins-worksheets.md) diff --git a/docs/excel/excel-add-ins-worksheets.md b/docs/excel/excel-add-ins-worksheets.md index 0e2c6b6449..97869a0c4d 100644 --- a/docs/excel/excel-add-ins-worksheets.md +++ b/docs/excel/excel-add-ins-worksheets.md @@ -1,7 +1,7 @@ --- title: Work with worksheets using the Excel JavaScript API description: Code samples that show how to perform common tasks with worksheets using the Excel JavaScript API. -ms.date: 04/25/2022 +ms.date: 04/03/2025 ms.localizationpriority: medium --- @@ -526,42 +526,6 @@ async function checkProtection(event) { } ``` -## Page layout and print settings - -Add-ins have access to page layout settings at a worksheet level. These control how the sheet is printed. A `Worksheet` object has three layout-related properties: `horizontalPageBreaks`, `verticalPageBreaks`, `pageLayout`. - -`Worksheet.horizontalPageBreaks` and `Worksheet.verticalPageBreaks` are [PageBreakCollections](/javascript/api/excel/excel.pagebreakcollection). These are collections of [PageBreaks](/javascript/api/excel/excel.pagebreak), which specify ranges where manual page breaks are inserted. The following code sample adds a horizontal page break above row **21**. - -```js -await Excel.run(async (context) => { - let sheet = context.workbook.worksheets.getActiveWorksheet(); - sheet.horizontalPageBreaks.add("A21:E21"); // The page break is added above this range. - await context.sync(); -}); -``` - -`Worksheet.pageLayout` is a [PageLayout](/javascript/api/excel/excel.pagelayout) object. This object contains layout and print settings that are not dependent any printer-specific implementation. These settings include margins, orientation, page numbering, title rows, and print area. - -The following code sample centers the page (both vertically and horizontally), sets a title row that will be printed at the top of every page, and sets the printed area to a subsection of the worksheet. - -```js -await Excel.run(async (context) => { - let sheet = context.workbook.worksheets.getActiveWorksheet(); - - // Center the page in both directions. - sheet.pageLayout.centerHorizontally = true; - sheet.pageLayout.centerVertically = true; - - // Set the first row as the title row for every page. - sheet.pageLayout.setPrintTitleRows("$1:$1"); - - // Limit the area to be printed to the range "A1:D100". - sheet.pageLayout.setPrintArea("A1:D100"); - - await context.sync(); -}); -``` - ## See also - [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) diff --git a/docs/excel/excel-data-types-add-properties-to-basic-cell-values.md b/docs/excel/excel-data-types-add-properties-to-basic-cell-values.md new file mode 100644 index 0000000000..a44ec9da4b --- /dev/null +++ b/docs/excel/excel-data-types-add-properties-to-basic-cell-values.md @@ -0,0 +1,219 @@ +--- +title: Add properties to basic cell values +description: Add properties to basic cell values. +ms.topic: how-to #Required; leave this attribute/value as-is +ms.date: 05/12/2025 +ms.localizationpriority: medium +--- + +# Add properties to basic cell values + +Add properties to basic cell values in Excel to associate additional information with the values. Similar to [entity values](excel-data-types-linked-entity-cell-values.md), you can add properties to the **string**, **double**, and **Boolean** basic types. Each property is a key/value pair. The following example shows the number 14.67 (a double) that represents a bill with added fields named **Drinks**, **Food**, **Tax**, and **Tip**. + +:::image type="content" source="../images/data-type-basic-fields.png" alt-text="Screenshot of the drinks, food, tax, and tip fields shown for the selected cell value."::: + +If the user chooses to show the data type card, they'll see the values for the fields. + +:::image type="content" source="../images/data-type-basic-data-type-card.png" alt-text="Data type card showing values for drinks, food, tax, and tip properties."::: + +Cell value properties can also be used in formulas. + +:::image type="content" source="../images/data-type-basic-dot-syntax.png" alt-text="Show user typing 'a1.' and Excel showing a menu with drinks, food, tax, and tip options."::: + +## Create a cell value with properties + +To create a cell value and add properties to it, use `Range.valuesAsJson` to assign properties. The following code sample shows how to create a new number in cell **A1**. It adds the **Food**, **Drinks**, and additional properties describing a bill in a restaurant. It assigns a JSON description of the properties to `valuesAsJson`. + +```typescript +async function createNumberProperties() { + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("A1"); + range.valuesAsJson = [ + [ + { + type: Excel.CellValueType.double, + basicType: Excel.RangeValueType.double, + basicValue: 14.67, + properties: { + Food: { + type: Excel.CellValueType.string, + basicType: Excel.RangeValueType.string, + basicValue: "Sandwich and fries" + }, + Drinks: { + type: Excel.CellValueType.string, + basicType: Excel.RangeValueType.string, + basicValue: "Soda" + }, + Tax: { + type: Excel.CellValueType.double, + basicType: Excel.RangeValueType.double, + basicValue: 5.5 + }, + Tip: { + type: Excel.CellValueType.double, + basicType: Excel.RangeValueType.double, + basicValue: 21 + } + } + } + ] + ]; + await context.sync(); + }); +} +``` + +> [!NOTE] +> Some cell values change based on a user's locale. The `valuesAsJsonLocal` property offers localization support and is available on all the same objects as `valuesAsJson`. + +## Add properties to an existing value + +To add properties to an existing value, first get the value from the cell using `valuesAsJson`, then add a properties JSON object to it. The following example shows how to get the number value from cell **A1** and assign a property named **Precision** to it. Note that you should check the type of the value to ensure it's a **string**, **double**, or **Boolean** basic type. + +```typescript +async function addPropertyToNumber() { + await Excel.run(async (context) => { + let sheet = context.workbook.worksheets.getActiveWorksheet(); + let range = sheet.getRange("A1"); + range.load("valuesAsJson"); + await context.sync(); + let cellValue = range.valuesAsJson[0][0] as any; + + // Only apply this property to a double. + if (cellValue.basicType === "Double") { + cellValue.properties = { + Precision: { + type: Excel.CellValueType.double, + basicValue: 4 + } + }; + range.valuesAsJson = [[cellValue]]; + await context.sync(); + } + }); +} +``` + +## Differences from entity values + +Adding properties to **string**, **Boolean**, and **double** basic types is similar to adding properties to entity values. However there are differences. + +- Basic types have a non-error fallback so that calculations can operate on them. For example, consider the formula **=SUM(A1:A3)** where **A1** is **1**, **A2** is **2**, and **A3** is **3**. **A1** is a double with properties, while **A2** and **A3** don't have properties. The sum returns the correct result of **6**. The formula wouldn't work if **A1** was an entity value. +- When the value of a basic type is used in a calculation, the properties are excluded in the result. In the previous example of **=SUM(A1:A3)** where A1 is a double with properties, the result of **6** does not have any properties. +- If no icon is specified for a basic type, the cell doesn't show any icon. But if an entity value doesn't specify an icon, it shows a default icon in the cell value. + +## Formatted number values + +You can apply number formatting to values of type `CellValueType.double`. Use the `numberFormat` property in the JSON schema to specify a number format. The following code sample shows the complete schema of a number value formatted as currency. The formatted number value in the code sample displays as **$24.00** in the Excel UI. + +```typescript +// This is an example of the complete JSON of a formatted number value with a property. +// In this case, the number is formatted as currency. +async function createCurrencyValue() { + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("A1"); + range.valuesAsJson = [ + [ + { + type: Excel.CellValueType.double, + basicType: Excel.RangeValueType.double, + basicValue: 24, + numberFormat: "$0.00", + properties: { + Name: { + type: Excel.CellValueType.string, + basicValue: "dollar" + } + } + } + ] + ]; + await context.sync(); + }); +} +``` + +The number formatting is considered the default format. If the user, or other code, applies formatting to a cell containing a formatted number, the applied format overrides the number’s format. + +## Card layout + +Cell values with properties have a default data type card that the user can view. You can provide a custom card layout to use instead of the default card layout to improve the user experience when viewing properties. To do this, add the **layouts** property to the JSON description. + +For more information, see [Use cards with cell value data types](excel-data-types-entity-card.md). + +## Nested data types + +You can nest data types in a cell value, such as additional entity values, as well as **strings**, **doubles**, and **Booleans**. The following code sample shows how to create a cell value that represents the charge status on a computer battery. It contains a nested entity value that describes the computer properties for power consumption and charging status. The computer entity value also contains a nested string value that describes the computer’s power plan. + +```typescript +async function createNumberWithNestedEntity() { + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("A1"); + range.valuesAsJson = [ + [ + { + type: Excel.CellValueType.double, + basicType: Excel.RangeValueType.double, + layouts: { + compact: { + icon: "Battery10" + } + }, + basicValue: 0.7, + numberFormat: "00%", + properties: { + Computer: { + type: Excel.CellValueType.entity, + text: "Laptop", + properties: { + "Power Consumption": { + type: Excel.CellValueType.double, + basicType: Excel.RangeValueType.double, + basicValue: 0.25, + numberFormat: "00%", + layouts: { + compact: { + icon: "Power" + } + }, + properties: { + plan: { + type: Excel.CellValueType.string, + basicType: Excel.RangeValueType.string, + basicValue: "Balanced" + } + } + }, + Charging: { + type: Excel.CellValueType.boolean, + basicType: Excel.RangeValueType.boolean, + basicValue: true + } + } + } + } + } + ] + ]; + await context.sync(); + }); +} +``` + +The following image shows the number value and the data type card for the nested laptop entity. + +:::image type="content" source="../images/data-type-basic-nested-entities.png" alt-text="Cell value in Excel showing battery charge at 70%, and the data type card showing the nested laptop entity with charging and power consumption property values."::: + +## Compatibility + +On previous versions of Excel that don't support the data types feature, users see a warning of **Unavailable Data Type**. The value still displays in the cell and functions as expected with formulas and other Excel features. If the value is a formatted number, calculations use the `basicValue` in place of the formatted number. + +On Excel versions older than Office 2016, the value is shown in the cell with no error and is indistinguishable from a basic value. + +## See also + +- [Excel JavaScript API data types core concepts](excel-data-types-concepts.md) diff --git a/docs/excel/excel-data-types-concepts.md b/docs/excel/excel-data-types-concepts.md index 28fd323026..2d875908b7 100644 --- a/docs/excel/excel-data-types-concepts.md +++ b/docs/excel/excel-data-types-concepts.md @@ -1,7 +1,7 @@ --- title: Excel JavaScript API data types core concepts description: Learn the core concepts for using Excel data types in your Office Add-in. -ms.date: 10/14/2022 +ms.date: 04/14/2025 ms.topic: overview ms.custom: scenarios:getting-started ms.localizationpriority: high @@ -37,8 +37,10 @@ The `valuesAsJson` property returns a [CellValue](/javascript/api/excel/excel.ce - [EmptyCellValue](/javascript/api/excel/excel.emptycellvalue) - [EntityCellValue](/javascript/api/excel/excel.entitycellvalue) - [ErrorCellValue](/javascript/api/excel/excel.errorcellvalue) -- [FormattedNumberCellValue](/javascript/api/excel/excel.formattednumbercellvalue) +- [ExternalCodeServiceObjectCellValue](/javascript/api/excel/excel.externalcodeserviceobjectcellvalue) +- [FunctionCellValue](/javascript/api/excel/excel.functioncellvalue) - [LinkedEntityCellValue](/javascript/api/excel/excel.linkedentitycellvalue) +- [LocalImageCellValue](/javascript/api/excel/excel.localimagecellvalue) - [ReferenceCellValue](/javascript/api/excel/excel.referencecellvalue) - [StringCellValue](/javascript/api/excel/excel.stringcellvalue) - [ValueTypeNotAvailableCellValue](/javascript/api/excel/excel.valuetypenotavailablecellvalue) @@ -58,23 +60,33 @@ The following sections show JSON code samples for the formatted number value, en ## Formatted number values -The [FormattedNumberCellValue](/javascript/api/excel/excel.formattednumbercellvalue) object enables Excel add-ins to define a `numberFormat` property for a value. Once assigned, this number format travels through calculations with the value and can be returned by functions. +The [DoubleCellValue](/javascript/api/excel/excel.doublecellvalue) object enables Excel add-ins to define a `numberFormat` property for a value. Once assigned, this number format travels through calculations with the value and can be returned by functions. The following JSON code sample shows the complete schema of a formatted number value. The `myDate` formatted number value in the code sample displays as **1/16/1990** in the Excel UI. If the minimum compatibility requirements for the data types feature aren't met, calculations use the `basicValue` in place of the formatted number. ```TypeScript // This is an example of the complete JSON of a formatted number value. // In this case, the number is formatted as a date. -const myDate: Excel.FormattedNumberCellValue = { - type: Excel.CellValueType.formattedNumber, +const myDate: Excel.DoubleCellValue = { + type: Excel.CellValueType.double, basicValue: 32889.0, basicType: Excel.RangeValueType.double, // A read-only property. Used as a fallback in incompatible scenarios. numberFormat: "m/d/yyyy" }; ``` +The number formatting is considered the default format. If the user, or other code, applies formatting to a cell containing a formatted number, the applied format overrides the number’s format. + Begin experimenting with formatted number values by opening [Script Lab](../overview/explore-with-script-lab.md) and checking out the [Data types: Formatted numbers](https://github.com/OfficeDev/office-js-snippets/blob/prod/samples/excel/20-data-types/data-types-formatted-number.yaml) snippet in our **Samples** library. +## Basic cell values + +Add properties to basic cell values in Excel to associate additional information with the values. Similar to entity values, you can add properties to the **string**, **double**, and **Boolean** basic types. Each property is a key/value pair. The following example shows the number 104.67 (a double) that represents a bill with added fields named **Drinks**, **Food**, **Tax**, and **Tip**. + +:::image type="content" source="../images/data-type-basic-fields.png" alt-text="Screenshot of the drinks, food, tax, and tip fields shown for the selected cell value."::: + +For more information, see [Add properties to basic cell values](excel-data-types-add-properties-to-basic-cell-values.md). + ## Entity values An entity value is a container for data types, similar to an object in object-oriented programming. Entities also support arrays as properties of an entity value. The [EntityCellValue](/javascript/api/excel/excel.entitycellvalue) object allows add-ins to define properties such as `type`, `text`, and `properties`. The `properties` property enables the entity value to define and contain additional data types. @@ -102,13 +114,18 @@ const myEntity: Excel.EntityCellValue = { }; ``` -Entity values also offer a `layouts` property that creates a card for the entity. The card displays as a modal window in the Excel UI and can display additional information contained within the entity value, beyond what's visible in the cell. To learn more, see [Use cards with entity value data types](excel-data-types-entity-card.md). - To explore entity data types, start by going to [Script Lab](../overview/explore-with-script-lab.md) in Excel and opening the [Data types: Create entity cards from data in a table](https://github.com/OfficeDev/office-js-snippets/blob/prod/samples/excel/20-data-types/data-types-entity-values.yaml) snippet in our **Samples** library. The [Data types: Entity values with references](https://github.com/OfficeDev/office-js-snippets/blob/prod/samples/excel/20-data-types/data-types-references.yaml) and [Data types: Entity value attribution properties](https://github.com/OfficeDev/office-js-snippets/blob/prod/samples/excel/20-data-types/data-types-entity-attribution.yaml) snippets offer a deeper look at entity features. -### Linked entities +### Linked entity cell values + +Linked entity cell values, or [LinkedEntityCellValue](/javascript/api/excel/excel.linkedentitycellvalue) objects, are integrated data types from external data sources and can display the data as an entity card. They enable you to scale your data types to represent large data sets without downloading all the data into the workbook. The [Stocks and Geography data domains](https://support.microsoft.com/office/excel-data-types-stocks-and-geography-61a33056-9935-484f-8ac8-f1a89e210877) available via the Excel UI provide linked entity cell values. + +Linked entity cell values are linked to an external data source. They provide the following advantages over regular entity values: + +- Linked entity cell values can nest, and nested linked entity cell values aren't retrieved until referenced, either by the user or by the worksheet. This helps reduce file size and improve workbook performance. +- Excel uses a cache to allow different cells to reference the same linked entity cell value seamlessly. This also improves workbook performance. -Linked entity values, or [LinkedEntityCellValue](/javascript/api/excel/excel.linkedentitycellvalue) objects, are a type of entity value. These objects integrate data provided by an external service and can display this data as an [entity card](excel-data-types-entity-card.md), like regular entity values. The [Stocks and Geography data types](https://support.microsoft.com/office/excel-data-types-stocks-and-geography-61a33056-9935-484f-8ac8-f1a89e210877) available via the Excel UI are linked entity values. +For more information, see [Create linked entity cell values](excel-data-types-linked-entity-cell-values.md). ## Web image values @@ -164,6 +181,8 @@ Use the [Create and explore data types in Excel](https://github.com/OfficeDev/Of ## See also - [Overview of data types in Excel add-ins](excel-data-types-overview.md) +- [Create linked entity cell values](excel-data-types-linked-entity-cell-values.md) +- [Add properties to basic cell values](excel-data-types-add-properties-to-basic-cell-values.md) - [Use cards with entity value data types](excel-data-types-entity-card.md) - [Create and explore data types in Excel](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-data-types-explorer) - [Custom functions and data types](custom-functions-data-types-concepts.md) diff --git a/docs/excel/excel-data-types-entity-card.md b/docs/excel/excel-data-types-entity-card.md index 567f51cff0..cc0ba2b153 100644 --- a/docs/excel/excel-data-types-entity-card.md +++ b/docs/excel/excel-data-types-entity-card.md @@ -1,18 +1,22 @@ --- -title: Excel JavaScript API data types entity value card -description: Learn how to use entity value cards with data types in your Excel add-in. -ms.date: 01/27/2023 +title: Use cards for cell values with the Excel JavaScript API +description: Learn how to create cards for cell value data types in your Excel add-in. +ms.date: 05/12/2025 ms.localizationpriority: medium --- -# Use cards with entity value data types +# Use cards with cell value data types -This article describes how to use the [Excel JavaScript API](../reference/overview/excel-add-ins-reference-overview.md) to create card modal windows in the Excel UI with entity value data types. These cards can display additional information contained within an entity value, beyond what's already visible in a cell, such as related images, product category information, and data attributions. +You can specify card modal windows in the Excel UI for various cell value data types. Cards can display additional information beyond what's already visible in a cell, such as related images, product category information, and data attributions. > [!NOTE] -> This article expands on information described in the [Excel data types core concepts](excel-data-types-concepts.md) article. We recommend reading that article before learning about entity cards. +> This article expands on information described in the [Excel data types core concepts](excel-data-types-concepts.md) article. We recommend reading that article before learning about cards for cell values. -An entity value, or [EntityCellValue](/javascript/api/excel/excel.entitycellvalue), is a container for data types and similar to an object in object-oriented programming. This article shows how to use entity value card properties, layout options, and data attribution functionality to create entity values that display as cards. +Cards are supported for the following cell value types. + +- [EntityCellValue](/javascript/api/excel/excel.entitycellvalue) +- [LinkedEntityCellValue](/javascript/api/excel/excel.linkedentitycellvalue) +- **string**, **double**, and **Boolean** basic types The following screenshot shows an example of an open entity value card, in this case for the **Chef Anton's Gumbo Mix** product from a list of grocery store products. @@ -20,7 +24,7 @@ The following screenshot shows an example of an open entity value card, in this ## Card properties -The entity value [`properties`](/javascript/api/excel/excel.entitycellvalue#excel-excel-entitycellvalue-properties-member) property allows you to set customized information about your data types. The `properties` key accepts nested data types. Each nested property, or data type, must have a `type` and `basicValue` setting. +Use [`properties`](/javascript/api/excel/excel.entitycellvalue#excel-excel-entitycellvalue-properties-member) to specify all custom information about your data types. The `properties` key supports nested data types. Each nested property, or data type, must have a `type` and `basicValue` setting. > [!IMPORTANT] > The nested `properties` data types are used in combination with the [Card layout](#card-layout) values described in the subsequent article section. After defining a nested data type in `properties`, it must be assigned in the `layouts` property to display on the card. @@ -52,7 +56,7 @@ const entity: Excel.EntityCellValue = { basicValue: product.quantityPerUnit || "" }, "Unit Price": { - type: Excel.CellValueType.formattedNumber, + type: Excel.CellValueType.double, basicValue: product.unitPrice, numberFormat: "$* #,##0.00" }, @@ -71,39 +75,16 @@ The following screenshot shows an entity value card that uses the preceding code :::image type="content" source="../images/excel-data-types-entity-card-properties-gumbo.png" alt-text="An entity value data type with the card layout window displayed. The card shows the product name, product ID, quantity per unit, and unit price information."::: -### Property metadata - -Entity properties have an optional `propertyMetadata` field that uses the [`CellValuePropertyMetadata`](/javascript/api/excel/excel.cellvaluepropertymetadata) object and offers the properties `attribution`, `excludeFrom`, and `sublabel`. The following code snippet shows how to add a `sublabel` to the `"Unit Price"` property from the preceding code snippet. In this case, the sublabel identifies the currency type. - -> [!NOTE] -> The `propertyMetadata` field is only available on data types that are nested within entity properties. - -```TypeScript -// This code snippet is an excerpt from the `properties` field of the -// preceding `EntityCellValue` snippet. "Unit Price" is a property of -// an entity value. - "Unit Price": { - type: Excel.CellValueType.formattedNumber, - basicValue: product.unitPrice, - numberFormat: "$* #,##0.00", - propertyMetadata: { - sublabel: "USD" - } - }, -``` - -The following screenshot shows an entity value card that uses the preceding code snippet, displaying the property metadata `sublabel` of **USD** next to the **Unit Price** property. - -:::image type="content" source="../images/excel-data-types-entity-card-property-metadata.png" alt-text="The sublabel USD next to the Unit Price."::: - ## Card layout -The entity value [`layouts`](/javascript/api/excel/excel.entitycellvalue#excel-excel-entitycellvalue-layouts-member) property defines the appearance of the entity. Use `layouts` to specify attributes such as an entity icon, card title, image for a card, and the number of sections to display. +Cell values have a default data type card that the user can view. Specify a custom card layout to improve the user experience when viewing properties. The [`layouts`](/javascript/api/excel/excel.entitycellvalue#excel-excel-entitycellvalue-layouts-member) property defines the structure and appearance of the card. Use `layouts` to specify attributes such as an icon, card title, image for a card, and the number of sections to display. > [!IMPORTANT] > The nested `layouts` values are used in combination with the [Card properties](#card-properties) data types described in the preceding article section. A nested data type must be defined in `properties` before it can be assigned in `layouts` to display on the card. -The `layouts` property contains two direct subproperties, `compact` and `card`. The `card` property specifies the appearance of a card when the entity card is open. The `compact` property only defines the icon for an entity, and this icon only displays when the card is in its compact, or unopened state. See the [`EntityCompactLayoutIcons`](/javascript/api/excel/excel.entitycompactlayouticons) enum for a full list of available icons. The next code snippet shows how to display the `shoppingBag` icon. +The `layouts` property contains two direct subproperties, `compact` and `card`. The `card` property specifies the appearance of a card when the card is open. The `compact` property is optional and defines the icon for a value. The icon is shown in the cell value if it's provided. It can also be shown in the card if it's referenced as a subproperty. + +See the [`EntityCompactLayoutIcons`](/javascript/api/excel/excel.entitycompactlayouticons) enum for a full list of available icons. The next code snippet shows how to display the `shoppingBag` icon. Within the `card` property, use the [`CardLayoutStandardProperties`](/javascript/api/excel/excel.cardlayoutstandardproperties) object to define the components of the card like `title`, `subTitle`, and `sections`. @@ -111,6 +92,9 @@ The entity value JSON in the next code snippet shows a `card` layout with nested Within each card section you can specify elements like `layout`, `title`, and `properties`. The `layout` key uses the [`CardLayoutListSection`](/javascript/api/excel/excel.cardlayoutlistsection) object and accepts the value `"List"`. The `properties` key accepts an array of strings. Note that the `properties` values, such as `"Product ID"`, have corresponding data types in the preceding [Card properties](#card-properties) article section. Sections can also be collapsible and can be defined with boolean values as collapsed or not collapsed when the entity card is opened in the Excel UI. +> [!TIP] +> The `layout` key also has additional display options available beyond `"List"` within card sections. Use `"Table"` for [Excel.CardLayoutTableSection](/javascript/api/excel/excel.cardlayouttablesection) and `"TwoColumn"` for [Excel.CardLayoutTwoColumnSection](/javascript/api/excel/excel.cardlayouttwocolumnsection). Note that the `"TwoColumn"` layout is only available in preview. + > [!NOTE] > To experiment with this code snippet in a complete sample, open [Script Lab](../overview/explore-with-script-lab.md) in Excel and select [Data types: Create entity cards from data in a table](https://github.com/OfficeDev/office-js-snippets/blob/prod/samples/excel/20-data-types/data-types-entity-values.yaml) in our **Samples** library. @@ -166,38 +150,113 @@ The following screenshot shows an entity value card that uses the preceding code > > There is a known issue with nested icons in Excel on Mac. In that environment, nested icons will always display as the `generic` icon, regardless of which icon is selected with the `EntityCompactLayoutIcons` enum. -## Card data attribution - -Entity value cards can display a data attribution to give credit to the provider of the information in the entity card. The entity value [`provider`](/javascript/api/excel/excel.entitycellvalue#excel-excel-entitycellvalue-provider-member) property uses the [`CellValueProviderAttributes`](/javascript/api/excel/excel.cellvalueproviderattributes) object, which defines the `description`, `logoSourceAddress`, and `logoTargetAddress` values. - -The data provider property displays an image in the lower left corner of the entity card. It uses the `logoSourceAddress` to specify a source URL for the image. The `logoTargetAddress` value defines the URL destination if the logo image is selected. The `description` value displays as a tooltip when hovering over the logo. The `description` value also displays as a plain text fallback if the `logoSourceAddress` is not defined or if the source address for the image is broken. +### Property metadata -The JSON in the following code snippet shows an entity value that uses the `provider` property to specify a data provider attribution for the entity. +Entity properties have an optional `propertyMetadata` field that uses the [`CellValuePropertyMetadata`](/javascript/api/excel/excel.cellvaluepropertymetadata) object and offers the properties `attribution`, `excludeFrom`, and `sublabel`. The following code snippet shows how to add a `sublabel` to the `"Unit Price"` property from the preceding code snippet. In this case, the sublabel identifies the currency type. > [!NOTE] -> To experiment with this code snippet in a complete sample, open [Script Lab](../overview/explore-with-script-lab.md) in Excel and select [Data types: Entity value attribution properties](https://github.com/OfficeDev/office-js-snippets/blob/prod/samples/excel/20-data-types/data-types-entity-attribution.yaml) in our **Samples** library. +> The `propertyMetadata` field is only available on data types that are nested within entity properties. ```TypeScript -const entity: Excel.EntityCellValue = { - type: Excel.CellValueType.entity, - text: productName, - properties: { - // Enter property settings here. - }, - layouts: { - // Enter layout settings here. +// This code snippet is an excerpt from the `properties` field of the +// preceding `EntityCellValue` snippet. "Unit Price" is a property of +// an entity value. + "Unit Price": { + type: Excel.CellValueType.double, + basicValue: product.unitPrice, + numberFormat: "$* #,##0.00", + propertyMetadata: { + sublabel: "USD" + } }, - provider: { - description: product.providerName, // Name of the data provider. Displays as a tooltip when hovering over the logo. Also displays as a fallback if the source address for the image is broken. - logoSourceAddress: product.sourceAddress, // Source URL of the logo to display. - logoTargetAddress: product.targetAddress // Destination URL that the logo navigates to when selected. - } -}; ``` -The following screenshot shows an entity value card that uses the preceding code snippet. The screenshot shows the data provider attribution in the lower left corner. In this instance, the data provider is Microsoft and the Microsoft logo is displayed. +## Attribution + +Add attribution for information that comes from third parties to indicate the source and any license information. Use [Excel.CellValueAttributionAttributes](/javascript/api/excel/excel.cellvalueattributionattributes) to add attribution to a cell value. The following code example shows how to add attribution for usage of information about the planet Mars from Wikipedia. + +```typescript +async function createPlanet() { + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("A1"); + const attributionObject: Excel.CellValueAttributionAttributes = { + licenseAddress: "https://en.wikipedia.org/wiki/Wikipedia:Wikipedia_is_free_content", + licenseText: "Free usage information", + sourceAddress: "https://en.wikipedia.org/wiki/Mars", + sourceText: "Wikipedia" + }; + + range.valuesAsJson = [ + [ + { + type: Excel.CellValueType.double, + basicType: Excel.RangeValueType.double, + basicValue: 6779, // kilometers (radius) + properties: { + Name: { + type: Excel.CellValueType.string, + basicType: Excel.RangeValueType.string, + basicValue: "Mars", + propertyMetadata: { + sublabel: "Planetary Body", + attribution: [attributionObject] + } + } + } + } + ] + ]; + await context.sync(); + }); +} +``` + +The following image shows how the attribution is displayed in the data type card for the user. + +:::image type="content" source="../images/data-type-basic-card-attribution.png" alt-text="Data type card showing attribution for Wikipedia."::: + +## Provider information + +You can add information about your add-in, or service, that is the source for the information in the data type card. Use [Excel.CellValueProviderAttributes](/javascript/api/excel/excel.cellvalueproviderattributes) to add your provider information. The following code sample shows how to add provider information for Contoso generic search as the source of search data for the cell value. + +```typescript +async function createSearchEntry() { + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("A1"); + + range.valuesAsJson = [ + [ + { + type: Excel.CellValueType.string, + basicType: Excel.RangeValueType.string, + basicValue: "cell function - Microsoft support", + properties: { + "Search Keywords": { + type: Excel.CellValueType.string, + basicType: Excel.RangeValueType.string, + basicValue: "Cell Values" + } + }, + provider: { + description: "Contoso generic search", + // Image credit: Ignacio javier igjav, Public domain, via Wikimedia Commons + logoSourceAddress: "https://upload.wikimedia.org/wikipedia/commons/f/f9/Lupa.png", + logoTargetAddress: "https://contoso.com/" + } + } + ] + ]; + + await context.sync(); + }); +} +``` + +The following image shows how the provider information appears as the logo in the data type card for the user. -:::image type="content" source="../images/excel-data-types-entity-card-attribution.png" alt-text="An entity value data type with the card layout window displayed. The card shows the data provider attribution in the lower left corner."::: +:::image type="content" source="../images/data-type-basic-provider-information.png" alt-text="Data type card showing the search logo for Contoso generic search."::: ## Next steps @@ -208,4 +267,4 @@ Try out the [Create and explore data types in Excel](https://github.com/OfficeDe - [Overview of data types in Excel add-ins](excel-data-types-overview.md) - [Excel data types core concepts](excel-data-types-concepts.md) - [Create and explore data types in Excel](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-data-types-explorer) -- [Excel JavaScript API reference](../reference/overview/excel-add-ins-reference-overview.md) \ No newline at end of file +- [Excel JavaScript API reference](../reference/overview/excel-add-ins-reference-overview.md) diff --git a/docs/excel/excel-data-types-linked-entity-cell-values.md b/docs/excel/excel-data-types-linked-entity-cell-values.md new file mode 100644 index 0000000000..359fbe791e --- /dev/null +++ b/docs/excel/excel-data-types-linked-entity-cell-values.md @@ -0,0 +1,660 @@ +--- +title: Create linked entity cell values +description: Create linked entity cell values to represent large data sets in Excel. +ms.topic: how-to +ms.date: 05/12/2025 +ms.localizationpriority: medium +--- + +# Create linked entity cell values + +Linked entity cell values integrate data types from external data sources and can display the data as an entity card, like [regular entity values](excel-data-types-entity-card.md). They enable you to scale your data types to represent large data sets without downloading all the data into the workbook. The [Stocks and Geography data domains](https://support.microsoft.com/office/excel-data-types-stocks-and-geography-61a33056-9935-484f-8ac8-f1a89e210877) available via the Excel UI provide linked entity cell values. This article explains how to create your own data provider in an Excel add-in to provide custom values for end users. + +Linked entity cell values are linked to an external data source. They provide the following advantages over regular entity values. + +- Linked entity cell values can nest, and nested linked entity cell values are not retrieved until referenced; either by the user, or by the worksheet. This helps reduce file size and improve workbook performance. +- Excel uses a cache to allow different cells to reference the same linked entity cell value seamlessly. This also improves workbook performance. + +This article expands on information described in the following articles. We recommend reading the following articles before learning how to build your own linked entity cell values. + +- [Excel data types: Stocks and geography](https://support.microsoft.com/office/61a33056-9935-484f-8ac8-f1a89e210877) +- [Overview of data types in Excel add-ins](excel-data-types-overview.md) +- [Excel JavaScript API data types entity value card](excel-data-types-entity-card.md) + +## Key concepts + +Linked entity cell values provide the user with data linked from an external data source. The user can view them as an entity value card. + +:::image type="content" source="../images/excel-geography-linked-data-type-seattle.png" alt-text="Screenshot of an entity value data card for the Seattle Geography linked data type in the worksheet."::: + +Like regular entity values, linked entity cell values can be referenced in formulas. + +:::image type="content" source="../images/excel-geography-seattle-dot-syntax.png" alt-text="Screenshot of using dot notation in a formula using =A1. To display fields for Seattle Geography data type."::: + +## Definitions + +The following definitions are fundamental to understanding how to implement your own linked entity cell values. + +- **Linked entity data domain** – A linked entity data domain describes the overall category that an entity belongs to. Some examples are employees, organizations, or cars. +- **Linked entity cell value** – An instance created from a data domain. An example is an employee value for someone named Joe. It can be displayed as an entity value card. +- **Data provider** - The data provider is recognized by Excel as the source of data for one or more registered linked entity data domains. +- **Linked entity load service function** – Every linked entity data domain defines a load service function to act as the source of data for that domain. The linked entity load service function handles requests from Excel to get linked entity cell values for the workbook. You implement it as a TypeScript or JavaScript custom function. + +## How your add-in provides linked entity cell values + +This diagram shows the steps that occur when your add-in is loaded and then inserts a new linked entity cell value into a cell. The following description explains what happens at each step of the process. + +:::image type="content" source="../images/excel-data-types-linked-entity-workflow.png" alt-text="Diagram showing the five steps for an add-in to register data domains and handle requests from Excel to get properties from a linked entity cell value."::: + +1. Excel loads your add-in, and your add-in registers all of the linked entity data domains that it supports. Each registration includes the ID of a linked entity load service function. This ID is called later by Excel to request property values for the linked entity cell value from the linked entity data domain. In this example, one data domain named **Products** is registered. +1. Excel tracks each registered linked entity data domain in a linked entity data domain collection. This enables Excel to call your linked entity load service function when data is needed for a linked entity cell value. +1. Your add-in inserts a new linked entity cell value into the worksheet. In this example a new linked entity cell value is created for the product **Chai**. This would typically occur from the user choosing a button on your add-in that results in creating one or more linked entity cell values. When you create new linked entity cell values, they only contain an initial text string that is displayed in the cell. Excel calls your linked entity load service function to get the remaining property values. Your add-in can also create linked entity cell values from custom functions. +1. Excel calls the linked entity load service function that you registered in step 1. This occurs every time you create a new linked entity cell value, or if a data refresh occurs. Excel calls your linked entity load service function to get all of the property values. +1. The linked entity load service function returns an up-to-date linked entity cell value ([Excel.LinkedEntityCellValue](/javascript/api/excel/excel.linkedentitycellvalue)) for the linked entity ID ([Excel.LinkedEntityId](/javascript/api/excel/excel.linkedentityid)) requested by Excel. Typically, your linked entity load service function queries an external data source to get the values and create the linked entity cell value. In this example the values for **product ID**, **category**, **quantity**, and **price** are returned. + +> [!NOTE] +> If Excel needs multiple linked entity cell values, the linked entity IDs are passed as a batch to your linked entity load service function. The linked entity load service then returns a batch result of all values. + +The following sections provide additional details about the terms defined earlier in this article. + +### Data provider + +Your add-in is the data provider and is recognized by Excel as the source of data for one or more registered data domains. Your add-in exposes one or more data provider functions that return data for linked entity cell values. The [data provider](/javascript/api/excel/excel.linkedentitydatadomaincreateoptions) is identified by a text string such as **Contoso** or the name of your add-in. The name must be unique within your add-in. + +### Linked entity data domains + +The data provider (your add-in) registers one or more data domains. A data domain describes an entity to Excel. For example, a data provider can provide the **products** and **categories** data domains. The domains must be registered with Excel so that it can work with those domains to retrieve and display linked entity cell values and perform calculations. + +A data domain describes to Excel the following attributes: + +- The name of the data provider it is associated with. +- A domain ID to uniquely identify it, such as **products**. +- A display name for the user, such as **Products**. +- A linked entity load service function to call when Excel needs a linked entity cell value. +- A specified refresh mode and interval describing how often it refreshes. + +An example of a linked entity data domain is the **Geography** data domain in Excel that provides linked entity cell values for cities. + +### Linked entity cell value + +A linked entity cell value is an instance created from a data domain. An example is a value for Seattle, from the [Geography data domain](https://support.microsoft.com/office/excel-data-types-stocks-and-geography-61a33056-9935-484f-8ac8-f1a89e210877). It displays an entity value card like regular entity cell values. + +:::image type="content" source="../images/excel-geography-linked-data-type-seattle.png" alt-text="Screenshot of an entity value data card for the Seattle Geography linked data type in the worksheet."::: + +Since linked entity cell values are linked to the data domain, they can be refreshed. Also, nested linked entity cell values are not retrieved unless the user requests them (such as viewing the entity card). And nested entity cell values aren’t saved with the worksheet unless they are referenced from the worksheet (such as a formula). This reduces file size and improves performance. + +### Linked entity load service function + +Each data domain requires a function that Excel can call when it needs linked entity cell values. Your add-in provides the service as a JavaScript or TypeScript function tagged with **@linkedEntityLoadService**. It's recommended to create just one load service function for best performance. Excel sends all requests for linked entity cell values as a batch to the load service function. + +## Create a data provider with data domains + +The following sections of this article show how to write TypeScript code to implement an Excel add-in that is a data provider for **Contoso**. It provides two data domains named **Products** and **Categories**. + +### Register the data domains + +Let’s look at the code to register new domains named **Products** and **Categories**. The data provider name is **Contoso**. When the add-in loads, it first registers the data domains with Excel. + +Use the [Excel.LinkedEntityDataDomainCreateOptions](/javascript/api/excel/excel.linkedentitydatadomaincreateoptions) type to describe the options you want, including which function to use as the linked entity load service. Then add the domain to the [Workbook.linkedEntityDataDomains](/javascript/api/excel/excel.workbook#excel-excel-workbook-linkedentitydatadomains-member) collection. It's recommended to register domains when you [Initialize your Office Add-in](../develop/initialize-add-in.md). +The following code shows how to register the **Products**, **Categories**, and **Suppliers** data domains. + +```typescript +Office.onReady(async () => { + await Excel.run(async (context) => { + const productsDomain: Excel.LinkedEntityDataDomainCreateOptions = { + dataProvider: "Contoso", + id: "products", + name: "Products", + // ID of the custom function that is called on demand by Excel to resolve or refresh linked entity cell values of this data domain. + loadFunctionId: "CONTOSOLOADSERVICE", + // periodicRefreshInterval is only required when supportedRefreshModes contains "Periodic". + periodicRefreshInterval: 300, + // Manual refresh mode is always supported, even if unspecified. + supportedRefreshModes: [ + Excel.LinkedEntityDataDomainRefreshMode.periodic, + Excel.LinkedEntityDataDomainRefreshMode.onLoad + ] + }; + + const categoriesDomain: Excel.LinkedEntityDataDomainCreateOptions = { + dataProvider: "Contoso", + id: "categories", + name: "Categories", + loadFunctionId: "CONTOSOLOADSERVICE", + periodicRefreshInterval: 300, + supportedRefreshModes: [ + Excel.LinkedEntityDataDomainRefreshMode.periodic, + Excel.LinkedEntityDataDomainRefreshMode.onLoad + ] + }; + + const suppliersDomain: Excel.LinkedEntityDataDomainCreateOptions = { + dataProvider: "Contoso", + id: "suppliers", + name: "Suppliers", + loadFunctionId: "CONTOSOLOADSERVICE" + }; + // Register the data domains by adding them to the collection. + context.workbook.linkedEntityDataDomains.add(productsDomain); + context.workbook.linkedEntityDataDomains.add(categoriesDomain); + context.workbook.linkedEntityDataDomains.add(suppliersDomain); + + await context.sync(); + }); +}); +``` + +## Insert a linked entity cell value + +There are two ways to insert a linked entity cell value into a cell on a worksheet. + +- Create a command button on the ribbon or a button in your task pane. When the user selects the button, your code inserts a linked entity cell value. +- Create a custom function that returns a linked entity cell value. + +The following code example shows how to insert a new linked entity cell value into the selected cell. This code can be called from a command button on the ribbon, or a button in the task pane. Notes about the following code: + +- You must specify a `serviceId` of `268436224` for any linked entity cell values you return. This informs Excel that the linked entity cell value is associated with an Excel add-in. +- You must specify a `culture`. Excel will pass it to your linked entity load service function so that you can maintain the original culture when the workbook is opened in a different culture. +- The `text` property is displayed to the user in the cell while the linked entity data value is updated. This prevents the user seeing a blank cell while the update is completed. + +```typescript +async function insertProduct() { + await Excel.run(async (context) => { + const productLinkedEntity: Excel.LinkedEntityCellValue = { + type: Excel.CellValueType.linkedEntity, + id: { + entityId: "P1", // Don't use exclamation marks in this value. + domainId: "products", // Don't use exclamation marks in this value. + serviceId: 268436224, + culture: "en-US", + }, + text: "Chai", + }; + context.workbook.getActiveCell().valuesAsJson = [[productLinkedEntity]]; + await context.sync(); + }); +} +``` + +> [!NOTE] +> Don't use exclamation marks in the `entityID` or `domainId` values. + +The following code sample shows how to insert a linked entity cell value by using a custom function. A user could get a linked entity cell value by entering `=CONTOSO.GETPRODUCTBYID("productid")` into any cell. The notes for the previous code sample also apply to this one. + +```typescript +/** + * Custom function that shows how to insert a `LinkedEntityCellValue`. + * @customfunction + * @param {string} productID Unique ID of the product. + * @return {any} `LinkedEntityCellValue` for the requested product, if found. + */ +function getProductById(productID: string): any { + const product = getProduct(productID); + if (product === null) { + throw new CustomFunctions.Error(CustomFunctions.ErrorCode.notAvailable, "Invalid productID"); + } + const productLinkedEntity: Excel.LinkedEntityCellValue = { + type: Excel.CellValueType.linkedEntity, + id: { + entityId: product.productID, + domainId: "products", + serviceId: 268436224, + culture: "en-US", + }, + text: product.productName + }; + + return productLinkedEntity; +} +``` + +## Implement the linked entity load service function + +The add-in must provide a linked entity load service function to handle requests from Excel when property values are needed for any linked entity cell values. The function is identified with the `@linkedEntityLoadService` JSDoc tag. + +The following code example shows how to create a function that handles data requests from Excel for the **Products** and **Categories** data domains. Notes on the following code: + +- It uses helper functions to create the linked entity cell values. That code is shown later. +- If an error occurs it throws a `CustomFunctions.ErrorCode.notAvailable` error. This displays `#CONNECT!` in the cell that the user sees. + +```typescript +// Linked entity data domain constants +const productsDomainId = "products"; +const categoriesDomainId = "categories"; +const suppliersDomainId = "suppliers"; + +// Linked entity cell value constants +const addinDomainServiceId = 268436224; +const defaultCulture = "en-US"; + +/** + * Custom function which acts as the "service" or the data provider for a `LinkedEntityDataDomain`, that is + * called on demand by Excel to resolve/refresh `LinkedEntityCellValue`s of that `LinkedEntityDataDomain`. + * @customfunction + * @linkedEntityLoadService + * @param {any} request Request to resolve/refresh `LinkedEntityCellValue` objects. + * @return {any} Resolved/Refreshed `LinkedEntityCellValue` objects that were requested in the passed-in request. + */ +function contosoLoadService(request: any): any { + const notAvailableError = new CustomFunctions.Error(CustomFunctions.ErrorCode.notAvailable); + console.log(`Fetching linked entities from request: ${request} ...`); + + try { + // Parse the request that was passed-in by Excel. + const parsedRequest: Excel.LinkedEntityLoadServiceRequest = JSON.parse(request); + // Initialize result to populate and return to Excel. + const result: Excel.LinkedEntityLoadServiceResult = { entities: [] }; + + // Identify the domainId of the request and call the corresponding function to create + // linked entity cell values for that linked entity data domain. + for (const { entityId } of parsedRequest.entities) { + var linkedEntityResult = null; + switch (parsedRequest.domainId) { + case productsDomainId: { + linkedEntityResult = makeProductLinkedEntity(entityId); + break; + } + case categoriesDomainId: { + linkedEntityResult = makeCategoryLinkedEntity(entityId); + break; + } + case suppliersDomainId: { + linkedEntityResult = makeSupplierLinkedEntity(entityId); + break; + } + default: + throw notAvailableError; + } + + if (!linkedEntityResult) { + // Throw an error to signify to Excel that resolution/refresh of the requested linkedEntityId failed. + throw notAvailableError; + } + + result.entities.push(linkedEntityResult); + } + + return result; + } catch (error) { + console.error(error); + throw notAvailableError; + } +} +``` + +The following code sample shows the helper function to create a product linked entity cell value. This function is called by the previous code `contosoLoadService` to create a linked entity for a specific product ID. Notes on the following code: + +- It uses the same settings as the previous `insertProduct` example for the `type`, `id`, and `text` properties. +- It includes additional properties specific to the **Products** data domain, such as `Product Name` and `Unit Price`. +- It creates a deferred nested linked entity for the category of the product. The properties for the category are not requested until they are needed. + +```typescript +/** Helper function to create a linked entity from product properties. */ +function makeProductLinkedEntity(productID: string): any { + // Search the product data in the data source for a matching product ID. + const product = getProduct(productID); + if (product === null) { + // Return null if no matching product is found. + return null; + } + + const productLinkedEntity: Excel.LinkedEntityCellValue = { + type: "LinkedEntity", + text: product.productName, + id: { + entityId: product.productID, + domainId: productsDomainId, + serviceId: addinDomainServiceId, + culture: defaultCulture + }, + properties: { + "Product ID": { + type: "String", + basicValue: product.productID + }, + "Product Name": { + type: "String", + basicValue: product.productName + }, + "Quantity Per Unit": { + type: "String", + basicValue: product.quantityPerUnit + }, + // Add Unit Price as a formatted number. + "Unit Price": { + type: "FormattedNumber", + basicValue: product.unitPrice, + numberFormat: "$* #,##0.00" + }, + Discontinued: { + type: "Boolean", + basicValue: product.discontinued + } + }, + layouts: { + compact: { + icon: "ShoppingBag" + }, + card: { + title: { property: "Product Name" }, + sections: [ + { + layout: "List", + properties: ["Product ID"] + }, + { + layout: "List", + title: "Quantity and price", + collapsible: true, + collapsed: false, + properties: ["Quantity Per Unit", "Unit Price"] + }, + { + layout: "List", + title: "Additional information", + collapsed: true, + properties: ["Discontinued"] + } + ] + } + } + }; + + // Add image property to the linked entity and then add it to the card layout. + if (product.productImage) { + productLinkedEntity.properties["Image"] = { + type: "WebImage", + address: product.productImage + }; + productLinkedEntity.layouts.card.mainImage = { property: "Image" }; + } + + // Add a deferred nested linked entity for the product category. + const category = getCategory(product.categoryID.toString()); + if (category) { + productLinkedEntity.properties["Category"] = { + type: "LinkedEntity", + text: category.categoryName, + id: { + entityId: category.categoryID.toString(), + domainId: categoriesDomainId, + serviceId: addinDomainServiceId, + culture: defaultCulture + } + }; + + // Add nested product category to the card layout. + productLinkedEntity.layouts.card.sections[0].properties.push("Category"); + } + + // Add a deferred nested linked entity for the supplier. + const supplier = getSupplier(product.supplierID.toString()); + if (supplier) { + productLinkedEntity.properties["Supplier"] = { + type: "LinkedEntity", + text: supplier.companyName, + id: { + entityId: supplier.supplierID.toString(), + domainId: suppliersDomainId, + serviceId: addinDomainServiceId, + culture: defaultCulture + } + }; + + // Add nested product supplier to the card layout. + productLinkedEntity.layouts.card.sections[2].properties.push("Supplier"); + } + + return productLinkedEntity; +} +``` + +The following code sample shows the helper function to create a category linked entity cell value. This function is called by the previous code `contosoLoadService` to create a linked entity for a specific category ID. + +```typescript +/** Helper function to create a linked entity from category properties. */ +function makeCategoryLinkedEntity(categoryID: string): any { + // Search the sample JSON category data for a matching category ID. + const category = getCategory(categoryID); + if (category === null) { + // Return null if no matching category is found. + return null; + } + + const categoryLinkedEntity: Excel.LinkedEntityCellValue = { + type: "LinkedEntity", + text: category.categoryName, + id: { + entityId: category.categoryID, + domainId: categoriesDomainId, + serviceId: addinDomainServiceId, + culture: defaultCulture + }, + properties: { + "Category ID": { + type: "String", + basicValue: category.categoryID, + propertyMetadata: { + // Exclude the category ID property from the card view and auto-complete. + excludeFrom: { + cardView: true, + autoComplete: true + } + } + }, + "Category Name": { + type: "String", + basicValue: category.categoryName + }, + Description: { + type: "String", + basicValue: category.description + } + }, + layouts: { + compact: { + icon: "Branch" + } + } + }; + + return categoryLinkedEntity; +} +``` + +The following code sample shows the helper function to create a supplier linked entity cell value. This function is called by the previous code `contosoLoadService` to create a linked entity for a specific supplier ID. + +```typescript +/** Helper function to create linked entity from supplier properties. */ +function makeSupplierLinkedEntity(supplierID: string): any { + // Search the sample JSON category data for a matching supplier ID. + const supplier = getSupplier(supplierID); + if (supplier === null) { + // Return null if no matching supplier is found. + return null; + } + + const supplierLinkedEntity: Excel.LinkedEntityCellValue = { + type: "LinkedEntity", + text: supplier.companyName, + id: { + entityId: supplier.supplierID, + domainId: suppliersDomainId, + serviceId: addinDomainServiceId, + culture: defaultCulture + }, + properties: { + "Supplier ID": { + type: "String", + basicValue: supplier.supplierID + }, + "Company Name": { + type: "String", + basicValue: supplier.companyName + }, + "Contact Name": { + type: "String", + basicValue: supplier.contactName + }, + "Contact Title": { + type: "String", + basicValue: supplier.contactTitle + } + }, + cardLayout: { + title: { property: "Company Name" }, + sections: [ + { + layout: "List", + properties: ["Supplier ID", "Company Name", "Contact Name", "Contact Title"] + } + ] + } + }; + + return supplierLinkedEntity; +} +``` + +The following code sample contains sample data you can use with the previous code samples. + +```typescript +/// Sample product data. +const products = [ + { + productID: "P1", + productName: "Chai", + supplierID: "S1", + categoryID: "C1", + quantityPerUnit: "10 boxes x 20 bags", + unitPrice: 18, + discontinued: false, + productImage: "https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Masala_Chai.JPG/320px-Masala_Chai.JPG" + } +]; + +/// Sample product category data. +const categories = [ + { + categoryID: "C1", + categoryName: "Beverages", + description: "Soft drinks, coffees, teas, beers, and ales" + }]; + +/// Sample product supplier data. +const suppliers = [ + { + supplierID: "S1", + companyName: "Exotic Liquids", + contactName: "Ema Vargova", + contactTitle: "Purchasing Manager" + }]; +``` + +## Data refresh options + +When you register a data domain, the user can refresh it manually at any time, such as by choosing **Refresh All** from the **Data** tab. There are three refresh modes you can specify for your data domain. + +- `manual`- The data is refreshed only when the user chooses to refresh. This is the default mode. Manual refresh can always be performed by the user, even when the refresh mode is set to `onLoad` or `periodic`. +- `onLoad`- The data is refreshed when the data domain is registered (typically when the add-in is loaded). Afterwards, data is only refreshed manually by the user. If you want to refresh data when the workbook is opened, configure your add-in to load on document open. For more information, see [Run code in your Office Add-in when the document opens](../develop/run-code-on-document-open.md). +- `periodic`- The data is refreshed when the data domain is registered (typically when the add-in is loaded). Afterwards, the data is continuously updated after a specified interval of time. For example you could specify that the data domain refreshes every 300 seconds (which is the minimum value). The number of seconds is always rounded up to the nearest number of minutes since the refresh interval is only performed in minutes. + +The following code example shows how to configure a data domain to refresh on load, and then continue to refresh every 5 minutes. + +```typescript +const productsDomain: Excel.LinkedEntityDataDomainCreateOptions = { + dataProvider: domainDataProvider, + id: "products", + name: "Products", + // ID of the custom function that is called on demand by Excel to resolve or refresh linked entity cell values of this data domain. + loadFunctionId: loadFunctionId, + // periodicRefreshInterval is only required when supportedRefreshModes contains "Periodic". + periodicRefreshInterval: 300, // equivalent to 5 minutes. + // Manual refresh mode is always supported, even if unspecified. + supportedRefreshModes: [ + Excel.LinkedEntityDataDomainRefreshMode.periodic, + Excel.LinkedEntityDataDomainRefreshMode.onLoad + ] +}; +``` + +You can also programmatically request a refresh on a linked entity data domain by using either of the following methods. + +- `LinkedEntityDataDomain.refresh()` - Refreshes all `LinkedEntityCellValue` objects of the linked entity data domain. +- `LinkedEntityDataDomainCollection.refreshAll()` - Refreshes all `LinkedEntityCellValue` objects of all linked entity data domains in the collection. + +The refresh methods request a refresh which occurs asynchronously. To determine the results of the refresh, listen for the `onRefreshCompleted` event. The following code sample shows an example of listening for the `onRefreshCompleted` event. + +```typescript +await Excel.run(async (context) => { + const dataDomains = context.workbook.linkedEntityDataDomains; + dataDomains.onRefreshCompleted.add(onLinkedEntityDomainRefreshed); + + await context.sync(); +}); + +async function onLinkedEntityDomainRefreshed(eventArgs: Excel.LinkedEntityDataDomainRefreshCompletedEventArgs): Promise { + console.log("Linked entity domain refreshed: " + eventArgs.id); + console.log("Refresh status: " + eventArgs.refreshed); + console.log("Refresh error: " + eventArgs.errors); + return null; +} +``` + +## Error handling with the linked entity load service + +When Excel calls your add-in to get data for a linked entity cell value, it's possible an error can occur. If Excel is unable to connect to your add-in at all, such as when the add-in isn't loaded, Excel displays the `#CONNECT!` error to the user. + +If your linked entity load service function encounters an error, it should throw the `notAvailableError` error. This causes Excel to show `#CONNECT!` to the user. + +The following code shows how to handle an error in a linked entity load service function. + +```typescript +async function contosoLoadService(request: any): Promise { + const notAvailableError = new CustomFunctions.Error(CustomFunctions.ErrorCode.notAvailable); + try { + // Create and return a new linked entity cell value. + let linkedEntityResult = ... + ... + if (!linkedEntityResult) { + // Throw an error to signify to Excel that resolution or refresh of the requested linkedEntityId failed. + throw notAvailableError; + } + ... + } catch (error) { + console.error(error); + throw notAvailableError; + } +} +``` + +## Debugging the linked entity load service + +Most add-in functionality for linked entity data types can be debugged using the guidance in [Overview of debugging Office Add-ins](../testing/debug-add-ins-overview.md). However, the linked entity load service function can be implemented in a shared runtime or a JavaScript-only runtime (also know as a custom functions runtime.) If you choose to implement the function in a JavaScript-only runtime, use the [Custom functions debugging in a non-shared runtime](custom-functions-debugging.md) guidance. + +The linked entity load service function uses the custom functions architecture, regardless of which runtime you use. However, there are significant differences from regular custom functions. + +Linked entity load service functions have the following differences from custom functions: + +- They don't appear to end users for usage in formulas. +- They don't support the JSDoc tags `@streaming` or `@volatile`. The user will see a **#CALC!** error if these tags are used. + +Linked entity load service functions have the following similarities with custom functions: + +- They use [Custom functions naming and localization](custom-functions-naming.md). +- They use the same error handling approach. + +## Behavior in Excel 2019 and earlier + +If someone opens a worksheet with linked entity cell values on an older version of Excel that doesn’t support linked entity cell values, Excel shows the cell values as errors. This is the designed behavior. This is also why you set the `basicType` to `Error` and the `basicValue` to `#VALUE!` every time you insert or update a linked entity cell value. This is the error that Excel uses as a fallback on older versions. + +## Best practices + +- Don't use exclamation marks in the `entityID` or `domainId` values. +- Register linked entity data domains in the initialization code `Office.OnReady` so that the user has immediate functionality such as the ability to refresh the linked entity cell values. +- After publishing your add-in, don’t change the linked entity data domain IDs. Consistent IDs across the same logical objects helps with performance. +- Always provide the `text` property when creating a new linked entity cell value. This value is displayed while Excel calls your data provider function to get the remaining property values. Otherwise the user sees a blank cell until the data is retrieved. + +## See also + +- [Overview of data types in Excel add-ins](excel-data-types-overview.md) diff --git a/docs/excel/excel-data-types-overview.md b/docs/excel/excel-data-types-overview.md index 2a19a6257b..450488415b 100644 --- a/docs/excel/excel-data-types-overview.md +++ b/docs/excel/excel-data-types-overview.md @@ -1,7 +1,7 @@ --- title: Overview of data types in Excel add-ins description: Data types in the Excel JavaScript API enable Office Add-in developers to work with formatted number values, web images, entities, arrays within entities, and enhanced errors as data types. -ms.date: 12/14/2022 +ms.date: 01/22/2025 ms.topic: overview ms.custom: scenarios:getting-started ms.localizationpriority: high @@ -11,9 +11,9 @@ ms.localizationpriority: high Data types organize complex data structures as objects. This includes formatted number values, web images, and entities as [entity cards](excel-data-types-entity-card.md). -The following screenshot highlights one of the primary features of data types: an entity card. In this case, the entity card shows expanded information about the **Tofu** product from a list of grocery store products. +The following screenshot highlights one of the primary features of data types: an entity card. In this case, the entity card shows expanded information about the **Chef Anton's Gumbo Mix** product from a list of grocery store products. -:::image type="content" source="../images/excel-data-types-entity-card-tofu.png" alt-text="An entity value data type with the card window displayed."::: +:::image type="content" source="../images/excel-data-types-entity-card-gumbo.png" alt-text="An entity value data type with the card window displayed."::: > [!NOTE] > To start experimenting with data types right away, install [Script Lab](../overview/explore-with-script-lab.md) in Excel and check out the **Data types** section in our **Samples** library. You can also explore the Script Lab samples in our [OfficeDev/office-js-snippets](https://github.com/OfficeDev/office-js-snippets/tree/prod/samples/excel/20-data-types) repository. diff --git a/docs/excel/make-custom-functions-compatible-with-xll-udf.md b/docs/excel/make-custom-functions-compatible-with-xll-udf.md index ea54da2370..7b3d247bb7 100644 --- a/docs/excel/make-custom-functions-compatible-with-xll-udf.md +++ b/docs/excel/make-custom-functions-compatible-with-xll-udf.md @@ -1,11 +1,11 @@ --- -title: Extend custom functions with XLL user-defined functions -description: Enable compatibility with Excel XLL user-defined functions that have equivalent functionality to your custom functions. -ms.date: 10/23/2023 +title: Extend custom functions with XLL add-ins +description: Enable compatibility with Excel XLL add-ins that have equivalent functionality to your custom functions. +ms.date: 07/29/2025 ms.localizationpriority: medium --- -# Extend custom functions with XLL user-defined functions +# Extend custom functions with XLL add-ins > [!NOTE] > An XLL add-in is an Excel add-in file with the file extension **.xll**. An XLL file is a type of dynamic link library (DLL) file that can only be opened by Excel. XLL add-in files must be written in C or C++. See [Developing Excel XLLs](/office/client-developer/excel/developing-excel-xlls) to learn more. @@ -20,7 +20,33 @@ To enable compatibility with an existing XLL add-in, identify the equivalent XLL To set the equivalent XLL add-in for your custom functions, specify the `FileName` of the XLL file. When the user opens a workbook with functions from the XLL file, Excel converts the functions to compatible functions. The workbook then uses the XLL file when opened in Excel on Windows, but it continues to use custom functions from your Excel JavaScript API add-in when opened on the web or on Mac. -The following example shows how to specify both a COM add-in and an XLL add-in as equivalents in an Excel JavaScript API add-in manifest file. Often you specify both. For completeness, this example shows both equivalents in context. They're identified by their `ProgId` and `FileName` respectively. The `EquivalentAddins` element must be positioned immediately before the closing `VersionOverrides` tag. For more information on COM add-in compatibility, see [Make your Office Add-in compatible with an existing COM add-in](../develop/make-office-add-in-compatible-with-existing-com-add-in.md). +The manifest configuration depends on what type of manifest the add-in uses. + +# [Unified manifest for Microsoft 365](#tab/jsonmanifest) + +The following example shows how to specify both a COM add-in and an XLL add-in as equivalents in a unified manifest. Often you specify both. For completeness, this example shows both equivalents in context. They're identified by their [`"alternates.prefer.comAddin.progId"`](/microsoft-365/extensibility/schema/extension-alternate-versions-array-prefer-com-addin#progid) and [`"alternates.prefer.xllCustomFunctions.filename"`](/microsoft-365/extensibility/schema/extension-xll-custom-functions#filename) respectively. For more information on COM add-in compatibility, see [Make your Office Add-in compatible with an existing COM or VSTO add-in](../develop/make-office-add-in-compatible-with-existing-com-add-in.md). + +```json +"extensions" [ + ... + "alternates" [ + { + "prefer": { + "comAddin": { + "progId": "ContosoCOMAddin" + }, + "xllCustomFunctions": { + "fileName": "contosofunctions.xll" + } + } + } + ] +] +``` + +# [Add-in only manifest](#tab/xmlmanifest) + +The following example shows how to specify both a COM add-in and an XLL add-in as equivalents in an Excel JavaScript API add-in only manifest file. Often you specify both. For completeness, this example shows both equivalents in context. They're identified by their `ProgId` and `FileName` respectively. The `EquivalentAddins` element must be positioned immediately before the closing `VersionOverrides` tag. For more information on COM add-in compatibility, see [Make your Office Add-in compatible with an existing COM or VSTO add-in](../develop/make-office-add-in-compatible-with-existing-com-add-in.md). ```xml @@ -39,6 +65,8 @@ The following example shows how to specify both a COM add-in and an XLL add-in a ``` +--- + > [!NOTE] > If an Excel JavaScript API add-in declares its custom functions to be compatible with an XLL add-in, changing the manifest at a later time could break a user's workbook because it will change the file format. @@ -62,5 +90,5 @@ The following table compares features across XLL user-defined functions, XLL com ## See also -- [Make your Office Add-in compatible with an existing COM add-in](../develop/make-office-add-in-compatible-with-existing-com-add-in.md) +- [Make your Office Add-in compatible with an existing COM or VSTO add-in](../develop/make-office-add-in-compatible-with-existing-com-add-in.md) - [Excel custom functions tutorial](../tutorials/excel-tutorial-create-custom-functions.md) diff --git a/docs/excel/performance.md b/docs/excel/performance.md index 3ee9d34066..60ef08f5f1 100644 --- a/docs/excel/performance.md +++ b/docs/excel/performance.md @@ -1,25 +1,37 @@ --- title: Excel JavaScript API performance optimization -description: Optimize Excel add-in performance using the JavaScript API. -ms.date: 02/17/2022 +description: Optimize Excel add-in performance using the Excel JavaScript API with batching, fewer objects, and reduced payload size. +ms.date: 09/19/2025 ms.topic: best-practice ms.localizationpriority: medium --- # Performance optimization using the Excel JavaScript API -There are multiple ways that you can perform common tasks with the Excel JavaScript API. You'll find significant performance differences between various approaches. This article provides guidance and code samples to show you how to perform common tasks efficiently using Excel JavaScript API. +Write faster, more scalable Excel add-ins by minimizing processes, batching functions, and reducing payload size. This article shows patterns, anti-patterns, and code samples to help you optimize common operations. + +## Quick improvements + +Apply these strategies first for the largest immediate impact. + +- Batch loads and writes: group property `load` calls, then make a single `context.sync()`. +- Minimize object creation: operate on block ranges instead of many single-cell ranges. +- Write data in arrays, then assign once to a target range. +- Suspend screen updating or calculation only around large changes. +- Avoid per-iteration `Excel.run` or `context.sync()` inside loops. +- Reuse worksheet, table, and range objects instead of re-querying inside loops. +- Keep payloads below size limits by chunking or aggregating before assignment. > [!IMPORTANT] > Many performance issues can be addressed through recommended usage of `load` and `sync` calls. See the "Performance improvements with the application-specific APIs" section of [Resource limits and performance optimization for Office Add-ins](../concepts/resource-limits-and-performance-optimization.md#performance-improvements-with-the-application-specific-apis) for advice on working with the application-specific APIs in an efficient way. ## Suspend Excel processes temporarily -Excel has a number of background tasks reacting to input from both users and your add-in. Some of these Excel processes can be controlled to yield a performance benefit. This is especially helpful when your add-in deals with large data sets. +Excel performs background tasks that react to user input and add-in actions. Pausing selected processes can improve performance for large operations. ### Suspend calculation temporarily -If you are trying to perform an operation on a large number of cells (for example, setting the value of a huge range object) and you don't mind suspending the calculation in Excel temporarily while your operation finishes, we recommend that you suspend calculation until the next `context.sync()` is called. +If you need to update a large range (such as to assign values and then recalculate dependent formulas) and interim recalculation results aren't needed, suspend calculation temporarily until the next `context.sync()`. See the [Application Object](/javascript/api/excel/excel.application) reference documentation for information about how to use the `suspendApiCalculationUntilNextSync()` API to suspend and reactivate calculations in a very convenient way. The following code demonstrates how to suspend calculation temporarily. @@ -62,22 +74,27 @@ await Excel.run(async (context) => { }); ``` -Please note that only formula calculations are suspended. Any altered references are still rebuilt. For example, renaming a worksheet still updates any references in formulas to that worksheet. +Only formula calculations are suspended. Any altered references are still rebuilt. For example, renaming a worksheet still updates any references in formulas to that worksheet. ### Suspend screen updating -Excel displays changes your add-in makes approximately as they happen in the code. For large, iterative data sets, you may not need to see this progress on the screen in real-time. `Application.suspendScreenUpdatingUntilNextSync()` pauses visual updates to Excel until the add-in calls `context.sync()`, or until `Excel.run` ends (implicitly calling `context.sync`). Be aware, Excel will not show any signs of activity until the next sync. Your add-in should either give users guidance to prepare them for this delay or provide a status bar to demonstrate activity. +Excel displays changes as they occur. For large, iterative updates, suppress intermediate screen updates. `Application.suspendScreenUpdatingUntilNextSync()` pauses visual updates until the next `context.sync()` or the end of `Excel.run`. Provide your users with feedback such as status text or a progress bar, because the UI appears idle during suspension. > [!NOTE] > Don't call `suspendScreenUpdatingUntilNextSync` repeatedly (such as in a loop). Repeated calls will cause the Excel window to flicker. ### Enable and disable events -Performance of an add-in may be improved by disabling events. A code sample showing how to enable and disable events is in the [Work with Events](excel-add-ins-events.md#enable-and-disable-events) article. +You can sometimes improve performance by disabling events. A code sample showing how to enable and disable events is in the [Work with Events](excel-add-ins-events.md#enable-and-disable-events) article. ## Importing data into tables -When trying to import a huge amount of data directly into a [Table](/javascript/api/excel/excel.table) object directly (for example, by using `TableRowCollection.add()`), you might experience slow performance. If you are trying to add a new table, you should fill in the data first by setting `range.values`, and then call `worksheet.tables.add()` to create a table over the range. If you are trying to write data into an existing table, write the data into a range object via `table.getDataBodyRange()`, and the table will expand automatically. +When you import large datasets directly into a [Table](/javascript/api/excel/excel.table), such as repeatedly calling `TableRowCollection.add()`, performance can degrade. Instead, take the following approach: + +1. Write the entire 2D array to a range with `range.values`. +2. Create the table over that populated range (`worksheet.tables.add()`). + +For existing tables, set values on `table.getDataBodyRange()` in bulk. The table expands automatically. Here is an example of this approach: @@ -107,19 +124,19 @@ await Excel.run(async (context) => { ## Payload size limit best practices -The Excel JavaScript API has size limitations for API calls. Excel on the web has a payload size limit for requests and responses of 5MB, and an API returns a `RichAPI.Error` error if this limit is exceeded. On all platforms, a range is limited to five million cells for get operations. Large ranges typically exceed both of these limitations. +The Excel JavaScript API has size limitations for API calls. **Excel on the web** limits requests and responses to **5 MB**. The API returns a `RichAPI.Error` error if this limit is exceeded. On all platforms, a range is limited to five million cells for get operations. Large ranges often exceed both limits. -The payload size of a request is a combination of the following three components. +The payload size of a request combines: -* The number of API calls -* The number of objects, such as `Range` objects -* The length of the value to set or get +- The number of API calls. +- The number of objects, such as `Range` objects. +- The length of the value to set or get. -If an API returns the `RequestPayloadSizeLimitExceeded` error, use the best practice strategies documented in this article to optimize your script and avoid the error. +If you get `RequestPayloadSizeLimitExceeded`, apply the following strategies to reduce size before you split operations. ### Strategy 1: Move unchanged values out of loops -Limit the number of processes that occur within loops to improve performance. In the following code sample, `context.workbook.worksheets.getActiveWorksheet()` can be moved out of the `for` loop, because it doesn't change within that loop. +Limit the processes inside loops to improve performance. In the following code sample, `context.workbook.worksheets.getActiveWorksheet()` can be moved out of the `for` loop because it doesn't change within that loop. ```js // DO NOT USE THIS CODE SAMPLE. This sample shows a poor performance strategy. @@ -136,7 +153,7 @@ async function run() { } ``` -The following code sample shows logic similar to the preceding code sample, but with an improved performance strategy. The value `context.workbook.worksheets.getActiveWorksheet()` is retrieved before the `for` loop, because this value doesn't need to be retrieved each time the `for` loop runs. Only values that change within the context of a loop should be retrieved within that loop. +The following code sample shows similar logic but with an improved strategy. The value `context.workbook.worksheets.getActiveWorksheet()` is retrieved before the loop because it doesn't change. Only values that vary should be retrieved inside the loop. ```js // This code sample shows a good performance strategy. @@ -157,14 +174,14 @@ async function run() { ### Strategy 2: Create fewer range objects -Create fewer range objects to improve performance and minimize payload size. Two approaches for creating fewer range objects are described in the following article sections and code samples. +Create fewer range objects to improve performance and reduce payload size. Two approaches follow. #### Split each range array into multiple arrays One way to create fewer range objects is to split each range array into multiple arrays, and then process each new array with a loop and a new `context.sync()` call. > [!IMPORTANT] -> Only use this strategy if you've first determined that you're exceeding the payload request size limit. Using multiple loops can reduce the size of each payload request to avoid exceeding the 5MB limit, but using multiple loops and multiple `context.sync()` calls also negatively impacts performance. +> Only use this strategy after you have confirmed that you exceed the payload size limit. Multiple loops reduce the size of each payload request but also add extra `context.sync()` calls and can hurt performance. The following code sample attempts to process a large array of ranges in a single loop and then a single `context.sync()` call. Processing too many range values in one `context.sync()` call causes the payload request size to exceed the 5MB limit. @@ -239,9 +256,14 @@ async function run() { } ``` +## Next steps + +- Review [resource limits and performance optimization](../concepts/resource-limits-and-performance-optimization.md) for host-level constraints. +- Explore [working with multiple ranges](excel-add-ins-multiple-ranges.md) to create fewer objects. +- Add telemetry for data such as operation durations and row counts to guide further performance optimization. + ## See also -* [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) -* [Error handling with the application-specific JavaScript APIs](../testing/application-specific-api-error-handling.md) -* [Resource limits and performance optimization for Office Add-ins](../concepts/resource-limits-and-performance-optimization.md) -* [Worksheet Functions Object (JavaScript API for Excel)](/javascript/api/excel/excel.functions) +- [Excel JavaScript object model in Office Add-ins](excel-add-ins-core-concepts.md) +- [Error handling with the application-specific JavaScript APIs](../testing/application-specific-api-error-handling.md) +- [Worksheet Functions Object (JavaScript API for Excel)](/javascript/api/excel/excel.functions) \ No newline at end of file diff --git a/docs/excel/pnp-open-in-excel.md b/docs/excel/pnp-open-in-excel.md index 6d249e4373..65efe814f1 100644 --- a/docs/excel/pnp-open-in-excel.md +++ b/docs/excel/pnp-open-in-excel.md @@ -1,4 +1,4 @@ ---- +--- title: Create an Excel spreadsheet from your web page, populate it with data, and embed your Office Add-in description: Create an Excel spreadsheet from your web page, populate it with data, and embed your Office Add-in. ms.date: 01/23/2023 @@ -75,15 +75,15 @@ Much of the `SpreadsheetBuilder` class contains code that was generated by the O The `SpreadsheetBuilder` class also embeds the Script Lab add-in inside the spreadsheet and configures to display when the document is opened. -The **SpreadsheetBuilder.GenerateWebExtensionPart1Content** method in the **SpreadsheetBuilder.cs** file sets the reference to the ID of Script Lab in Microsoft AppSource: +The **SpreadsheetBuilder.GenerateWebExtensionPart1Content** method in the **SpreadsheetBuilder.cs** file sets the reference to the ID of Script Lab in Microsoft Marketplace: ```csharp We.WebExtensionStoreReference webExtensionStoreReference1 = new We.WebExtensionStoreReference() { Id = "wa104380862", Version = "1.1.0.0", Store = "en-US", StoreType = "OMEX" }; ``` -- The **StoreType** value is "OMEX", an alias for Microsoft AppSource. -- The **Store** value is "en-US" found in the Microsoft AppSource culture section for Script Lab. -- The **Id** value is the Microsoft AppSource asset ID for Script Lab. +- The **StoreType** value is "OMEX", an alias for Microsoft Marketplace. +- The **Store** value is "en-US" found in the Microsoft Marketplace culture section for Script Lab. +- The **Id** value is the Microsoft Marketplace asset ID for Script Lab. You can change these values to embed your own Office Add-in. This makes it discoverable to the user and increases engagement with your add-in and web services. If your add-in is deployed through central deployment, use the following values instead. diff --git a/docs/excludes/excel-quickstart-angular.md b/docs/excludes/excel-quickstart-angular.md index 22d661f70f..f0cc148113 100644 --- a/docs/excludes/excel-quickstart-angular.md +++ b/docs/excludes/excel-quickstart-angular.md @@ -27,8 +27,6 @@ In this article, you'll walk through the process of building an Excel task pane After you complete the wizard, the generator creates the project and installs supporting Node components. -[!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - ## Explore the project The add-in project that you've created with the Yeoman generator contains sample code for a basic task pane add-in. If you'd like to explore the key components of your add-in project, open the project in your code editor and review the files listed below. When you're ready to try out your add-in, proceed to the next section. diff --git a/docs/excludes/outlook-quickstart-json-manifest-typescript.md b/docs/excludes/outlook-quickstart-json-manifest-typescript.md index d91465b7d3..082be5c055 100644 --- a/docs/excludes/outlook-quickstart-json-manifest-typescript.md +++ b/docs/excludes/outlook-quickstart-json-manifest-typescript.md @@ -1,14 +1,14 @@ ---- +--- title: Build an Outlook add-in with the unified manifest for Microsoft 365 description: Learn how to build a simple Outlook task pane add-in with the unified manifest for Microsoft 365. -ms.date: 01/26/2024 +ms.date: 05/19/2025 ms.service: outlook ms.localizationpriority: high --- # Build an Outlook add-in with the unified manifest for Microsoft 365 -There are two tools that you can use to create an Outlook Add-in project that uses the unified manifest for Microsoft 365. This article describes how to do it with the Yeoman generator for Office (also called "Yo Office"). Alternatively, you can create an Outlook add-in project with the Teams Toolkit as described at [Create Office Add-in projects with Teams Toolkit](../develop/teams-toolkit-overview.md). +There are two tools that you can use to create an Outlook Add-in project that uses the unified manifest for Microsoft 365. This article describes how to do it with the Yeoman generator for Office (also called "Yo Office"). Alternatively, you can create an Outlook add-in project with Microsoft 365 Agents Toolkit as described at [Create Office Add-in projects with Microsoft 365 Agents Toolkit](../develop/agents-toolkit-overview.md). In this article, you'll walk through the process of building an Outlook task pane add-in that displays a property of a selected message, triggers a notification on the reading pane, and inserts text into a message on the compose pane. This add-in will use the unified manifest for Microsoft 365. For more information about this manifest, see [Unified manifest for Microsoft 365](../develop/unified-manifest-overview.md). @@ -46,8 +46,6 @@ You can create an Office Add-in with the unified manifest by using the [Yeoman g After you complete the wizard, the generator will create the project and install supporting Node components. - [!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - 1. Navigate to the root folder of the web application project. ```command line @@ -72,7 +70,7 @@ The add-in project that you've created with the Yeoman generator contains sample > [!TIP] > On Windows, you can navigate to the root directory of the project via the command line and then enter `code .` to open that folder in VS Code. -1. Open the file **./src/taskpane/taskpane.html** and replace the entire **\** element (within the **\** element) with the following markup. This new markup adds a label where the script in **./src/taskpane/taskpane.ts** will write data. +1. Open the file **./src/taskpane/taskpane.html** and replace the entire `
` element (within the `` element) with the following markup. This new markup adds a label where the script in **./src/taskpane/taskpane.ts** will write data. ```html
@@ -159,7 +157,7 @@ Add a custom button to the ribbon that inserts text into a message body. 1. To write to a message, the add-in's permissions need to be raised. Scroll to the property `authorization.permissions.resourceSpecific[0].name` and change the value to `MailboxItem.ReadWrite.User`. -1. When an add-in command runs code instead of opening a task pane, it must run the code in a runtime that is separate from the embedded webview where the task pane code runs. So the manifest must specify an additional runtime. Scroll to the property `extension.runtimes` and add the following object to the `runtimes` array. Be sure to put a comma after the object that is already in the array. Note the following about this markup. +1. When an add-in command runs code instead of opening a task pane, it must run the code in a runtime that is separate from the embedded webview where the task pane code runs. So the manifest must specify an additional runtime. Scroll to the property `"extension.runtimes"` and add the following object to the [`"runtimes"`](/microsoft-365/extensibility/schema/element-extensions#runtimes) array. Be sure to put a comma after the object that is already in the array. Note the following about this markup. - The value of the `actions[0].id` property must be exactly the same as the name of the function that you added to the **commands.ts** file, in this case `insertHelloWorld`. In a later step, you'll refer to the item by this ID. @@ -182,9 +180,9 @@ Add a custom button to the ribbon that inserts text into a message body. } ``` -1. The **Show Taskpane** button appears when the user is reading an email, but the button for adding text should only appear when the user is composing a new email (or replying to one). So the manifest must specify a new ribbon object. Scroll to the property `extension.ribbons` and add the following object to the `ribbons` array. Be sure to put a comma after the object that is already in the array. Note the following about this JSON: +1. The **Show Taskpane** button appears when the user is reading an email, but the button for adding text should only appear when the user is composing a new email (or replying to one). So the manifest must specify a new ribbon object. Scroll to the property `"extension.ribbons"` and add the following object to the [`"ribbons"`](/microsoft-365/extensibility/schema/element-extensions#ribbons) array. Be sure to put a comma after the object that is already in the array. Note the following about this JSON: - - The only value in the `contexts` array is "mailCompose", so the button will appear when in a compose (or reply) window but not in a message read window where the **Show Taskpane** and **Perform an action** buttons appear. Compare this value with the `contexts` array in the existing ribbon object, whose value is `["mailRead"]`. + - The only value in the `contexts` array is `"mailCompose"`, so the button will appear when in a compose (or reply) window but not in a message read window where the **Show Taskpane** and **Perform an action** buttons appear. Compare this value with the `contexts` array in the existing ribbon object, whose value is `[`"mailRead"`]`. - The value of the `tabs[0].groups[0].controls[0].actionId` must be exactly the same as the value of `actions[0].id` property in the runtime object you created in an earlier step. ```json diff --git a/docs/reference/images/Visio-embed-url.png b/docs/images/Visio-embed-url.png similarity index 100% rename from docs/reference/images/Visio-embed-url.png rename to docs/images/Visio-embed-url.png diff --git a/docs/images/add-in-shortcut-conflict-modal.png b/docs/images/add-in-shortcut-conflict-modal.png index 737a112bd4..24bfb9cb4c 100644 Binary files a/docs/images/add-in-shortcut-conflict-modal.png and b/docs/images/add-in-shortcut-conflict-modal.png differ diff --git a/docs/images/addinRegistrationWindows.png b/docs/images/addinRegistrationWindows.png new file mode 100644 index 0000000000..da57f9c71f Binary files /dev/null and b/docs/images/addinRegistrationWindows.png differ diff --git a/docs/images/addinRegistrationWindowsDeveloperSubkeys.png b/docs/images/addinRegistrationWindowsDeveloperSubkeys.png new file mode 100644 index 0000000000..e0c5a2a412 Binary files /dev/null and b/docs/images/addinRegistrationWindowsDeveloperSubkeys.png differ diff --git a/docs/images/addinRegistrationWindowsManifestPath.png b/docs/images/addinRegistrationWindowsManifestPath.png new file mode 100644 index 0000000000..a4b35cde39 Binary files /dev/null and b/docs/images/addinRegistrationWindowsManifestPath.png differ diff --git a/docs/images/alert-caution.gif b/docs/images/alert-caution.gif deleted file mode 100644 index 331b50bda2..0000000000 Binary files a/docs/images/alert-caution.gif and /dev/null differ diff --git a/docs/images/alert-note.gif b/docs/images/alert-note.gif deleted file mode 100644 index 57bf20c916..0000000000 Binary files a/docs/images/alert-note.gif and /dev/null differ diff --git a/docs/images/atk-cli-install.png b/docs/images/atk-cli-install.png new file mode 100644 index 0000000000..9ae5688238 Binary files /dev/null and b/docs/images/atk-cli-install.png differ diff --git a/docs/images/atk-toolkit-icon.png b/docs/images/atk-toolkit-icon.png new file mode 100644 index 0000000000..3da228a8be Binary files /dev/null and b/docs/images/atk-toolkit-icon.png differ diff --git a/docs/images/atk-toolkit-new-project-list.png b/docs/images/atk-toolkit-new-project-list.png new file mode 100644 index 0000000000..2db9e60b1f Binary files /dev/null and b/docs/images/atk-toolkit-new-project-list.png differ diff --git a/docs/images/azure-portal-enable-sign-in.png b/docs/images/azure-portal-enable-sign-in.png new file mode 100644 index 0000000000..b9526ccb72 Binary files /dev/null and b/docs/images/azure-portal-enable-sign-in.png differ diff --git a/docs/images/azure-portal-managed-application.png b/docs/images/azure-portal-managed-application.png new file mode 100644 index 0000000000..c43a48ced2 Binary files /dev/null and b/docs/images/azure-portal-managed-application.png differ diff --git a/docs/images/azure-portal-manifest-token-version.png b/docs/images/azure-portal-manifest-token-version.png index 99ccf0b90b..dbe0277d79 100644 Binary files a/docs/images/azure-portal-manifest-token-version.png and b/docs/images/azure-portal-manifest-token-version.png differ diff --git a/docs/images/azure-portal-manifest.png b/docs/images/azure-portal-manifest.png index b4982a33e4..e9a94b2e7a 100644 Binary files a/docs/images/azure-portal-manifest.png and b/docs/images/azure-portal-manifest.png differ diff --git a/docs/images/big-arch.gif b/docs/images/big-arch.gif deleted file mode 100644 index 9f0ae03161..0000000000 Binary files a/docs/images/big-arch.gif and /dev/null differ diff --git a/docs/images/block-on-send-subject-cc-inforbar.png b/docs/images/block-on-send-subject-cc-infobar.png similarity index 100% rename from docs/images/block-on-send-subject-cc-inforbar.png rename to docs/images/block-on-send-subject-cc-infobar.png diff --git a/docs/images/box.gif b/docs/images/box.gif deleted file mode 100644 index a0e0ca91ed..0000000000 Binary files a/docs/images/box.gif and /dev/null differ diff --git a/docs/images/bullet.gif b/docs/images/bullet.gif deleted file mode 100644 index bd7f9d235b..0000000000 Binary files a/docs/images/bullet.gif and /dev/null differ diff --git a/docs/images/caution-icon.gif b/docs/images/caution-icon.gif deleted file mode 100644 index 0f24145a12..0000000000 Binary files a/docs/images/caution-icon.gif and /dev/null differ diff --git a/docs/images/checked.png b/docs/images/checked.png deleted file mode 100644 index dc8a2c99ae..0000000000 Binary files a/docs/images/checked.png and /dev/null differ diff --git a/docs/images/collall.gif b/docs/images/collall.gif deleted file mode 100644 index 66a6f11629..0000000000 Binary files a/docs/images/collall.gif and /dev/null differ diff --git a/docs/images/collapse-all.gif b/docs/images/collapse-all.gif deleted file mode 100644 index b38b9903b1..0000000000 Binary files a/docs/images/collapse-all.gif and /dev/null differ diff --git a/docs/images/collapse.gif b/docs/images/collapse.gif deleted file mode 100644 index d57c046779..0000000000 Binary files a/docs/images/collapse.gif and /dev/null differ diff --git a/docs/images/com-preference-disable-failure.png b/docs/images/com-preference-disable-failure.png new file mode 100644 index 0000000000..8b2d56b073 Binary files /dev/null and b/docs/images/com-preference-disable-failure.png differ diff --git a/docs/images/com-preference-disable-success.png b/docs/images/com-preference-disable-success.png new file mode 100644 index 0000000000..0ee29ac2a4 Binary files /dev/null and b/docs/images/com-preference-disable-success.png differ diff --git a/docs/images/com-preference-prompt.png b/docs/images/com-preference-prompt.png new file mode 100644 index 0000000000..a9797a6bb4 Binary files /dev/null and b/docs/images/com-preference-prompt.png differ diff --git a/docs/images/copilot-agent-list.png b/docs/images/copilot-agent-list.png new file mode 100644 index 0000000000..af79f34637 Binary files /dev/null and b/docs/images/copilot-agent-list.png differ diff --git a/docs/images/copycode-highlight.gif b/docs/images/copycode-highlight.gif deleted file mode 100644 index be87230ff9..0000000000 Binary files a/docs/images/copycode-highlight.gif and /dev/null differ diff --git a/docs/images/copycode.gif b/docs/images/copycode.gif deleted file mode 100644 index 1678162660..0000000000 Binary files a/docs/images/copycode.gif and /dev/null differ diff --git a/docs/images/custom-functions-add-in-components.png b/docs/images/custom-functions-add-in-components.png new file mode 100644 index 0000000000..66167cc83a Binary files /dev/null and b/docs/images/custom-functions-add-in-components.png differ diff --git a/docs/images/custom-functions-custom-enum-autocomplete.png b/docs/images/custom-functions-custom-enum-autocomplete.png new file mode 100644 index 0000000000..8904e00da9 Binary files /dev/null and b/docs/images/custom-functions-custom-enum-autocomplete.png differ diff --git a/docs/images/custom-functions-delay-example.png b/docs/images/custom-functions-delay-example.png new file mode 100644 index 0000000000..516c30c938 Binary files /dev/null and b/docs/images/custom-functions-delay-example.png differ diff --git a/docs/images/custom-functions-dynamic-array.png b/docs/images/custom-functions-dynamic-array.png new file mode 100644 index 0000000000..cad1ecac20 Binary files /dev/null and b/docs/images/custom-functions-dynamic-array.png differ diff --git a/docs/images/custom-functions-inline-description.png b/docs/images/custom-functions-inline-description.png new file mode 100644 index 0000000000..18670f67c4 Binary files /dev/null and b/docs/images/custom-functions-inline-description.png differ diff --git a/docs/images/custom-functions-not-dynamic-array.png b/docs/images/custom-functions-not-dynamic-array.png new file mode 100644 index 0000000000..e58d3f97e9 Binary files /dev/null and b/docs/images/custom-functions-not-dynamic-array.png differ diff --git a/docs/images/data-type-basic-card-attribution.png b/docs/images/data-type-basic-card-attribution.png new file mode 100644 index 0000000000..b111b24610 Binary files /dev/null and b/docs/images/data-type-basic-card-attribution.png differ diff --git a/docs/images/data-type-basic-card-layout.png b/docs/images/data-type-basic-card-layout.png new file mode 100644 index 0000000000..525032f9a4 Binary files /dev/null and b/docs/images/data-type-basic-card-layout.png differ diff --git a/docs/images/data-type-basic-data-type-card.png b/docs/images/data-type-basic-data-type-card.png new file mode 100644 index 0000000000..4b12abce26 Binary files /dev/null and b/docs/images/data-type-basic-data-type-card.png differ diff --git a/docs/images/data-type-basic-dot-syntax.png b/docs/images/data-type-basic-dot-syntax.png new file mode 100644 index 0000000000..53fe3d97fe Binary files /dev/null and b/docs/images/data-type-basic-dot-syntax.png differ diff --git a/docs/images/data-type-basic-fields.png b/docs/images/data-type-basic-fields.png new file mode 100644 index 0000000000..c6f3fb87f0 Binary files /dev/null and b/docs/images/data-type-basic-fields.png differ diff --git a/docs/images/data-type-basic-nested-entities.png b/docs/images/data-type-basic-nested-entities.png new file mode 100644 index 0000000000..6ba145dc74 Binary files /dev/null and b/docs/images/data-type-basic-nested-entities.png differ diff --git a/docs/images/data-type-basic-provider-information.png b/docs/images/data-type-basic-provider-information.png new file mode 100644 index 0000000000..408c41c7dd Binary files /dev/null and b/docs/images/data-type-basic-provider-information.png differ diff --git a/docs/images/data-types-icon-table.png b/docs/images/data-types-icon-table.png new file mode 100644 index 0000000000..d239375554 Binary files /dev/null and b/docs/images/data-types-icon-table.png differ diff --git a/docs/images/disabled.png b/docs/images/disabled.png deleted file mode 100644 index 83e2d2eee9..0000000000 Binary files a/docs/images/disabled.png and /dev/null differ diff --git a/docs/images/dropdown-02.gif b/docs/images/dropdown-02.gif deleted file mode 100644 index 9d3bbb6e75..0000000000 Binary files a/docs/images/dropdown-02.gif and /dev/null differ diff --git a/docs/images/edge-webview2-automatic-save-passwords.png b/docs/images/edge-webview2-automatic-save-passwords.png new file mode 100644 index 0000000000..bd346a659e Binary files /dev/null and b/docs/images/edge-webview2-automatic-save-passwords.png differ diff --git a/docs/images/excel-add-in-dot-function-data-card.png b/docs/images/excel-add-in-dot-function-data-card.png new file mode 100644 index 0000000000..745dba6c37 Binary files /dev/null and b/docs/images/excel-add-in-dot-function-data-card.png differ diff --git a/docs/images/excel-add-in-dot-function-roman-numeral.png b/docs/images/excel-add-in-dot-function-roman-numeral.png new file mode 100644 index 0000000000..fcf1961db8 Binary files /dev/null and b/docs/images/excel-add-in-dot-function-roman-numeral.png differ diff --git a/docs/images/excel-add-in-dot-function.png b/docs/images/excel-add-in-dot-function.png new file mode 100644 index 0000000000..e13e7ae5f1 Binary files /dev/null and b/docs/images/excel-add-in-dot-function.png differ diff --git a/docs/images/excel-data-labels-chart-anchor-change.png b/docs/images/excel-data-labels-chart-anchor-change.png new file mode 100644 index 0000000000..6b86b0cee9 Binary files /dev/null and b/docs/images/excel-data-labels-chart-anchor-change.png differ diff --git a/docs/images/excel-data-labels-chart-callout.png b/docs/images/excel-data-labels-chart-callout.png new file mode 100644 index 0000000000..7b7ebdf570 Binary files /dev/null and b/docs/images/excel-data-labels-chart-callout.png differ diff --git a/docs/images/excel-data-labels-chart-formats.png b/docs/images/excel-data-labels-chart-formats.png new file mode 100644 index 0000000000..f3ea6f01bb Binary files /dev/null and b/docs/images/excel-data-labels-chart-formats.png differ diff --git a/docs/images/excel-data-labels-chart-leaderlines.png b/docs/images/excel-data-labels-chart-leaderlines.png new file mode 100644 index 0000000000..72a05de9e0 Binary files /dev/null and b/docs/images/excel-data-labels-chart-leaderlines.png differ diff --git a/docs/images/excel-data-labels-chart-substring.png b/docs/images/excel-data-labels-chart-substring.png new file mode 100644 index 0000000000..a256404edd Binary files /dev/null and b/docs/images/excel-data-labels-chart-substring.png differ diff --git a/docs/images/excel-data-labels-chart.png b/docs/images/excel-data-labels-chart.png new file mode 100644 index 0000000000..e1285479df Binary files /dev/null and b/docs/images/excel-data-labels-chart.png differ diff --git a/docs/images/excel-data-labels-starter-chart.png b/docs/images/excel-data-labels-starter-chart.png new file mode 100644 index 0000000000..9dea940f46 Binary files /dev/null and b/docs/images/excel-data-labels-starter-chart.png differ diff --git a/docs/images/excel-data-types-entity-card-attribution.png b/docs/images/excel-data-types-entity-card-attribution.png index f24ca4e1b2..91cad76f19 100644 Binary files a/docs/images/excel-data-types-entity-card-attribution.png and b/docs/images/excel-data-types-entity-card-attribution.png differ diff --git a/docs/images/excel-data-types-entity-card-gumbo.png b/docs/images/excel-data-types-entity-card-gumbo.png index 864f02c99b..9b851ff2b0 100644 Binary files a/docs/images/excel-data-types-entity-card-gumbo.png and b/docs/images/excel-data-types-entity-card-gumbo.png differ diff --git a/docs/images/excel-data-types-entity-card-properties-gumbo.png b/docs/images/excel-data-types-entity-card-properties-gumbo.png index 100195e2ae..7f3928986a 100644 Binary files a/docs/images/excel-data-types-entity-card-properties-gumbo.png and b/docs/images/excel-data-types-entity-card-properties-gumbo.png differ diff --git a/docs/images/excel-data-types-entity-card-properties.png b/docs/images/excel-data-types-entity-card-properties.png deleted file mode 100644 index 40eb3025b5..0000000000 Binary files a/docs/images/excel-data-types-entity-card-properties.png and /dev/null differ diff --git a/docs/images/excel-data-types-entity-card-property-metadata.png b/docs/images/excel-data-types-entity-card-property-metadata.png index 77514c0ee0..2912ca38de 100644 Binary files a/docs/images/excel-data-types-entity-card-property-metadata.png and b/docs/images/excel-data-types-entity-card-property-metadata.png differ diff --git a/docs/images/excel-data-types-entity-card-sections-gumbo.png b/docs/images/excel-data-types-entity-card-sections-gumbo.png index 4af35f4f81..2f31e84003 100644 Binary files a/docs/images/excel-data-types-entity-card-sections-gumbo.png and b/docs/images/excel-data-types-entity-card-sections-gumbo.png differ diff --git a/docs/images/excel-data-types-entity-card-sections.png b/docs/images/excel-data-types-entity-card-sections.png deleted file mode 100644 index b4da3d7977..0000000000 Binary files a/docs/images/excel-data-types-entity-card-sections.png and /dev/null differ diff --git a/docs/images/excel-data-types-entity-card-tofu.png b/docs/images/excel-data-types-entity-card-tofu.png deleted file mode 100644 index 47aa4ba011..0000000000 Binary files a/docs/images/excel-data-types-entity-card-tofu.png and /dev/null differ diff --git a/docs/images/excel-data-types-linked-entity-workflow.png b/docs/images/excel-data-types-linked-entity-workflow.png new file mode 100644 index 0000000000..e2c3064b5a Binary files /dev/null and b/docs/images/excel-data-types-linked-entity-workflow.png differ diff --git a/docs/images/excel-data-types-reference-method-autocomplete.png b/docs/images/excel-data-types-reference-method-autocomplete.png new file mode 100644 index 0000000000..e40b59320b Binary files /dev/null and b/docs/images/excel-data-types-reference-method-autocomplete.png differ diff --git a/docs/images/excel-data-types-reference-method-optional-parameters.png b/docs/images/excel-data-types-reference-method-optional-parameters.png new file mode 100644 index 0000000000..38738f5298 Binary files /dev/null and b/docs/images/excel-data-types-reference-method-optional-parameters.png differ diff --git a/docs/images/excel-data-types-reference-method-optional-ranges.png b/docs/images/excel-data-types-reference-method-optional-ranges.png new file mode 100644 index 0000000000..af1496cf64 Binary files /dev/null and b/docs/images/excel-data-types-reference-method-optional-ranges.png differ diff --git a/docs/images/excel-data-types-reference-method-repeating-parameters.png b/docs/images/excel-data-types-reference-method-repeating-parameters.png new file mode 100644 index 0000000000..9cb7a39934 Binary files /dev/null and b/docs/images/excel-data-types-reference-method-repeating-parameters.png differ diff --git a/docs/images/excel-formula-value-preview.png b/docs/images/excel-formula-value-preview.png new file mode 100644 index 0000000000..c522de099e Binary files /dev/null and b/docs/images/excel-formula-value-preview.png differ diff --git a/docs/images/excel-geography-linked-data-type-seattle.png b/docs/images/excel-geography-linked-data-type-seattle.png new file mode 100644 index 0000000000..57569fd573 Binary files /dev/null and b/docs/images/excel-geography-linked-data-type-seattle.png differ diff --git a/docs/images/excel-geography-seattle-dot-syntax.png b/docs/images/excel-geography-seattle-dot-syntax.png new file mode 100644 index 0000000000..363722c917 Binary files /dev/null and b/docs/images/excel-geography-seattle-dot-syntax.png differ diff --git a/docs/images/excel-gridlines.png b/docs/images/excel-gridlines.png new file mode 100644 index 0000000000..c0852e7e07 Binary files /dev/null and b/docs/images/excel-gridlines.png differ diff --git a/docs/images/excel-heading-label.png b/docs/images/excel-heading-label.png new file mode 100644 index 0000000000..8b480c078c Binary files /dev/null and b/docs/images/excel-heading-label.png differ diff --git a/docs/images/excel-range-checkbox-table.png b/docs/images/excel-range-checkbox-table.png new file mode 100644 index 0000000000..3ddea158a1 Binary files /dev/null and b/docs/images/excel-range-checkbox-table.png differ diff --git a/docs/images/excel-web-add-in-permission-error.png b/docs/images/excel-web-add-in-permission-error.png new file mode 100644 index 0000000000..4ba4a56d2f Binary files /dev/null and b/docs/images/excel-web-add-in-permission-error.png differ diff --git a/docs/images/expall.gif b/docs/images/expall.gif deleted file mode 100644 index 1a91b12735..0000000000 Binary files a/docs/images/expall.gif and /dev/null differ diff --git a/docs/images/expand-all.gif b/docs/images/expand-all.gif deleted file mode 100644 index c7061b5660..0000000000 Binary files a/docs/images/expand-all.gif and /dev/null differ diff --git a/docs/images/filter-1a.gif b/docs/images/filter-1a.gif deleted file mode 100644 index 8a2f9b58a6..0000000000 Binary files a/docs/images/filter-1a.gif and /dev/null differ diff --git a/docs/images/filter-1c.gif b/docs/images/filter-1c.gif deleted file mode 100644 index 49de223fd4..0000000000 Binary files a/docs/images/filter-1c.gif and /dev/null differ diff --git a/docs/images/footer.gif b/docs/images/footer.gif deleted file mode 100644 index 16bfa5e6db..0000000000 Binary files a/docs/images/footer.gif and /dev/null differ diff --git a/docs/images/get-app-cmdlet-bing-maps-manifestxml.png b/docs/images/get-app-cmdlet-bing-maps-manifestxml.png new file mode 100644 index 0000000000..41d02545c2 Binary files /dev/null and b/docs/images/get-app-cmdlet-bing-maps-manifestxml.png differ diff --git a/docs/images/get-app-cmdlet-bing-maps.png b/docs/images/get-app-cmdlet-bing-maps.png new file mode 100644 index 0000000000..4e32154cc2 Binary files /dev/null and b/docs/images/get-app-cmdlet-bing-maps.png differ diff --git a/docs/images/get-app-cmdlet-providername.png b/docs/images/get-app-cmdlet-providername.png new file mode 100644 index 0000000000..bff22c6afe Binary files /dev/null and b/docs/images/get-app-cmdlet-providername.png differ diff --git a/docs/images/gettingstarted-fast.gif b/docs/images/gettingstarted-fast.gif deleted file mode 100644 index 85f2a84fcf..0000000000 Binary files a/docs/images/gettingstarted-fast.gif and /dev/null differ diff --git a/docs/images/gradient.gif b/docs/images/gradient.gif deleted file mode 100644 index 0179762417..0000000000 Binary files a/docs/images/gradient.gif and /dev/null differ diff --git a/docs/images/greencheck.gif b/docs/images/greencheck.gif deleted file mode 100644 index 4ba17510db..0000000000 Binary files a/docs/images/greencheck.gif and /dev/null differ diff --git a/docs/images/greycheck.gif b/docs/images/greycheck.gif deleted file mode 100644 index adb8fa1e68..0000000000 Binary files a/docs/images/greycheck.gif and /dev/null differ diff --git a/docs/images/index/logo-office.png b/docs/images/index/logo-office.png new file mode 100644 index 0000000000..c1c375f2df Binary files /dev/null and b/docs/images/index/logo-office.png differ diff --git a/docs/images/kw.gif b/docs/images/kw.gif deleted file mode 100644 index 9f0ae03161..0000000000 Binary files a/docs/images/kw.gif and /dev/null differ diff --git a/docs/images/last-child.gif b/docs/images/last-child.gif deleted file mode 100644 index 0b9af7e88d..0000000000 Binary files a/docs/images/last-child.gif and /dev/null differ diff --git a/docs/images/load-hover.gif b/docs/images/load-hover.gif deleted file mode 100644 index c7740c189a..0000000000 Binary files a/docs/images/load-hover.gif and /dev/null differ diff --git a/docs/images/load.gif b/docs/images/load.gif deleted file mode 100644 index 5035e4f9c5..0000000000 Binary files a/docs/images/load.gif and /dev/null differ diff --git a/docs/images/m365-app-excel.png b/docs/images/m365-app-excel.png new file mode 100644 index 0000000000..b3567f84fd Binary files /dev/null and b/docs/images/m365-app-excel.png differ diff --git a/docs/images/m365-app-office.png b/docs/images/m365-app-office.png new file mode 100644 index 0000000000..a085548aa4 Binary files /dev/null and b/docs/images/m365-app-office.png differ diff --git a/docs/images/m365-app-onenote.png b/docs/images/m365-app-onenote.png new file mode 100644 index 0000000000..f870bfe0f5 Binary files /dev/null and b/docs/images/m365-app-onenote.png differ diff --git a/docs/images/m365-app-outlook.png b/docs/images/m365-app-outlook.png new file mode 100644 index 0000000000..6e69063cee Binary files /dev/null and b/docs/images/m365-app-outlook.png differ diff --git a/docs/images/m365-app-powerpoint.png b/docs/images/m365-app-powerpoint.png new file mode 100644 index 0000000000..0759ae791d Binary files /dev/null and b/docs/images/m365-app-powerpoint.png differ diff --git a/docs/images/m365-app-word.png b/docs/images/m365-app-word.png new file mode 100644 index 0000000000..e0af07c566 Binary files /dev/null and b/docs/images/m365-app-word.png differ diff --git a/docs/images/microsoft-365-insider.png b/docs/images/microsoft-365-insider.png new file mode 100644 index 0000000000..b6afd3cb0e Binary files /dev/null and b/docs/images/microsoft-365-insider.png differ diff --git a/docs/images/note.gif b/docs/images/note.gif deleted file mode 100644 index 54c6ae65b0..0000000000 Binary files a/docs/images/note.gif and /dev/null differ diff --git a/docs/images/office-add-ins-development-kit-samplepage-excelquickstart.png b/docs/images/office-add-ins-development-kit-samplepage-excelquickstart.png new file mode 100644 index 0000000000..8f82afe87f Binary files /dev/null and b/docs/images/office-add-ins-development-kit-samplepage-excelquickstart.png differ diff --git a/docs/images/office-add-ins-development-kit-samplepage-wordquickstart.png b/docs/images/office-add-ins-development-kit-samplepage-wordquickstart.png new file mode 100644 index 0000000000..1354555a2c Binary files /dev/null and b/docs/images/office-add-ins-development-kit-samplepage-wordquickstart.png differ diff --git a/docs/images/office-add-ins-lifecycle-step-1-plan.png b/docs/images/office-add-ins-lifecycle-step-1-plan.png new file mode 100644 index 0000000000..31cc50dc3e Binary files /dev/null and b/docs/images/office-add-ins-lifecycle-step-1-plan.png differ diff --git a/docs/images/office-add-ins-lifecycle-step-2-develop.png b/docs/images/office-add-ins-lifecycle-step-2-develop.png new file mode 100644 index 0000000000..c20dffd4b3 Binary files /dev/null and b/docs/images/office-add-ins-lifecycle-step-2-develop.png differ diff --git a/docs/images/office-add-ins-lifecycle-step-3-test-and-debug.png b/docs/images/office-add-ins-lifecycle-step-3-test-and-debug.png new file mode 100644 index 0000000000..052018874f Binary files /dev/null and b/docs/images/office-add-ins-lifecycle-step-3-test-and-debug.png differ diff --git a/docs/images/office-add-ins-lifecycle-step-4-publish.png b/docs/images/office-add-ins-lifecycle-step-4-publish.png new file mode 100644 index 0000000000..8561728af7 Binary files /dev/null and b/docs/images/office-add-ins-lifecycle-step-4-publish.png differ diff --git a/docs/images/office-add-ins-lifecycle-step-5-reference.png b/docs/images/office-add-ins-lifecycle-step-5-reference.png new file mode 100644 index 0000000000..a535b1fed2 Binary files /dev/null and b/docs/images/office-add-ins-lifecycle-step-5-reference.png differ diff --git a/docs/images/office-add-ins-my-account.png b/docs/images/office-add-ins-my-account.png deleted file mode 100644 index b174f21e03..0000000000 Binary files a/docs/images/office-add-ins-my-account.png and /dev/null differ diff --git a/docs/images/office-insiders-label.png b/docs/images/office-insiders-label.png deleted file mode 100644 index fec0366f66..0000000000 Binary files a/docs/images/office-insiders-label.png and /dev/null differ diff --git a/docs/images/office-loopback-exemption.png b/docs/images/office-loopback-exemption.png new file mode 100644 index 0000000000..40f17f4f4e Binary files /dev/null and b/docs/images/office-loopback-exemption.png differ diff --git a/docs/images/outlook-encryption-placeholder-message.png b/docs/images/outlook-encryption-placeholder-message.png new file mode 100644 index 0000000000..3a9d7ff8e4 Binary files /dev/null and b/docs/images/outlook-encryption-placeholder-message.png differ diff --git a/docs/images/outlook-error-notification.png b/docs/images/outlook-error-notification.png new file mode 100644 index 0000000000..8df883edcb Binary files /dev/null and b/docs/images/outlook-error-notification.png differ diff --git a/docs/images/outlook-images-still-loading-error.png b/docs/images/outlook-images-still-loading-error.png new file mode 100644 index 0000000000..42fa844206 Binary files /dev/null and b/docs/images/outlook-images-still-loading-error.png differ diff --git a/docs/images/outlook-informational-notification.png b/docs/images/outlook-informational-notification.png new file mode 100644 index 0000000000..e594518b79 Binary files /dev/null and b/docs/images/outlook-informational-notification.png differ diff --git a/docs/images/outlook-insight-notification.png b/docs/images/outlook-insight-notification.png new file mode 100644 index 0000000000..39a9dfdee7 Binary files /dev/null and b/docs/images/outlook-insight-notification.png differ diff --git a/docs/images/outlook-item-switch-block.png b/docs/images/outlook-item-switch-block.png deleted file mode 100644 index da9b10f09c..0000000000 Binary files a/docs/images/outlook-item-switch-block.png and /dev/null differ diff --git a/docs/images/outlook-item-switch-prompt-user.png b/docs/images/outlook-item-switch-prompt-user.png deleted file mode 100644 index dc0eadf3c6..0000000000 Binary files a/docs/images/outlook-item-switch-prompt-user.png and /dev/null differ diff --git a/docs/images/outlook-item-switch-web-block.png b/docs/images/outlook-item-switch-web-block.png new file mode 100644 index 0000000000..6041e6a9eb Binary files /dev/null and b/docs/images/outlook-item-switch-web-block.png differ diff --git a/docs/images/outlook-item-switch-web-prompt-user.png b/docs/images/outlook-item-switch-web-prompt-user.png new file mode 100644 index 0000000000..bc2fbd64bf Binary files /dev/null and b/docs/images/outlook-item-switch-web-prompt-user.png differ diff --git a/docs/images/outlook-item-switch-win32-block.png b/docs/images/outlook-item-switch-win32-block.png new file mode 100644 index 0000000000..50761e29f3 Binary files /dev/null and b/docs/images/outlook-item-switch-win32-block.png differ diff --git a/docs/images/outlook-item-switch-win32-prompt-user.png b/docs/images/outlook-item-switch-win32-prompt-user.png new file mode 100644 index 0000000000..533fb457fe Binary files /dev/null and b/docs/images/outlook-item-switch-win32-prompt-user.png differ diff --git a/docs/images/outlook-multi-select.png b/docs/images/outlook-multi-select.png index 5fde0b1464..b00957fa82 100644 Binary files a/docs/images/outlook-multi-select.png and b/docs/images/outlook-multi-select.png differ diff --git a/docs/images/outlook-notification.png b/docs/images/outlook-notification.png new file mode 100644 index 0000000000..e8bee26808 Binary files /dev/null and b/docs/images/outlook-notification.png differ diff --git a/docs/images/outlook-progress-notification.png b/docs/images/outlook-progress-notification.png new file mode 100644 index 0000000000..f08236c506 Binary files /dev/null and b/docs/images/outlook-progress-notification.png differ diff --git a/docs/images/outlook-smart-alerts-custom-button-and-override.png b/docs/images/outlook-smart-alerts-custom-button-and-override.png new file mode 100644 index 0000000000..743ce2eb94 Binary files /dev/null and b/docs/images/outlook-smart-alerts-custom-button-and-override.png differ diff --git a/docs/images/outlook-smart-alerts-custom-take-action.png b/docs/images/outlook-smart-alerts-custom-take-action.png new file mode 100644 index 0000000000..ec7c485de2 Binary files /dev/null and b/docs/images/outlook-smart-alerts-custom-take-action.png differ diff --git a/docs/images/outlook-smart-alerts-dont-send.png b/docs/images/outlook-smart-alerts-dont-send.png new file mode 100644 index 0000000000..216597fbee Binary files /dev/null and b/docs/images/outlook-smart-alerts-dont-send.png differ diff --git a/docs/images/outlook-smart-alerts-item-switch-dialog-web.png b/docs/images/outlook-smart-alerts-item-switch-dialog-web.png deleted file mode 100644 index 00384b6fd4..0000000000 Binary files a/docs/images/outlook-smart-alerts-item-switch-dialog-web.png and /dev/null differ diff --git a/docs/images/outlook-smart-alerts-take-action.png b/docs/images/outlook-smart-alerts-take-action.png new file mode 100644 index 0000000000..7fb45c732d Binary files /dev/null and b/docs/images/outlook-smart-alerts-take-action.png differ diff --git a/docs/images/outlook-win-smart-alerts-take-action.png b/docs/images/outlook-win-smart-alerts-take-action.png new file mode 100644 index 0000000000..c18c02ecde Binary files /dev/null and b/docs/images/outlook-win-smart-alerts-take-action.png differ diff --git a/docs/images/pencils.gif b/docs/images/pencils.gif deleted file mode 100644 index 000dcb42a0..0000000000 Binary files a/docs/images/pencils.gif and /dev/null differ diff --git a/docs/images/powerpoint-bind-shapes.png b/docs/images/powerpoint-bind-shapes.png new file mode 100644 index 0000000000..c2b0fb25fb Binary files /dev/null and b/docs/images/powerpoint-bind-shapes.png differ diff --git a/docs/images/powerpoint-steps-to-bind-shape.png b/docs/images/powerpoint-steps-to-bind-shape.png new file mode 100644 index 0000000000..0f2c0ed1da Binary files /dev/null and b/docs/images/powerpoint-steps-to-bind-shape.png differ diff --git a/docs/images/powerpoint-table-alignment-settings.png b/docs/images/powerpoint-table-alignment-settings.png new file mode 100644 index 0000000000..b280480813 Binary files /dev/null and b/docs/images/powerpoint-table-alignment-settings.png differ diff --git a/docs/images/powerpoint-table-empty.png b/docs/images/powerpoint-table-empty.png new file mode 100644 index 0000000000..011a5cc4bd Binary files /dev/null and b/docs/images/powerpoint-table-empty.png differ diff --git a/docs/images/powerpoint-table-height-width-settings.png b/docs/images/powerpoint-table-height-width-settings.png new file mode 100644 index 0000000000..9010c0a346 Binary files /dev/null and b/docs/images/powerpoint-table-height-width-settings.png differ diff --git a/docs/images/powerpoint-table-merged-cells.png b/docs/images/powerpoint-table-merged-cells.png new file mode 100644 index 0000000000..019f3964d0 Binary files /dev/null and b/docs/images/powerpoint-table-merged-cells.png differ diff --git a/docs/images/powerpoint-table-numbers.png b/docs/images/powerpoint-table-numbers.png new file mode 100644 index 0000000000..f444407768 Binary files /dev/null and b/docs/images/powerpoint-table-numbers.png differ diff --git a/docs/images/powerpoint-table-specific-cell-format.png b/docs/images/powerpoint-table-specific-cell-format.png new file mode 100644 index 0000000000..20c04fbfa0 Binary files /dev/null and b/docs/images/powerpoint-table-specific-cell-format.png differ diff --git a/docs/images/powerpoint-table-uniform-cell-format.png b/docs/images/powerpoint-table-uniform-cell-format.png new file mode 100644 index 0000000000..2bdb37bb36 Binary files /dev/null and b/docs/images/powerpoint-table-uniform-cell-format.png differ diff --git a/docs/images/privclass.gif b/docs/images/privclass.gif deleted file mode 100644 index 083c53429c..0000000000 Binary files a/docs/images/privclass.gif and /dev/null differ diff --git a/docs/images/privdelegate.gif b/docs/images/privdelegate.gif deleted file mode 100644 index d3aa8a65ef..0000000000 Binary files a/docs/images/privdelegate.gif and /dev/null differ diff --git a/docs/images/privenum.gif b/docs/images/privenum.gif deleted file mode 100644 index 0db2349874..0000000000 Binary files a/docs/images/privenum.gif and /dev/null differ diff --git a/docs/images/privenumeration.gif b/docs/images/privenumeration.gif deleted file mode 100644 index 0db2349874..0000000000 Binary files a/docs/images/privenumeration.gif and /dev/null differ diff --git a/docs/images/privevent.gif b/docs/images/privevent.gif deleted file mode 100644 index 621e71f473..0000000000 Binary files a/docs/images/privevent.gif and /dev/null differ diff --git a/docs/images/privextension.gif b/docs/images/privextension.gif deleted file mode 100644 index 949ddf0669..0000000000 Binary files a/docs/images/privextension.gif and /dev/null differ diff --git a/docs/images/privfield.gif b/docs/images/privfield.gif deleted file mode 100644 index 14120522aa..0000000000 Binary files a/docs/images/privfield.gif and /dev/null differ diff --git a/docs/images/privinterface.gif b/docs/images/privinterface.gif deleted file mode 100644 index dddf1a703e..0000000000 Binary files a/docs/images/privinterface.gif and /dev/null differ diff --git a/docs/images/privmethod.gif b/docs/images/privmethod.gif deleted file mode 100644 index ef9baa4651..0000000000 Binary files a/docs/images/privmethod.gif and /dev/null differ diff --git a/docs/images/privproperty.gif b/docs/images/privproperty.gif deleted file mode 100644 index 8062b4a72b..0000000000 Binary files a/docs/images/privproperty.gif and /dev/null differ diff --git a/docs/images/privstructure.gif b/docs/images/privstructure.gif deleted file mode 100644 index a2e5f8241f..0000000000 Binary files a/docs/images/privstructure.gif and /dev/null differ diff --git a/docs/images/protclass.gif b/docs/images/protclass.gif deleted file mode 100644 index 02944723a6..0000000000 Binary files a/docs/images/protclass.gif and /dev/null differ diff --git a/docs/images/protdelegate.gif b/docs/images/protdelegate.gif deleted file mode 100644 index 9047a1e326..0000000000 Binary files a/docs/images/protdelegate.gif and /dev/null differ diff --git a/docs/images/protenum.gif b/docs/images/protenum.gif deleted file mode 100644 index 9ba37e350c..0000000000 Binary files a/docs/images/protenum.gif and /dev/null differ diff --git a/docs/images/protenumeration.gif b/docs/images/protenumeration.gif deleted file mode 100644 index cc96bb6359..0000000000 Binary files a/docs/images/protenumeration.gif and /dev/null differ diff --git a/docs/images/protevent.gif b/docs/images/protevent.gif deleted file mode 100644 index 061d0f86fe..0000000000 Binary files a/docs/images/protevent.gif and /dev/null differ diff --git a/docs/images/protextension.gif b/docs/images/protextension.gif deleted file mode 100644 index 38199bea25..0000000000 Binary files a/docs/images/protextension.gif and /dev/null differ diff --git a/docs/images/protfield.gif b/docs/images/protfield.gif deleted file mode 100644 index 3dd0310ac2..0000000000 Binary files a/docs/images/protfield.gif and /dev/null differ diff --git a/docs/images/protinterface.gif b/docs/images/protinterface.gif deleted file mode 100644 index 522e7953aa..0000000000 Binary files a/docs/images/protinterface.gif and /dev/null differ diff --git a/docs/images/protmethod.gif b/docs/images/protmethod.gif deleted file mode 100644 index 2b3467229f..0000000000 Binary files a/docs/images/protmethod.gif and /dev/null differ diff --git a/docs/images/protoperator.gif b/docs/images/protoperator.gif deleted file mode 100644 index cd9e638ec9..0000000000 Binary files a/docs/images/protoperator.gif and /dev/null differ diff --git a/docs/images/protproperty.gif b/docs/images/protproperty.gif deleted file mode 100644 index 0f41ac3aaa..0000000000 Binary files a/docs/images/protproperty.gif and /dev/null differ diff --git a/docs/images/protstructure.gif b/docs/images/protstructure.gif deleted file mode 100644 index af356a1db0..0000000000 Binary files a/docs/images/protstructure.gif and /dev/null differ diff --git a/docs/images/pubclass.gif b/docs/images/pubclass.gif deleted file mode 100644 index dac8a76682..0000000000 Binary files a/docs/images/pubclass.gif and /dev/null differ diff --git a/docs/images/pubdelegate.gif b/docs/images/pubdelegate.gif deleted file mode 100644 index e336e5ccab..0000000000 Binary files a/docs/images/pubdelegate.gif and /dev/null differ diff --git a/docs/images/pubenum.gif b/docs/images/pubenum.gif deleted file mode 100644 index a6cb355ff7..0000000000 Binary files a/docs/images/pubenum.gif and /dev/null differ diff --git a/docs/images/pubenumeration.gif b/docs/images/pubenumeration.gif deleted file mode 100644 index a6cb355ff7..0000000000 Binary files a/docs/images/pubenumeration.gif and /dev/null differ diff --git a/docs/images/pubevent.gif b/docs/images/pubevent.gif deleted file mode 100644 index cc77aa8f37..0000000000 Binary files a/docs/images/pubevent.gif and /dev/null differ diff --git a/docs/images/pubextension.gif b/docs/images/pubextension.gif deleted file mode 100644 index b7e83d87dc..0000000000 Binary files a/docs/images/pubextension.gif and /dev/null differ diff --git a/docs/images/pubfield.gif b/docs/images/pubfield.gif deleted file mode 100644 index 590fbfc60c..0000000000 Binary files a/docs/images/pubfield.gif and /dev/null differ diff --git a/docs/images/pubinterface.gif b/docs/images/pubinterface.gif deleted file mode 100644 index 1a0038413e..0000000000 Binary files a/docs/images/pubinterface.gif and /dev/null differ diff --git a/docs/images/pubmethod.gif b/docs/images/pubmethod.gif deleted file mode 100644 index 4e61c9ff19..0000000000 Binary files a/docs/images/pubmethod.gif and /dev/null differ diff --git a/docs/images/puboperator.gif b/docs/images/puboperator.gif deleted file mode 100644 index ebc8d6a3ee..0000000000 Binary files a/docs/images/puboperator.gif and /dev/null differ diff --git a/docs/images/pubproperty.gif b/docs/images/pubproperty.gif deleted file mode 100644 index 074b71a23e..0000000000 Binary files a/docs/images/pubproperty.gif and /dev/null differ diff --git a/docs/images/pubstructure.gif b/docs/images/pubstructure.gif deleted file mode 100644 index 6210d36331..0000000000 Binary files a/docs/images/pubstructure.gif and /dev/null differ diff --git a/docs/images/requirements1a.gif b/docs/images/requirements1a.gif deleted file mode 100644 index 3b08793895..0000000000 Binary files a/docs/images/requirements1a.gif and /dev/null differ diff --git a/docs/images/requirements1c.gif b/docs/images/requirements1c.gif deleted file mode 100644 index d62bda3b59..0000000000 Binary files a/docs/images/requirements1c.gif and /dev/null differ diff --git a/docs/images/save-hover.gif b/docs/images/save-hover.gif deleted file mode 100644 index 7b62e923d1..0000000000 Binary files a/docs/images/save-hover.gif and /dev/null differ diff --git a/docs/images/save.gif b/docs/images/save.gif deleted file mode 100644 index 0c82243482..0000000000 Binary files a/docs/images/save.gif and /dev/null differ diff --git a/docs/images/script-lab-error-exchange-token.png b/docs/images/script-lab-error-exchange-token.png new file mode 100644 index 0000000000..d688c3098c Binary files /dev/null and b/docs/images/script-lab-error-exchange-token.png differ diff --git a/docs/images/script-lab-menu.png b/docs/images/script-lab-menu.png new file mode 100644 index 0000000000..a01f467b1c Binary files /dev/null and b/docs/images/script-lab-menu.png differ diff --git a/docs/images/script-lab-run-code.png b/docs/images/script-lab-run-code.png new file mode 100644 index 0000000000..5c5e116b65 Binary files /dev/null and b/docs/images/script-lab-run-code.png differ diff --git a/docs/images/script-lab-select-backstage-icon.png b/docs/images/script-lab-select-backstage-icon.png new file mode 100644 index 0000000000..4480a3ea2c Binary files /dev/null and b/docs/images/script-lab-select-backstage-icon.png differ diff --git a/docs/images/script-lab-select-user-identity-token-snippet.png b/docs/images/script-lab-select-user-identity-token-snippet.png new file mode 100644 index 0000000000..a7f567a28e Binary files /dev/null and b/docs/images/script-lab-select-user-identity-token-snippet.png differ diff --git a/docs/images/script-lab-successful-exchange-token.png b/docs/images/script-lab-successful-exchange-token.png new file mode 100644 index 0000000000..029d1b7020 Binary files /dev/null and b/docs/images/script-lab-successful-exchange-token.png differ diff --git a/docs/images/security.gif b/docs/images/security.gif deleted file mode 100644 index b663dbea05..0000000000 Binary files a/docs/images/security.gif and /dev/null differ diff --git a/docs/images/seealso1a.gif b/docs/images/seealso1a.gif deleted file mode 100644 index 7a01e1de8f..0000000000 Binary files a/docs/images/seealso1a.gif and /dev/null differ diff --git a/docs/images/seealso1c.gif b/docs/images/seealso1c.gif deleted file mode 100644 index 84f79e71f4..0000000000 Binary files a/docs/images/seealso1c.gif and /dev/null differ diff --git a/docs/images/spam-reporting-progress-notification.png b/docs/images/spam-reporting-progress-notification.png new file mode 100644 index 0000000000..dc83235de2 Binary files /dev/null and b/docs/images/spam-reporting-progress-notification.png differ diff --git a/docs/images/spam-reporting-suppress-dialog.png b/docs/images/spam-reporting-suppress-dialog.png new file mode 100644 index 0000000000..5f144e2b62 Binary files /dev/null and b/docs/images/spam-reporting-suppress-dialog.png differ diff --git a/docs/images/static.gif b/docs/images/static.gif deleted file mode 100644 index d3309435b6..0000000000 Binary files a/docs/images/static.gif and /dev/null differ diff --git a/docs/images/teams-toolkit-create-office-import-capability.png b/docs/images/teams-toolkit-create-office-import-capability.png new file mode 100644 index 0000000000..c9e3676994 Binary files /dev/null and b/docs/images/teams-toolkit-create-office-import-capability.png differ diff --git a/docs/images/teams-toolkit-create-office-task-pane-capability.png b/docs/images/teams-toolkit-create-office-task-pane-capability.png new file mode 100644 index 0000000000..9e8d0e6262 Binary files /dev/null and b/docs/images/teams-toolkit-create-office-task-pane-capability.png differ diff --git a/docs/images/teams-toolkit-create-outlook-add-in.png b/docs/images/teams-toolkit-create-outlook-add-in.png deleted file mode 100644 index 9ddd42a92b..0000000000 Binary files a/docs/images/teams-toolkit-create-outlook-add-in.png and /dev/null differ diff --git a/docs/images/teams-toolkit-create-outlook-task-pane-capability.png b/docs/images/teams-toolkit-create-outlook-task-pane-capability.png deleted file mode 100644 index 537af1445e..0000000000 Binary files a/docs/images/teams-toolkit-create-outlook-task-pane-capability.png and /dev/null differ diff --git a/docs/images/teams-toolkit-icon.png b/docs/images/teams-toolkit-icon.png deleted file mode 100644 index d69abf39ed..0000000000 Binary files a/docs/images/teams-toolkit-icon.png and /dev/null differ diff --git a/docs/images/unchecked.png b/docs/images/unchecked.png deleted file mode 100644 index b96b217e22..0000000000 Binary files a/docs/images/unchecked.png and /dev/null differ diff --git a/docs/images/word-compatibility-mode.png b/docs/images/word-compatibility-mode.png new file mode 100644 index 0000000000..fa7230b2d5 Binary files /dev/null and b/docs/images/word-compatibility-mode.png differ diff --git a/docs/images/xna.gif b/docs/images/xna.gif deleted file mode 100644 index 9e6a9d4bd9..0000000000 Binary files a/docs/images/xna.gif and /dev/null differ diff --git a/docs/images/yo-office-project-type-prompt.png b/docs/images/yo-office-project-type-prompt.png index 3c7e18445c..c9b494995e 100644 Binary files a/docs/images/yo-office-project-type-prompt.png and b/docs/images/yo-office-project-type-prompt.png differ diff --git a/docs/images/zztest.png b/docs/images/zztest.png deleted file mode 100644 index b45e015b52..0000000000 Binary files a/docs/images/zztest.png and /dev/null differ diff --git a/docs/includes/alert-use-https.md b/docs/includes/alert-use-https.md index 9e2795902f..db1df17185 100644 --- a/docs/includes/alert-use-https.md +++ b/docs/includes/alert-use-https.md @@ -1,2 +1,9 @@ > [!NOTE] -> Office Add-ins should use HTTPS, not HTTP, even while you're developing. If you're prompted to install a certificate after you run one of the following commands, accept the prompt to install the certificate that the Yeoman generator provides. You may also have to run your command prompt or terminal as an administrator for the changes to be made. +> +> - Office Add-ins should use HTTPS, not HTTP, even while you're developing. If you're prompted to install a certificate after you run one of the following commands, accept the prompt to install the certificate that the Yeoman generator provides. You may also have to run your command prompt or terminal as an administrator for the changes to be made. +> +> - If this is your first time developing an Office Add-in on your machine, you may be prompted in the command line to grant Microsoft Edge WebView a loopback exemption ("Allow localhost loopback for Microsoft Edge WebView?"). When prompted, enter `Y` to allow the exemption. Note that you'll need administrator privileges to allow the exemption. Once allowed, you shouldn't be prompted for an exemption when you sideload Office Add-ins in the future (unless you remove the exemption from your machine). To learn more, see ["We can't open this add-in from localhost" when loading an Office Add-in or using Fiddler](/office/troubleshoot/office-suite-issues/cannot-open-add-in-from-localhost). +> +> :::image type="content" source="../images/office-loopback-exemption.png" alt-text="The prompt in the command line to allow Microsoft Edge WebView a loopback exemption."::: +> +> - When you first use Yeoman generator to develop an Office Add-in, your default browser opens a window where you'll be prompted to sign in to your Microsoft 365 account. If a sign-in window doesn't appear and you encounter a sideloading or login timeout error, run `atk auth login m365`. diff --git a/docs/includes/appsource-enterprise.md b/docs/includes/appsource-enterprise.md index 827b439bd8..5ab5db3a77 100644 --- a/docs/includes/appsource-enterprise.md +++ b/docs/includes/appsource-enterprise.md @@ -1 +1 @@ -If your add-in targets larger organizations and enterprises, several AppSource requirements differ from those of a general commercial marketplace add-in. For more information, see the [submission FAQ](/partner-center/marketplace-offers/appsource-submission-faq#if-my-app-targets-enterprises--how-does-that-affect-my-submission-). \ No newline at end of file +If your add-in targets larger organizations and enterprises, several Microsoft Marketplace requirements differ from those of a general commercial marketplace add-in. For more information, see the [submission FAQ](/partner-center/marketplace-offers/appsource-submission-faq#if-my-app-targets-enterprises--how-does-that-affect-my-submission-). \ No newline at end of file diff --git a/docs/includes/auth-property-warning-note.md b/docs/includes/auth-property-warning-note.md new file mode 100644 index 0000000000..dd49e8c18a --- /dev/null +++ b/docs/includes/auth-property-warning-note.md @@ -0,0 +1,2 @@ +> [!NOTE] +> You may get a validation error from the plugin JSON that says you need an "auth" property. You should ignore this error. Your agent will work fine without that property. \ No newline at end of file diff --git a/docs/includes/auto-open-webview2-dev-tools.md b/docs/includes/auto-open-webview2-dev-tools.md new file mode 100644 index 0000000000..1a4ff7bd56 --- /dev/null +++ b/docs/includes/auto-open-webview2-dev-tools.md @@ -0,0 +1,10 @@ +To debug your add-in’s initialization sequence, configure your environment so that Microsoft WebView2 (Chromium-based) developer tools automatically open when the add-in launches. + +1. Close the Office application where you plan to debug the add-in. +1. Set the `WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS` environment variable to include the value `--auto-open-devtools-for-tabs`. +1. Open the Office application. +1. Run the add-in. +1. The Microsoft Edge (Chromium-based) developer tools should automatically open. Use the tool the same as you would when debugging a task pane, as specified in [Debug a task pane add-in using Microsoft Edge (Chromium-based) developer tools](../testing/debug-add-ins-using-devtools-edge-chromium.md#debug-a-task-pane-add-in-using-microsoft-edge-chromium-based-developer-tools). + + > [!NOTE] + > You may see other instances of the Microsoft Edge (Chromium-based) developer tool auto-opening since this environment variable will affect all WebView2 instances in your system. diff --git a/docs/includes/calendar-availability.md b/docs/includes/calendar-availability.md new file mode 100644 index 0000000000..86169d0a84 --- /dev/null +++ b/docs/includes/calendar-availability.md @@ -0,0 +1 @@ +Add-ins that interact with the user's calendar, meetings, or appointments are available only if the user opens the calendar in Outlook, not Teams. However, you can create a Teams meeting app and surface it in Outlook. For more information, see [Extend a Teams meeting app to Outlook](/microsoftteams/platform/m365-apps/extend-m365-meeting-app). \ No newline at end of file diff --git a/docs/includes/deploy-updates-that-require-admin-consent.md b/docs/includes/deploy-updates-that-require-admin-consent.md index 2d35417ab0..a16bf05108 100644 --- a/docs/includes/deploy-updates-that-require-admin-consent.md +++ b/docs/includes/deploy-updates-that-require-admin-consent.md @@ -1,11 +1,11 @@ -When you add features or fix bugs in your add-in, you'll need to deploy the updates. If your add-in is deployed by one or more admins to their organizations, some manifest changes will require the admin to consent to the updates. Users will be blocked from the add-in until consent is granted. The following manifest changes will require the admin to consent again. +When you add features or fix bugs in your add-in, you'll need to deploy the updates. If your add-in is deployed by one or more admins to their organizations, some manifest changes will require the admin to consent to the updates. Users remain on the existing version of the add-in until the admin consents to the updates. The following manifest changes will require the admin to consent again. - Changes to requested permissions. See [Requesting permissions for API use in add-ins](../develop/requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md) and [Understanding Outlook add-in permissions](../outlook/understanding-outlook-add-in-permissions.md). - Additional or changed [Scopes](/javascript/api/manifest/scopes). (Not applicable if the add-in uses the unified manifest for Microsoft 365.) -- Additional or changed [Outlook events](../outlook/autolaunch.md). +- Additional or changed [Events](../develop/event-based-activation.md). > [!NOTE] > Whenever you make a change to the manifest, you must raise the version number of the manifest. > > - If the add-in uses the add-in only manifest, see [Version element](/javascript/api/manifest/version). -> - If the add-in uses the unified manifest, see [version property](/microsoftteams/platform/resources/schema/manifest-schema#version). \ No newline at end of file +> - If the add-in uses the unified manifest, see [version property](/microsoft-365/extensibility/schema/root#version). \ No newline at end of file diff --git a/docs/includes/dev-kit-prerequisites.md b/docs/includes/dev-kit-prerequisites.md new file mode 100644 index 0000000000..39a5946edb --- /dev/null +++ b/docs/includes/dev-kit-prerequisites.md @@ -0,0 +1,5 @@ +## Prerequisites + +- Download and install [Visual Studio Code](https://code.visualstudio.com/). +- Node.js (the latest LTS version). Visit the [Node.js site](https://nodejs.org/) to download and install the right version for your operating system. To verify if you've already installed these tools, run the commands `node -v` and `npm -v` in your terminal. +- Office connected to a Microsoft 365 subscription. You might qualify for a Microsoft 365 E5 developer subscription through the [Microsoft 365 Developer Program](https://developer.microsoft.com/microsoft-365/dev-program), see [FAQ](/office/developer-program/microsoft-365-developer-program-faq#who-qualifies-for-a-microsoft-365-e5-developer-subscription-) for details. Alternatively, you can [sign up for a 1-month free trial](https://www.microsoft.com/microsoft-365/try?rtc=1) or [purchase a Microsoft 365 plan](https://www.microsoft.com/microsoft-365/buy/compare-all-microsoft-365-products). diff --git a/docs/includes/dev-kit-preview-note.md b/docs/includes/dev-kit-preview-note.md index 472190830e..9be5a14259 100644 --- a/docs/includes/dev-kit-preview-note.md +++ b/docs/includes/dev-kit-preview-note.md @@ -1,2 +1,2 @@ > [!IMPORTANT] -> The Office Add-ins Development Kit extension is currently in preview. It only supports creating add-ins that use the [add-in only manifest](../develop/xml-manifest-overview.md). It also only creates Excel, PowerPoint, and Word add-ins at this time. Support for Outlook is under development, as are additional samples and other improvements. We welcome any feedback you have on the tool. Issues and features requests should be submitted through [GitHub issues on the extension's repo](https://aka.ms/officedevkitnewissue). +> The Office Add-ins Development Kit extension only supports creating add-ins that use the [add-in only manifest](../develop/xml-manifest-overview.md). It also only creates Excel, PowerPoint, and Word add-ins at this time. Support for Outlook is under development, as are additional samples and other improvements. We welcome any feedback you have on the tool. Issues and features requests should be submitted through [GitHub issues on the extension's repo](https://aka.ms/officedevkitnewissue). diff --git a/docs/includes/dev-kit-start-debugging.md b/docs/includes/dev-kit-start-debugging.md new file mode 100644 index 0000000000..64411776b8 --- /dev/null +++ b/docs/includes/dev-kit-start-debugging.md @@ -0,0 +1,5 @@ +1. Open the extension by selecting the Office Add-ins Development Kit icon in the **Activity Bar**. +1. Select **Preview Your Office Add-in (F5)** +1. In the Quick Pick menu, select the option **{Office Application} Desktop (Edge Chromium)**, where '{Office Application}' is the appropriate application, such as "Excel" or "Word". This will launch the add-in and debug the code. + +The development kit checks that the prerequisites are met before debugging starts. Check the terminal for detailed information if there are issues with your environment. After this process, the Office desktop application launches and sideloads the add-in. Please note that the first time you run a project, it may make take a few minutes to install the dependencies. You'll need to install the certificate when prompted. \ No newline at end of file diff --git a/docs/includes/dev-kit-stop-debugging.md b/docs/includes/dev-kit-stop-debugging.md new file mode 100644 index 0000000000..2e2c162977 --- /dev/null +++ b/docs/includes/dev-kit-stop-debugging.md @@ -0,0 +1,7 @@ +## Stop testing your Office Add-in + +Once you are finished testing and debugging the add-in, *always* close the add-in by following these steps. (Closing the Office application or web server window doesn't reliably deregister the add-in.) + +1. Open the extension by selecting the Office Add-ins Development Kit icon in the **Activity Bar**. +1. Select **Stop Previewing Your Office Add-in**. This closes the web server and removes the add-in from the registry and cache. +1. Close the Office application window. \ No newline at end of file diff --git a/docs/includes/dev-kit-troubleshooting.md b/docs/includes/dev-kit-troubleshooting.md new file mode 100644 index 0000000000..5c2a72cf4b --- /dev/null +++ b/docs/includes/dev-kit-troubleshooting.md @@ -0,0 +1,12 @@ +## Troubleshooting + +If you have problems running the add-in, take these steps. + +- Close any open instances of Office. +- Close the previous web server started for the add-in with the **Stop Previewing Your Office Add-in** Office Add-ins Development Kit extension option. + +The article [Troubleshoot development errors with Office Add-ins](../testing/troubleshoot-development-errors.md) contains solutions to common problems. If you're still having issues, [create a GitHub issue](https://aka.ms/officedevkitnewissue) and we'll help you. + +For information on running the add-in on Office on the web, see [Sideload Office Add-ins to Office on the web](../testing/sideload-office-add-ins-for-testing.md). + +For information on debugging on older versions of Office, see [Debug add-ins using developer tools in Microsoft Edge Legacy](../testing/debug-add-ins-using-devtools-edge-legacy.md). \ No newline at end of file diff --git a/docs/includes/devkit-project-components-taskpane.md b/docs/includes/devkit-project-components-taskpane.md new file mode 100644 index 0000000000..9907c78d7d --- /dev/null +++ b/docs/includes/devkit-project-components-taskpane.md @@ -0,0 +1,8 @@ +## Explore the project + +The add-in project that you've created with the Office Add-ins Development Kit contains sample code for a basic task pane add-in. If you'd like to explore the components of your add-in project, open the project in your code editor and review the files listed below. When you're ready to try out your add-in, proceed to the next section. + +1. The **./manifest.xml** or **./manifest.json** file in the root directory of the project defines the settings and capabilities of the add-in. +1. The **./src/taskpane/taskpane.html** file contains the HTML markup for the task pane. +1. The **./src/taskpane/taskpane.css** file contains the CSS that's applied to content in the task pane. +1. The **./src/taskpane/taskpane.js** file contains the Office JavaScript API code that facilitates interaction between the task pane and the Office client application. \ No newline at end of file diff --git a/docs/includes/equivalent-add-in-support-note.md b/docs/includes/equivalent-add-in-support-note.md index 6bf35a7414..dffecc3d78 100644 --- a/docs/includes/equivalent-add-in-support-note.md +++ b/docs/includes/equivalent-add-in-support-note.md @@ -1,8 +1,9 @@ > [!IMPORTANT] -> The equivalent add-in feature is supported by the following platform and applications. COM add-ins can't be installed on any other platform, so on those platforms the manifest element that is discussed later in this article, `EquivalentAddins`, is ignored. +> The equivalent add-in feature is supported by the following platform and applications. COM, VSTO, and XLL add-ins can't be installed on any other platform, so on those platforms the manifest markup that is discussed later in this article is ignored. > > - Excel, Word, and PowerPoint on Windows (Version 1904 or later) > - Classic Outlook on Windows (Version 2102 or later) against a supported Exchange server version > - Exchange Online +> - Exchange Server Subscription Edition (SE) > - Exchange 2019 Cumulative Update 10 or later ([KB5003612](https://support.microsoft.com/topic/b1434cad-3fbc-4dc3-844d-82568e8d4344)) > - Exchange 2016 Cumulative Update 21 or later ([KB5003611](https://support.microsoft.com/topic/b7ba1656-abba-4a0b-9be9-dac45095d969)) diff --git a/docs/includes/equivalent-add-ins-limitations.md b/docs/includes/equivalent-add-ins-limitations.md new file mode 100644 index 0000000000..2f40669f8e --- /dev/null +++ b/docs/includes/equivalent-add-ins-limitations.md @@ -0,0 +1,6 @@ + +> [!NOTE] +> The option described in this section has the following limitations. +> +> - It's supported only for Excel, PowerPoint, and Word. +> - The minimum Office version that supports the feature is subscription Office on Windows Version 2506 (Build 19029.20004). diff --git a/docs/includes/es5-support.md b/docs/includes/es5-support.md deleted file mode 100644 index 17912fe213..0000000000 --- a/docs/includes/es5-support.md +++ /dev/null @@ -1,6 +0,0 @@ -For [some versions of Office and Windows](../concepts/browsers-used-by-office-web-add-ins.md), the JavaScript engine in which add-ins run is linked to the Trident webview that's provided by Internet Explorer. This engine doesn't support versions of JavaScript later than ES5. This means that without special handling, the JavaScript files that your add-in serves cannot use syntax, types, or methods that were added to the language after ES5. This doesn't mean that you must *write* in ES5 syntax. You have two other options: - -- Write your code in [ECMAScript 2015](https://www.w3schools.com/Js/js_es6.asp) (also called ES6) or later JavaScript, or in TypeScript, and then compile your code to ES5 JavaScript using a compiler such as [babel](https://babeljs.io/) or [tsc](https://www.typescriptlang.org/index.html). -- Write in ECMAScript 2015 or later JavaScript, but also load a [polyfill](https://en.wikipedia.org/wiki/Polyfill_(programming)) library such as [core-js](https://github.com/zloirock/core-js) that enables IE to run your code. - -For more information about these options, see [Support older Microsoft webviews and Office versions](../develop/support-ie-11.md). diff --git a/docs/includes/excel-custom-functions-manually-register.md b/docs/includes/excel-custom-functions-manually-register.md index 3564668037..1636ec20de 100644 --- a/docs/includes/excel-custom-functions-manually-register.md +++ b/docs/includes/excel-custom-functions-manually-register.md @@ -2,15 +2,15 @@ If the `CONTOSO` namespace isn't available in the autocomplete menu, take the fo # [Excel on the web](#tab/excel-online) -1. In Excel, select **Home** > **Add-ins**, then select **More Add-ins**. +1. Select **Home** > **Add-ins**, then select **More Settings**. -1. In the **MY ADD-INS** tab, select **Manage My Add-ins** and choose **Upload My Add-in**. +1. On the **Office Add-ins** dialog, select **Upload My Add-in**. 1. Choose **Browse...** and navigate to the root directory of the project that the Yeoman generator created. 1. Select the file **manifest.xml** and choose **Open**, then choose **Upload**. -1. Try out the new function. In cell **B1**, type the text **=CONTOSO.GETSTARCOUNT("OfficeDev", "Excel-Custom-Functions")** and press Enter. You should see that the result in cell **B1** is the current number of stars given to the [Excel-Custom-Functions Github repository](https://github.com/OfficeDev/Excel-Custom-Functions). +1. Try out the new function. In cell **B1**, type the text **=CONTOSO.GETSTARCOUNT("OfficeDev", "Excel-Custom-Functions")** and press Enter. You should see that the result in cell **B1** is the current number of stars given to the [Excel-Custom-Functions Github repository](https://github.com/OfficeDev/Excel-Custom-Functions). # [Excel on Windows or on Mac](#tab/excel-windows) diff --git a/docs/includes/excel-custom-functions-note.md b/docs/includes/excel-custom-functions-note.md index 7d952e323e..fb03d568a0 100644 --- a/docs/includes/excel-custom-functions-note.md +++ b/docs/includes/excel-custom-functions-note.md @@ -5,10 +5,13 @@ > - Office on Windows > - Microsoft 365 subscription > - retail perpetual Office 2016 and later -> - volume-licensed perpetual Office 2021 and later +> - volume-licensed perpetual/[LTSC](../resources/resources-glossary.md#long-term-service-channel-ltsc) Office 2021 and later > - Office on Mac > > Excel custom functions aren't currently supported in the following: > > - Office on iPad > - volume-licensed perpetual versions of Office 2019 or earlier on Windows + +> [!NOTE] +> The unified manifest for Microsoft 365 doesn't currently support custom functions projects. You must use the add-in only manifest for custom functions projects. For more information, see [Office Add-ins manifest](../develop/add-in-manifests.md). diff --git a/docs/includes/excel-shared-runtime-preview-note.md b/docs/includes/excel-shared-runtime-preview-note.md index f62ad60699..0395ba07f3 100644 --- a/docs/includes/excel-shared-runtime-preview-note.md +++ b/docs/includes/excel-shared-runtime-preview-note.md @@ -1,3 +1,3 @@ > [!IMPORTANT] -> The features described in this article are currently in preview and subject to change. They are not currently supported for use in production environments. To try the preview features, you will need to [join the Microsoft 365 Insider program](https://insider.microsoft365.com/join). +> The features described in this article are currently in preview and subject to change. They are not currently supported for use in production environments. To try the preview features, you will need to [join the Microsoft 365 Insider program](https://aka.ms/MSFT365InsiderProgram). > A good way to try out preview features is by using a Microsoft 365 subscription. If you don't already have a Microsoft 365 subscription, you might qualify for a Microsoft 365 E5 developer subscription through the [Microsoft 365 Developer Program](https://aka.ms/m365devprogram); for details, see the [FAQ](/office/developer-program/microsoft-365-developer-program-faq#who-qualifies-for-a-microsoft-365-e5-developer-subscription-). Alternatively, you can [sign up for a 1-month free trial](https://www.microsoft.com/microsoft-365/try) or [purchase a Microsoft 365 plan](https://www.microsoft.com/microsoft-365/business/compare-all-microsoft-365-business-products-g). diff --git a/docs/includes/grant-admin-consent-to-an-add-in-include.md b/docs/includes/grant-admin-consent-to-an-add-in-include.md index 30e75716a8..f640a9e5b9 100644 --- a/docs/includes/grant-admin-consent-to-an-add-in-include.md +++ b/docs/includes/grant-admin-consent-to-an-add-in-include.md @@ -1,6 +1,6 @@ - + > [!NOTE] -> This procedure is only needed when you're developing the add-in. When your production add-in is deployed to AppSource or the Microsoft 365 admin center, users will individually trust it or an admin will consent for the organization at installation. +> This procedure is only needed when you're developing the add-in. When your production add-in is deployed to Microsoft Marketplace or the Microsoft 365 admin center, users will individually trust it or an admin will consent for the organization at installation. Carry out this procedure *after* you have [registered the add-in](../develop/register-sso-add-in-aad-v2.md). (If you have just completed that procedure and the **API permissions** tab of the **$ADD-IN-NAME$** page is open in your browser, you can choose the **Grant admin consent for [tenant name]** button, and then select **Yes** for the confirmation that appears. Skip the rest of this procedure.) diff --git a/docs/includes/https-guidance.md b/docs/includes/https-guidance.md index e7213c0e1b..9c1bae4ad6 100644 --- a/docs/includes/https-guidance.md +++ b/docs/includes/https-guidance.md @@ -1,2 +1,2 @@ -While not strictly required in all add-in scenarios, using an HTTPS endpoint for your add-in is strongly recommended. Add-ins that are not SSL-secured (HTTPS) generate unsecure content warnings and errors during use. If you plan to run your add-in in Office on the web or publish your add-in to AppSource, it must be SSL-secured. If your add-in accesses external data and services, it should be SSL-secured to protect data in transit. Self-signed certificates can be used for development and testing, so long as the certificate is trusted on the local machine. +While not strictly required in all add-in scenarios, using an HTTPS endpoint for your add-in is strongly recommended. Add-ins that are not SSL-secured (HTTPS) generate unsecure content warnings and errors during use. If you plan to run your add-in in Office on the web or publish your add-in to Microsoft Marketplace, it must be SSL-secured. If your add-in accesses external data and services, it should be SSL-secured to protect data in transit. Self-signed certificates can be used for development and testing, so long as the certificate is trusted on the local machine. diff --git a/docs/includes/install-dev-kit.md b/docs/includes/install-dev-kit.md index 705f062228..72b7b12f3a 100644 --- a/docs/includes/install-dev-kit.md +++ b/docs/includes/install-dev-kit.md @@ -1,4 +1,4 @@ 1. Launch Visual Studio Code. -1. Select **View** > **Extensions** or **Ctrl+Shift+X**. You can also open extensions by selecting the **Extensions** tab from the Visual Studio Code activity bar. +1. Select **View** > **Extensions** or Ctrl+Shift+X. You can also open extensions by selecting the **Extensions** tab from the Visual Studio Code activity bar. 1. Enter **Office Add-ins Development Kit** in the search box. 1. Select **Office Add-ins Development Kit**. From the Office Add-ins Development Kit extension page that appears in the main pane, select **Install**. After successfully installing, the Office Add-ins Development Kit icon will appear in the Visual Studio Code activity bar. diff --git a/docs/includes/keyboard-shortcuts-prerequisites.md b/docs/includes/keyboard-shortcuts-prerequisites.md deleted file mode 100644 index bdab81923e..0000000000 --- a/docs/includes/keyboard-shortcuts-prerequisites.md +++ /dev/null @@ -1,12 +0,0 @@ -> [!IMPORTANT] -> Keyboard shortcuts are currently only supported on Excel and only on these platforms and builds: -> ->- Excel on the web ->- Excel on Windows: Version 2102 (Build 13801.20632) and later ->- Excel on Mac: Version 16.48 and later - -> [!NOTE] -> Keyboard shortcuts work only on platforms that support the following requirement sets. For more about requirement sets and how to work with them, see [Specify Office applications and API requirements](../develop/specify-office-hosts-and-api-requirements.md). -> -> - [SharedRuntime 1.1](/javascript/api/requirement-sets/common/shared-runtime-requirement-sets) -> - Also needed if the add-in enables the user to customize keyboard shortcuts: [KeyboardShortcuts 1.1](/javascript/api/requirement-sets/common/keyboard-shortcuts-requirement-sets) \ No newline at end of file diff --git a/docs/includes/landing-page-office-addins-guidance-note.md b/docs/includes/landing-page-office-addins-guidance-note.md deleted file mode 100644 index d1d4058561..0000000000 --- a/docs/includes/landing-page-office-addins-guidance-note.md +++ /dev/null @@ -1 +0,0 @@ -Note: See the Core concepts section of this documentation for the full set of articles that apply to all types of Office Add-ins. \ No newline at end of file diff --git a/docs/includes/landing-page-office-addins-guidance.md b/docs/includes/landing-page-office-addins-guidance.md deleted file mode 100644 index 47718eb76f..0000000000 --- a/docs/includes/landing-page-office-addins-guidance.md +++ /dev/null @@ -1,50 +0,0 @@ -

All Office Add-ins are built upon the Office Add-ins platform. They share a common framework through which certain capabilities can be implemented. Explore the following articles for information that's relevant to building any Office Add-in.

- - diff --git a/docs/includes/landing-page-resources-no-script-lab.md b/docs/includes/landing-page-resources-no-script-lab.md deleted file mode 100644 index 8583aadc5a..0000000000 --- a/docs/includes/landing-page-resources-no-script-lab.md +++ /dev/null @@ -1,52 +0,0 @@ -

Resources

-

Use the following resources to ask questions, report issues, or request features related to the Office Add-ins platform or JavaScript API. For information about additional resources, see Office Add-ins additional resources.

- \ No newline at end of file diff --git a/docs/includes/landing-page-resources.md b/docs/includes/landing-page-resources.md deleted file mode 100644 index 51939f0899..0000000000 --- a/docs/includes/landing-page-resources.md +++ /dev/null @@ -1,68 +0,0 @@ -

Resources

-

Use the following resources to explore the APIs, ask questions, report issues, or request features related to the Office Add-ins platform or JavaScript API. For information about additional resources, see Office Add-ins additional resources.

- \ No newline at end of file diff --git a/docs/includes/legacy-exchange-token-deprecation.md b/docs/includes/legacy-exchange-token-deprecation.md index c68ff49a77..d8648d64a7 100644 --- a/docs/includes/legacy-exchange-token-deprecation.md +++ b/docs/includes/legacy-exchange-token-deprecation.md @@ -1,2 +1,2 @@ > [!IMPORTANT] -> Legacy Exchange tokens are deprecated. Starting October 2024, legacy Exchange [user identity](../outlook/authentication.md#exchange-user-identity-token) and [callback](../outlook/authentication.md#callback-tokens) tokens will begin to be turned off for Exchange Online tenants. For the timeline and details, see our [FAQ page](../outlook/faq-nested-app-auth-outlook-legacy-tokens.yml). This is part of [Microsoft's Secure Future Initiative](https://blogs.microsoft.com/on-the-issues/2023/11/02/secure-future-initiative-sfi-cybersecurity-cyberattacks/), which gives organizations the tools needed to respond to the current threat landscape. Exchange user identity tokens will still work for Exchange on-premises. Nested app authentication is the recommended approach for tokens going forward. +> Legacy Exchange Online [user identity tokens](../outlook/authentication.md#exchange-user-identity-token) and [callback tokens](../outlook/authentication.md#callback-tokens) are no longer supported and turned off across all Microsoft 365 tenants. If an Outlook add-in requires delegated user access or user identity, we recommend using [MSAL (Microsoft Authentication Library) and nested app authentication](../develop/enable-nested-app-authentication-in-your-add-in.md). Exchange user identity tokens are still supported for Exchange on-premises. diff --git a/docs/includes/mac-cache-folders.md b/docs/includes/mac-cache-folders.md deleted file mode 100644 index 645ca8de29..0000000000 --- a/docs/includes/mac-cache-folders.md +++ /dev/null @@ -1,28 +0,0 @@ -Add-ins are often cached in Office on Mac for performance reasons. Normally, the cache is cleared by reloading the add-in. If more than one add-in exists in the same document, the process of automatically clearing the cache on reload might not be reliable. - -### Use the personality menu to clear the cache - -You can clear the cache by using the personality menu of any task pane add-in. However, because the personality menu isn't supported in Outlook add-ins, you can try the option to [clear the cache manually](#clear-the-cache-manually) if you're using Outlook. - -- Choose the personality menu. Then choose **Clear Web Cache**. - > [!NOTE] - > You must run macOS Version 10.13.6 or later to see the personality menu. - - ![The clear web cache option on personality menu.](../images/mac-clear-cache-menu.png) - -### Clear the cache manually - -You can also clear the cache manually by deleting the contents of the `~/Library/Containers/com.Microsoft.OsfWebHost/Data/` and `~/Library/Containers/com.microsoft.{host}/Data/Documents/wef` folders. Replace `{host}` with the Office application, such as `Excel`. Look for these folders via terminal. - -Deleting the contents of the `~/Library/Containers/com.microsoft.{host}/Data/Documents/wef` folder removes a sideloaded add-in from the add-ins menu in an application. - -> [!NOTE] -> If the `~/Library/Containers/com.Microsoft.OsfWebHost/Data/` folder doesn't exist, check for the following folders via terminal and if found, delete the contents of the folder. -> -> - `~/Library/Containers/com.microsoft.{host}/Data/Library/Caches/` where `{host}` is the Office application (e.g., `Excel`) -> - `~/Library/Containers/com.microsoft.{host}/Data/Library/Application Support/Microsoft/Office/16.0/Wef/` where `{host}` is the Office application (e.g., `Excel`) -> - `~/Library/Containers/com.microsoft.Office365ServiceV2/Data/Caches/com.microsoft.Office365ServiceV2/` -> - `~/Library/Containers/com.microsoft.Office365ServiceV2/Data/Library/Caches/com.microsoft.Office365ServiceV2/` - -> [!TIP] -> To look for these folders via Finder, you must set Finder to show hidden files. Finder displays the folders inside the **Containers** directory by product name, such as **Microsoft Excel** instead of **com.microsoft.Excel**. \ No newline at end of file diff --git a/docs/includes/mailbox-object-desc.md b/docs/includes/mailbox-object-desc.md index f8e689b477..a5f7402904 100644 --- a/docs/includes/mailbox-object-desc.md +++ b/docs/includes/mailbox-object-desc.md @@ -1,16 +1,17 @@ -Outlook add-ins primarily use a subset of the API exposed through the [Mailbox](/javascript/api/outlook/office.mailbox) object. To access the objects and members specifically for use in Outlook add-ins, such as the [Item](/javascript/api/outlook/office.item) object, use the [mailbox](/javascript/api/office/office.context#office-office-context-mailbox-member) property of the **Context** object to access the **Mailbox** object, as shown in the following line of code. +Outlook add-ins primarily use a subset of the API exposed through the [Mailbox](/javascript/api/outlook/office.mailbox) object. To access the objects and members for use in Outlook add-ins, such as the [Item](/javascript/api/outlook/office.item) object in compose or read mode, use the [mailbox](/javascript/api/office/office.context#office-office-context-mailbox-member) property of the **Context** object to access the **Mailbox** object. The following code is an example. ```js // Access the Item object. const item = Office.context.mailbox.item; ``` +> [!IMPORTANT] +> When calling `Office.context.mailbox.item` on a message, note that the Reading Pane in the Outlook client must be turned on. For guidance on how to configure the Reading Pane, see [Use and configure the Reading Pane to preview messages](https://support.microsoft.com/office/2fd687ed-7fc4-4ae3-8eab-9f9b8c6d53f0). + Additionally, Outlook add-ins can use the following objects. - **Office** object: for initialization. - **Context** object: for access to content and display language properties. -- **RoamingSettings** object: for saving Outlook add-in-specific custom settings to the user's mailbox where the add-in is installed. - -For information about using JavaScript in Outlook add-ins, see [Outlook add-ins](../outlook/outlook-add-ins-overview.md). +For information about using JavaScript in Outlook add-ins, see [Outlook add-ins](../outlook/outlook-add-ins-overview.md). To explore the Outlook JavaScript API, see the [Outlook API reference](/javascript/api/outlook) page. diff --git a/docs/includes/manifest-guidance.md b/docs/includes/manifest-guidance.md index 91409152cf..6002f0ea33 100644 --- a/docs/includes/manifest-guidance.md +++ b/docs/includes/manifest-guidance.md @@ -1,7 +1,12 @@ > [!TIP] > If you'll be testing your add-in across multiple environments (for example, in development, staging, demo, etc.), we recommend that you maintain a different manifest file for each environment. In each manifest file, you can: +> > - Specify the URLs that correspond to the environment. -> - Customize metadata values like `DisplayName` and labels within `Resources` to indicate the environment, so that end users will be able to identify a sideloaded add-in's corresponding environment. +> - Customize metadata values so that end users are able to identify a sideloaded add-in's corresponding environment. For example: +> +> - In the unified manifest for Microsoft 365, customize the [`"name"`](/microsoft-365/extensibility/schema/root-name) property of the add-in and the `"label"` properties for various UI controls to indicate the environment. +> - In the add-in only manifest, customize the `DisplayName` element and and labels within the `Resources` element to indicate the environment. +> > - Customize the custom functions `namespace` to indicate the environment, if your add-in defines custom functions. -> +> > By following this guidance, you'll streamline the testing process and avoid issues that would otherwise occur when an add-in is simultaneously sideloaded for multiple environments. \ No newline at end of file diff --git a/docs/includes/modern-js-note.md b/docs/includes/modern-js-note.md deleted file mode 100644 index 0c52464a71..0000000000 --- a/docs/includes/modern-js-note.md +++ /dev/null @@ -1,2 +0,0 @@ -> [!NOTE] -> The following code uses ES6 JavaScript, which isn't compatible with [older versions of Office that use the Trident (Internet Explorer 11) browser engine](/office/dev/add-ins/concepts/browsers-used-by-office-web-add-ins). For information on how to support those platforms in production, see [Support older Microsoft webviews and Office versions](/office/dev/add-ins/develop/support-ie-11). If you don't already have a Microsoft 365 subscription to use for development, you might qualify for a Microsoft 365 E5 developer subscription through the [Microsoft 365 Developer Program](https://aka.ms/m365devprogram); for details, see the [FAQ](/office/developer-program/microsoft-365-developer-program-faq#who-qualifies-for-a-microsoft-365-e5-developer-subscription-). Alternatively, you can [sign up for a 1-month free trial](https://www.microsoft.com/microsoft-365/try) or [purchase a Microsoft 365 plan](https://www.microsoft.com/microsoft-365/business/compare-all-microsoft-365-business-products-g). diff --git a/docs/includes/new-outlook-vsto-com-support.md b/docs/includes/new-outlook-vsto-com-support.md index 2b3842eae5..cb7f983336 100644 --- a/docs/includes/new-outlook-vsto-com-support.md +++ b/docs/includes/new-outlook-vsto-com-support.md @@ -1,3 +1,3 @@ > [!IMPORTANT] > -> COM and VSTO add-ins aren't supported in the [new Outlook on Windows](https://insider.office.com/blog/new-outlook-for-windows-available-to-all-office-insiders) that's currently in preview. These add-ins are still supported in the classic Outlook on Windows desktop client. To learn more, see [Develop Outlook add-ins for new Outlook on Windows](../outlook/one-outlook.md). +> COM and VSTO add-ins aren't supported in the [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627). These add-ins are still supported in the classic Outlook on Windows desktop client. To learn more, see [Develop Outlook add-ins for new Outlook on Windows](../outlook/one-outlook.md). diff --git a/docs/includes/non-unified-manifest-clients.md b/docs/includes/non-unified-manifest-clients.md index 5391134e08..f9eba29e08 100644 --- a/docs/includes/non-unified-manifest-clients.md +++ b/docs/includes/non-unified-manifest-clients.md @@ -1,4 +1,2 @@ > [!NOTE] -> Office Add-ins that use the unified manifest for Microsoft 365 are *directly* supported in Office on the web, in [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627), and in Office on Windows connected to a Microsoft 365 subscription, Version 2304 (Build 16320.00000) or later. -> -> When the app package that contains the unified manifest is deployed in [AppSource](https://appsource.microsoft.com/) or the [Microsoft 365 Admin Center](../publish/publish.md) then, if the manifest has a valid "alternateIcons" property, an add-in only manifest is generated from the unified manifest and stored. This add-in only manifest enables the add-in to be installed on platforms that don't directly support the unified manifest, including Office on Mac, Office on mobile, subscription versions of Office on Windows earlier than 2304 (Build 16320.00000), and perpetual versions of Office on Windows. +> For information on clients and platforms that *directly* support Office Add-ins that use the unified manifest for Microsoft 365, see [Office Add-ins with the unified app manifest for Microsoft 365](../develop/unified-manifest-overview.md#client-and-platform-support). diff --git a/docs/includes/note-publish-policies.md b/docs/includes/note-publish-policies.md index 2b3370857a..2645ee30e4 100644 --- a/docs/includes/note-publish-policies.md +++ b/docs/includes/note-publish-policies.md @@ -1,2 +1,2 @@ -> [!NOTE] -> If you plan to [publish](../publish/publish.md) your add-in to AppSource and make it available within the Office experience, make sure that you conform to the [Commercial marketplace certification policies](/legal/marketplace/certification-policies). For example, to pass validation, your add-in must work across all platforms that support the methods that you define (for more information, see [section 1120.3](/legal/marketplace/certification-policies#11203-functionality) and the [Office Add-in application and availability page](/javascript/api/requirement-sets)). \ No newline at end of file +> [!NOTE] +> If you plan to [publish](../publish/publish.md) your add-in to Microsoft Marketplace and make it available within the Office experience, make sure that you conform to the [Commercial marketplace certification policies](/legal/marketplace/certification-policies). For example, to pass validation, your add-in must work across all platforms that support the methods that you define (for more information, see [section 1120.3](/legal/marketplace/certification-policies#11203-functionality) and the [Office Add-in application and availability page](/javascript/api/requirement-sets)). \ No newline at end of file diff --git a/docs/includes/office-bundle-js.md b/docs/includes/office-bundle-js.md new file mode 100644 index 0000000000..af42c8bffb --- /dev/null +++ b/docs/includes/office-bundle-js.md @@ -0,0 +1,9 @@ +> [!TIP] +> +> - For readability, this article refers to the file name as **bundle.js**, but exact name depends on the Office application. +> - Excel: **bundle_excel.js** +> - Outlook: **bundle.js**. +> - PowerPoint: **bundle_powerpoint.js** +> - Word: **bundle_word.js** +> - There's no direct method to determine the Office profile GUID and account encoding used in the **bundle.js** file path. The most effective approach to locate your add-in's **bundle.js** file is to manually inspect each folder until you locate the **Javascript** folder that contains your add-in's ID. +> - The **bundle.js** file is downloaded to the local **Wef** folder when the add-in is first installed. It's refreshed every time the Office application starts or is restarted. If the **bundle.js** file doesn't appear in the **Wef** folder and your add-in is installed or sideloaded, restart Office. For Outlook, you may need to [remove your add-in](../outlook/sideload-outlook-add-ins-for-testing.md#remove-a-sideloaded-add-in), then [sideload](../outlook/sideload-outlook-add-ins-for-testing.md) it again. diff --git a/docs/includes/office-js-access-library.md b/docs/includes/office-js-access-library.md index 4507446282..8a873497a4 100644 --- a/docs/includes/office-js-access-library.md +++ b/docs/includes/office-js-access-library.md @@ -10,4 +10,4 @@ The Office JavaScript API library can be accessed via the Office JS content deli > [!NOTE] > To use preview APIs, reference the preview version of the Office JavaScript API library on the CDN: `https://appsforoffice.microsoft.com/lib/beta/hosted/office.js`. -For more information about accessing the Office JavaScript API library, including how to get IntelliSense, see [Referencing the Office JavaScript API library from its content delivery network (CDN)](../develop/referencing-the-javascript-api-for-office-library-from-its-cdn.md). \ No newline at end of file +For more information about accessing the Office JavaScript API library, including how to get IntelliSense, see [Referencing the Office JavaScript API library from its content delivery network (CDN)](../develop/referencing-the-javascript-api-for-office-library-from-its-cdn.md). diff --git a/docs/includes/office-js-api-models.md b/docs/includes/office-js-api-models.md index fd9c52289e..6ddfe6494c 100644 --- a/docs/includes/office-js-api-models.md +++ b/docs/includes/office-js-api-models.md @@ -10,7 +10,7 @@ The Office JavaScript API includes two distinct models: This API model uses [promises](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise) and allows you to specify multiple operations in each request you send to the Office application. Batching operations in this manner can significantly improve add-in performance in Office applications on the web. Application-specific APIs were introduced with Office 2016. > [!NOTE] - > There's also an application-specific API for [Visio](../reference/overview/visio-javascript-reference-overview.md), but you can use it only in SharePoint Online pages to interact with Visio diagrams that have been embedded in the page. Office Web Add-ins are not supported in Visio. + > There's also an application-specific API for [Visio](../visio/visio-overview.md), but you can use it only in SharePoint Online pages to interact with Visio diagrams that have been embedded in the page. Office Web Add-ins are not supported in Visio. See [Using the application-specific API model](../develop/application-specific-api-model.md) to learn more about this API model. diff --git a/docs/includes/outlook-bundle-js.md b/docs/includes/outlook-bundle-js.md deleted file mode 100644 index 9449954e64..0000000000 --- a/docs/includes/outlook-bundle-js.md +++ /dev/null @@ -1,5 +0,0 @@ -> [!TIP] -> If the **bundle.js** file doesn't appear in the **Wef** folder, try the following: -> -> - If your add-in is installed or sideloaded, restart Outlook. -> - [Remove your add-in](../outlook/sideload-outlook-add-ins-for-testing.md#remove-a-sideloaded-add-in) from Outlook, then [sideload](../outlook/sideload-outlook-add-ins-for-testing.md) it again. diff --git a/docs/includes/outlook-manual-sideloading.md b/docs/includes/outlook-manual-sideloading.md index cf5533a03b..bf2f80013e 100644 --- a/docs/includes/outlook-manual-sideloading.md +++ b/docs/includes/outlook-manual-sideloading.md @@ -1,2 +1,5 @@ > [!NOTE] +> +> - When you first use Yeoman generator to develop an Office Add-in, your default browser opens a window where you'll be prompted to sign in to your Microsoft 365 account. If a sign-in window doesn't appear and you encounter a sideloading or login timeout error, run `atk auth login m365` before running `npm start` again. +> > If your add-in wasn't automatically sideloaded, follow the instructions in [Sideload Outlook add-ins for testing](../outlook/sideload-outlook-add-ins-for-testing.md#sideload-manually) to manually sideload the add-in in Outlook. diff --git a/docs/includes/outlook-permission-levels-table.md b/docs/includes/outlook-permission-levels-table.md deleted file mode 100644 index d2e57c078c..0000000000 --- a/docs/includes/outlook-permission-levels-table.md +++ /dev/null @@ -1,17 +0,0 @@ -|Permission level
canonical name|add-in only manifest name|unified manifest for Microsoft 365 name|Summary description| -|:-----|:-----|:-----|:-----| -|**restricted**|Restricted|MailboxItem.Restricted.User|Allows access to properties and methods that don't pertain to specific information about the user or mail item.| -|**read item**|ReadItem|MailboxItem.Read.User|In addition to what is allowed in **restricted**, it allows:
  • regular expressions
  • Outlook add-in API read access
  • getting the item properties and the callback token
  • writing custom properties
| -|**read/write item**|ReadWriteItem|MailboxItem.ReadWrite.User|In addition to what is allowed in **read item**, it allows:
  • full Outlook add-in API access except `makeEwsRequestAsync`
  • setting the item properties
| -|**read/write mailbox**|ReadWriteMailbox|Mailbox.ReadWrite.User|In addition to what is allowed in **read/write item**, it allows:
  • creating, reading, writing items and folders
  • sending items
  • calling [makeEwsRequestAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox#methods)
| - -Permissions are declared in the manifest. The markup varies depending on the type of manifest. - -- **Add-in only manifest**: Use the **\** element. -- **Unified manifest for Microsoft 365**: Use the "name" property of an object in the "authorization.permissions.resourceSpecific" array. - -> [!NOTE] -> -> - There's a supplementary permission needed for add-ins that use the append-on-send feature. With the add-in only manifest, specify the permission in the [ExtendedPermissions](/javascript/api/manifest/extendedpermissions) element. For details, see [Implement append-on-send in your Outlook add-in](../outlook/append-on-send.md). With the unified manifest, specify this permission with the name **Mailbox.AppendOnSend.User** in an additional object in the "authorization.permissions.resourceSpecific" array. -> - There's a supplementary permission needed for add-ins that use shared folders. With the add-in only manifest, specify the permission by setting the [SupportsSharedFolders](/javascript/api/manifest/supportssharedfolders) element to `true`. For details, see [Enable shared folders and shared mailbox scenarios in an Outlook add-in](../outlook/delegate-access.md). With the unified manifest, specify this permission with the name **Mailbox.SharedFolder** in an additional object in the "authorization.permissions.resourceSpecific" array. - diff --git a/docs/includes/outlook-sensitivity-label-event-support.md b/docs/includes/outlook-sensitivity-label-event-support.md new file mode 100644 index 0000000000..81aabd4c15 --- /dev/null +++ b/docs/includes/outlook-sensitivity-label-event-support.md @@ -0,0 +1,2 @@ +> [!NOTE] +> The `OnSensitivityLabelChanged` event isn't currently available with the unified manifest for Microsoft 365 in Outlook on the web and the new Outlook on Windows. To handle these events, implement an add-in only manifest instead. For information about the types of manifests, see [Office Add-ins manifest](../develop/add-in-manifests.md). diff --git a/docs/includes/outlook-smart-alerts-deployment.md b/docs/includes/outlook-smart-alerts-deployment.md index c48bae21a5..5f40fff467 100644 --- a/docs/includes/outlook-smart-alerts-deployment.md +++ b/docs/includes/outlook-smart-alerts-deployment.md @@ -1,2 +1,2 @@ -> [!IMPORTANT] -> Add-ins that use the [Smart Alerts feature](../outlook/onmessagesend-onappointmentsend-events.md) can only be published to AppSource if the manifest's send mode property is set to the **prompt user** or **soft block** option. If an add-in's send mode property is set to **block**, it can only be deployed by an organization's admin as it will fail AppSource validation. +> [!IMPORTANT] +> Add-ins that use the [Smart Alerts feature](../outlook/onmessagesend-onappointmentsend-events.md) can only be published to Microsoft Marketplace if the manifest's send mode property is set to the **prompt user** or **soft block** option. If an add-in's send mode property is set to **block**, it can only be deployed by an organization's admin as it will fail Microsoft Marketplace validation. diff --git a/docs/includes/outlook-unified-manifest-mac.md b/docs/includes/outlook-unified-manifest-mac.md new file mode 100644 index 0000000000..4e05d10645 --- /dev/null +++ b/docs/includes/outlook-unified-manifest-mac.md @@ -0,0 +1,2 @@ +> [!NOTE] +> Add-ins that use the unified manifest for Microsoft 365 aren't directly supported in Outlook on Mac. To run this type of add-in on Mac, the add-in must first be published to [Microsoft Marketplace](https://marketplace.microsoft.com/) then deployed in the [Microsoft 365 Admin Center](../publish/publish.md). For more information, see [Support for add-ins with the unified manifest for Microsoft 365](../outlook/compare-outlook-add-in-support-in-outlook-for-mac.md#support-for-add-ins-with-the-unified-manifest-for-microsoft-365). diff --git a/docs/includes/outlook-unified-manifest-mobile.md b/docs/includes/outlook-unified-manifest-mobile.md new file mode 100644 index 0000000000..20d2da4234 --- /dev/null +++ b/docs/includes/outlook-unified-manifest-mobile.md @@ -0,0 +1,2 @@ +> [!NOTE] +> Add-ins that use the unified manifest for Microsoft 365 aren't directly supported in Outlook on mobile devices. To run this type of add-in on mobile platforms, the add-in must first be published to [Microsoft Marketplace](https://marketplace.microsoft.com/) then deployed in the [Microsoft 365 Admin Center](../publish/publish.md). For more information, see [Support for add-ins with the unified manifest for Microsoft 365](../outlook/outlook-mobile-addins.md#support-for-add-ins-with-the-unified-manifest-for-microsoft-365). diff --git a/docs/includes/outlook-unified-manifest-platforms.md b/docs/includes/outlook-unified-manifest-platforms.md new file mode 100644 index 0000000000..bc5e366576 --- /dev/null +++ b/docs/includes/outlook-unified-manifest-platforms.md @@ -0,0 +1,2 @@ +> [!NOTE] +> Add-ins that use the unified manifest for Microsoft 365 aren't directly supported in Outlook on Mac and on mobile devices. To run this type of add-in on Mac and on mobile platforms, the add-in must first be published to [Microsoft Marketplace](https://marketplace.microsoft.com/) then deployed in the [Microsoft 365 Admin Center](../publish/publish.md). For more information, see the "Client and platform support" section of [Office Add-ins with the unified app manifest for Microsoft 365](../develop/unified-manifest-overview.md#client-and-platform-support). diff --git a/docs/includes/publish-add-in.md b/docs/includes/publish-add-in.md index a0bf301e88..099b5a9c2e 100644 --- a/docs/includes/publish-add-in.md +++ b/docs/includes/publish-add-in.md @@ -1,4 +1,4 @@ -An Office Add-in consists of a web application and a manifest file. The web application defines the add-in's user interface and functionality, while the manifest specifies the location of the web application and defines settings and capabilities of the add-in. +An Office Add-in includes two basic components: a manifest file and your own web application. The manifest defines various settings, including how your add-in integrates with Office clients. Your web application serves the HTML, JavaScript, and other files that provide the add-in's functionality and UI. While you're developing your add-in, you can run the add-in on your local web server (`localhost`), but when you're ready to publish it for other users to access, you'll need to deploy the web application to a web server or web hosting service (for example, Microsoft Azure) and update the manifest to specify the URL of the deployed application. @@ -14,6 +14,6 @@ When your add-in is working as desired and you're ready to publish it for other 2. Upload the contents of the **dist** folder to the web server that'll host your add-in. You can use any type of web server or web hosting service to host your add-in. -3. In VS Code, open the add-in's manifest file, located in the root directory of the project (`manifest.xml`). Replace all occurrences of `https://localhost:3000` with the URL of the web application that you deployed to a web server in the previous step. +3. In VS Code, open the add-in's manifest file, located in the root directory of the project. Replace all occurrences of `https://localhost:3000` with the URL of the web application that you deployed to a web server in the previous step. -4. Choose the method you'd like to use to [deploy your Office Add-in](../publish/publish.md), and follow the instructions to publish the manifest file. +4. Choose the method you'd like to use to [deploy your Office Add-in](../publish/publish.md), and follow the instructions to publish the add-in. diff --git a/docs/includes/quickstart-troubleshooting-vs.md b/docs/includes/quickstart-troubleshooting-vs.md index 4df131f8d1..bd615c00f4 100644 --- a/docs/includes/quickstart-troubleshooting-vs.md +++ b/docs/includes/quickstart-troubleshooting-vs.md @@ -1,3 +1,3 @@ [!include[The common troubleshooting section for all quick starts](../includes/quickstart-troubleshooting-common.md)] -- If your add-in shows an error (for example, "This add-in could not be started. Close this dialog to ignore the problem or click "Restart" to try again.") when you press **F5** or choose **Debug** > **Start Debugging** in Visual Studio, see [Debug Office Add-ins in Visual Studio](../develop/debug-office-add-ins-in-visual-studio.md) for other debugging options. \ No newline at end of file +- If your add-in shows an error (for example, "This add-in could not be started. Close this dialog to ignore the problem or click "Restart" to try again.") when you press F5 or choose **Debug** > **Start Debugging** in Visual Studio, see [Debug Office Add-ins in Visual Studio](../develop/debug-office-add-ins-in-visual-studio.md) for other debugging options. \ No newline at end of file diff --git a/docs/includes/quickstart-troubleshooting-yo.md b/docs/includes/quickstart-troubleshooting-yo.md index 8410d36c75..9532219fb0 100644 --- a/docs/includes/quickstart-troubleshooting-yo.md +++ b/docs/includes/quickstart-troubleshooting-yo.md @@ -1,3 +1,9 @@ [!include[The common troubleshooting section for all quick starts](../includes/quickstart-troubleshooting-common.md)] -- The automatic `npm install` step Yo Office performs may fail. If you see errors when trying to run `npm start`, navigate to the newly created project folder in a command prompt and manually run `npm install`. For more information about Yo Office, see [Create Office Add-in projects using the Yeoman Generator](../develop/yeoman-generator-overview.md). \ No newline at end of file +- The automatic `npm install` step Yo Office performs may fail. If you see errors when trying to run `npm start`, navigate to the newly created project folder in a command prompt and manually run `npm install`. For more information about Yo Office, see [Create Office Add-in projects using the Yeoman Generator](../develop/yeoman-generator-overview.md). +- You may see warnings generated when running `npm install` for either Yeoman generator or the project. In most cases, you can safely ignore these warnings. Sometimes, dependencies become deprecated and their replacements aren't supported by other packages on which the project depends. If you would like to resolve these warnings, use the `npm-check-updates` tool. + - In the command prompt while in the root project directory, run `npm i -g npm-check-updates`. This installs the tool globally. + - Run `ncu -u`. This provides a report of all packages and to what versions they will be updated. + - Run `npm install` to update all the packages. + + For more information about warnings when running `npm install`, see [Warnings and dependencies in the Node.js and npm world](../overview/npm-warnings-advice.md). \ No newline at end of file diff --git a/docs/includes/quickstart-yo-start-server-excel.md b/docs/includes/quickstart-yo-start-server-excel.md index b9d5635623..4c82472b52 100644 --- a/docs/includes/quickstart-yo-start-server-excel.md +++ b/docs/includes/quickstart-yo-start-server-excel.md @@ -18,4 +18,4 @@ Complete the following steps to start the local web server and sideload your add - To test your add-in in Excel on a browser, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of an Excel document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] diff --git a/docs/includes/register-sso-add-in-aad-v2-include.md b/docs/includes/register-sso-add-in-aad-v2-include.md index 7d57d0648b..9d69be4fb6 100644 --- a/docs/includes/register-sso-add-in-aad-v2-include.md +++ b/docs/includes/register-sso-add-in-aad-v2-include.md @@ -79,7 +79,7 @@ Sometimes called an _application password_, a client secret is a string value yo For additional application ID URI details, see [Application manifest identifierUris attribute](/azure/active-directory/develop/reference-app-manifest#identifieruris-attribute). > [!NOTE] - > If you get an error saying that the domain is already owned but you own it, follow the procedure at [Quickstart: Add a custom domain name to Azure Active Directory](/azure/active-directory/add-custom-domain) to register it, and then repeat this step. (This error can also occur if you are not signed in with credentials of an admin in the Microsoft 365 tenancy. See step 2. Sign out and sign in again with admin credentials and repeat the process from step 3.) + > If you get an error saying that the domain is already owned but you own it, follow the procedure at [Add your custom domain name to your tenant](/entra/fundamentals/add-custom-domain) to register it, and then repeat this step. (This error can also occur if you are not signed in with credentials of an admin in the Microsoft 365 tenancy. See step 2. Sign out and sign in again with admin credentials and repeat the process from step 3.) ## Add a scope @@ -126,8 +126,6 @@ Sometimes called an _application password_, a client secret is a string value yo > - `93d53678-613d-4013-afc1-62e9e444a0a5` (Office on the web) > - `bc59ab01-8403-45c6-8796-ac3ef710b3e3` (Outlook on the web) - - 1. In **Authorized scopes**, select the `api:////access_as_user` checkbox. 1. Select **Add application**. @@ -169,7 +167,7 @@ Sometimes called an _application password_, a client secret is a string value yo ## Configure access token version -You must define the access token version that is acceptable for your app. This configuration is made in the Azure Active Directory application manifest. +You must define the access token version that is acceptable for your app. This configuration is made in the Microsoft Entra ID application manifest. ### Define the access token version @@ -179,9 +177,9 @@ The access token version can change if you chose an account type other than **Ac :::image type="content" source="../images/azure-portal-manifest.png" alt-text="Select Azure manifest."::: - The Azure Active Directory application manifest appears. + The Microsoft Entra ID application manifest appears. -1. Enter **2** as the value for the `accessTokenAcceptedVersion` property. +1. Enter **2** as the value for the `requestedAccessTokenVersion` property (in the `api` object). :::image type="content" source="../images/azure-portal-manifest-token-version.png" alt-text="Value for accepted access token version."::: diff --git a/docs/includes/start-web-sideload-instructions.md b/docs/includes/start-web-sideload-instructions.md index a1875a09e2..6b344a4770 100644 --- a/docs/includes/start-web-sideload-instructions.md +++ b/docs/includes/start-web-sideload-instructions.md @@ -2,13 +2,13 @@ > If you are developing on a Mac, enclose the `{url}` in single quotation marks. Do *not* do this on Windows. ```command line -npm run start:web -- --document {url} +npm run start -- web --document {url} ``` The following are examples. -- `npm run start:web -- --document https://contoso.sharepoint.com/:t:/g/EZGxP7ksiE5DuxvY638G798BpuhwluxCMfF1WZQj3VYhYQ?e=F4QM1R` -- `npm run start:web -- --document https://1drv.ms/x/s!jkcH7spkM4EGgcZUgqthk4IK3NOypVw?e=Z6G1qp` -- `npm run start:web -- --document https://contoso-my.sharepoint-df.com/:t:/p/user/EQda453DNTpFnl1bFPhOVR0BwlrzetbXvnaRYii2lDr_oQ?e=RSccmNP` +- `npm run start -- web --document https://contoso.sharepoint.com/:t:/g/EZGxP7ksiE5DuxvY638G798BpuhwluxCMfF1WZQj3VYhYQ?e=F4QM1R` +- `npm run start -- web --document https://1drv.ms/x/s!jkcH7spkM4EGgcZUgqthk4IK3NOypVw?e=Z6G1qp` +- `npm run start -- web --document https://contoso-my.sharepoint-df.com/:t:/p/user/EQda453DNTpFnl1bFPhOVR0BwlrzetbXvnaRYii2lDr_oQ?e=RSccmNP` If your add-in doesn't sideload in the document, manually sideload it by following the instructions in [Manually sideload add-ins to Office on the web](../testing/sideload-office-add-ins-for-testing.md#manually-sideload-an-add-in-to-office-on-the-web). diff --git a/docs/includes/tutorial-excel-start-server.md b/docs/includes/tutorial-excel-start-server.md index ad07bf392f..e60ffb29ca 100644 --- a/docs/includes/tutorial-excel-start-server.md +++ b/docs/includes/tutorial-excel-start-server.md @@ -8,5 +8,5 @@ If the local web server is already running and your add-in is already loaded in - To test your add-in in Excel on the web, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of an Excel document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] diff --git a/docs/includes/tutorial-word-start-server.md b/docs/includes/tutorial-word-start-server.md index cd96799936..e818f3877a 100644 --- a/docs/includes/tutorial-word-start-server.md +++ b/docs/includes/tutorial-word-start-server.md @@ -8,5 +8,5 @@ If the local web server is already running and your add-in is already loaded in - To test your add-in in Word on the web, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of a Word document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] diff --git a/docs/includes/unified-manifest-sideload-restrictions-note.md b/docs/includes/unified-manifest-sideload-restrictions-note.md new file mode 100644 index 0000000000..a0dc91df64 --- /dev/null +++ b/docs/includes/unified-manifest-sideload-restrictions-note.md @@ -0,0 +1,4 @@ +> [!NOTE] +> Currently, an add-in that uses the [Unified manifest for Microsoft 365](../develop/json-manifest-overview.md) can't be sideloaded on Mac or iPad. +> +> To sideload an add-in with a unified manifest on Windows and on the web, see [Sideload Office Add-ins that uses the unified manifest for Microsoft 365](../testing/sideload-add-in-with-unified-manifest.md). \ No newline at end of file diff --git a/docs/includes/unified-manifest-support-note.md b/docs/includes/unified-manifest-support-note.md index 2810e966df..303e6cfeb9 100644 --- a/docs/includes/unified-manifest-support-note.md +++ b/docs/includes/unified-manifest-support-note.md @@ -1,2 +1,2 @@ > [!NOTE] -> The [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md) can be used in production Outlook add-ins. It is available only as a preview for Excel, PowerPoint, and Word add-ins. \ No newline at end of file +> The [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md) can be used in production Outlook add-ins. It's available only as a preview for Excel, PowerPoint, and Word add-ins. diff --git a/docs/includes/unified-manifest-value-prop-feedback.md b/docs/includes/unified-manifest-value-prop-feedback.md index 1f69fd816a..44aa808b6f 100644 --- a/docs/includes/unified-manifest-value-prop-feedback.md +++ b/docs/includes/unified-manifest-value-prop-feedback.md @@ -1,4 +1,4 @@ > [!NOTE] -> The unified manifest for Microsoft 365 enables you to combine an Outlook Add-in with a Teams app as a single unit of development and deployment. We're working to extend support for the unified manifest to Excel, PowerPoint, Word, custom Copilot development, and other extensions of Microsoft 365. For more about it, see [Office Add-ins with the unified manifest](../develop/unified-manifest-overview.md). For a sample of a combined Teams app and Outlook Add-in, see [Discount Offers](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/tab-add-in-combined/nodejs). +> The unified manifest for Microsoft 365 enables you to combine an Outlook add-in with a Teams app into an App for Microsoft 365 as a single unit of development and deployment. We're working to extend support for the unified manifest to Excel, PowerPoint, Word, custom Copilot development, and other extensions of Microsoft 365. For more about it, see [Office Add-ins with the unified manifest](../develop/unified-manifest-overview.md). For a sample of an App for Microsoft 365 that combines a Teams app and Outlook add-in, see [Discount Offers](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/tab-add-in-combined/nodejs). > > We love to get your feedback about the unified manifest. If you have any suggestions, please create an issue in the repo for the [Office JavaScript Library](https://github.com/OfficeDev/office-js/issues). \ No newline at end of file diff --git a/docs/includes/use-legacy-edge-or-ie.md b/docs/includes/use-legacy-edge-or-ie.md index a5ab9eda24..78123ee7fa 100644 --- a/docs/includes/use-legacy-edge-or-ie.md +++ b/docs/includes/use-legacy-edge-or-ie.md @@ -1,7 +1,7 @@ If your project is Node.js-based (that is, not developed with Visual Studio and Internet Information server (IIS)), you can force Office on Windows to use either the EdgeHTML webview control that is provided by Edge Legacy or the Trident webview control that is provided by Internet Explorer to run add-ins, even if you have a combination of Windows and Office versions that would normally use a more recent webview. For more information about which browsers and webviews are used by various combinations of Windows and Office versions, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). > [!NOTE] -> The tool that's used to force the change in webview is supported only in the Beta subscription channel of Microsoft 365. Join the [Microsoft 365 Insider program](https://insider.microsoft365.com/join/Windows) and select the **Beta Channel** option to access Office Beta builds. See also [About Office: What version of Office am I using?](https://support.microsoft.com/office/932788b8-a3ce-44bf-bb09-e334518b8b19). +> The tool that's used to force the change in webview is supported only in the Beta subscription channel of Microsoft 365. Join the [Microsoft 365 Insider program](https://techcommunity.microsoft.com/blog/microsoft365insiderblog/join-the-microsoft-365-insider-program-on-windows/4206638) and select the **Beta Channel** option to access Office Beta builds. See also [About Office: What version of Office am I using?](https://support.microsoft.com/office/932788b8-a3ce-44bf-bb09-e334518b8b19). > > Strictly, it's the `webview` switch of this tool (see **Step 2**) that requires the Beta channel. The tool has other switches that don't have this requirement. diff --git a/docs/includes/using-preview-apis-host.md b/docs/includes/using-preview-apis-host.md index 341c3f2f67..3f16b0c945 100644 --- a/docs/includes/using-preview-apis-host.md +++ b/docs/includes/using-preview-apis-host.md @@ -4,4 +4,4 @@ > To use preview APIs: > > - You must use the preview version of the Office JavaScript API library from the [Office.js content delivery network (CDN)](https://appsforoffice.microsoft.com/lib/beta/hosted/office.js). The [type definition file](https://appsforoffice.microsoft.com/lib/beta/hosted/office.d.ts) for TypeScript compilation and IntelliSense is found at the CDN and [DefinitelyTyped](https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/master/types/office-js-preview/index.d.ts). You can install these types with `npm install --save-dev @types/office-js-preview`. -> - You may need to join the [Microsoft 365 Insider program](https://insider.microsoft365.com/join) for access to more recent Office builds. +> - You may need to join the [Microsoft 365 Insider program](https://aka.ms/MSFT365InsiderProgram) for access to more recent Office builds. diff --git a/docs/includes/word-preview-apis-note.md b/docs/includes/word-preview-apis-note.md deleted file mode 100644 index 98ee49abda..0000000000 --- a/docs/includes/word-preview-apis-note.md +++ /dev/null @@ -1,7 +0,0 @@ -> [!IMPORTANT] -> Note that the following Word preview APIs may be available on the following platforms. -> -> - Word on Windows -> - Word on Mac -> -> Word preview APIs are currently not supported on iPad. However, bookmark feature APIs are also available in Word on the web. For APIs available only in Word on the web, see the [Web-only API list](#web-only-api-list). diff --git a/docs/includes/yo-office-next-steps.md b/docs/includes/yo-office-next-steps.md deleted file mode 100644 index b194237ade..0000000000 --- a/docs/includes/yo-office-next-steps.md +++ /dev/null @@ -1,2 +0,0 @@ -> [!TIP] -> You can ignore the *next steps* guidance that the Yeoman generator provides after the add-in project's been created. The step-by-step instructions within this article provide all of the guidance you'll need to complete this tutorial. \ No newline at end of file diff --git a/docs/index.yml b/docs/index.yml index d3d1a11d2d..b7935aa8d2 100644 --- a/docs/index.yml +++ b/docs/index.yml @@ -1,4 +1,4 @@ -### YamlMime:Hub +### YamlMime:Hub title: Office Add-ins documentation # < 60 chars summary: Use the Office Add-ins platform to build solutions that extend Office applications and interact with content in Office documents and in Outlook mail messages and calendar items. With Office Add-ins, you can use familiar web technologies such as HTML, CSS, and JavaScript to build solutions that can run in Office on the web, Windows, Mac, and mobile. # < 160 chars @@ -10,9 +10,11 @@ metadata: services: service ms.service: microsoft-365 ms.topic: hub-page # Required + ms.localizationpriority: high author: o365devx #Required; your GitHub user alias, with correct capitalization. ms.author: o365devx #Required; microsoft alias of author; optional team alias. - ms.date: 07/18/2024 #Required; mm/dd/yyyy format. + ms.date: 01/16/2025 #Required; mm/dd/yyyy format. + ms.custom: required-for-compliance # Indicates that this page is linked to in a legal document. # highlightedContent section # Maximum of 8 items @@ -49,16 +51,16 @@ productDirectory: - title: Add-in scenarios imageSrc: images/index-landing-page/i_code-blocks.svg links: + - url: develop/enable-nested-app-authentication-in-your-add-in.md + text: Enable single sign-on in an Office Add-in using nested app authentication - url: excel/pnp-open-in-excel.md text: Create an Excel spreadsheet with your add-in from a web page - url: outlook/smart-alerts-onmessagesend-walkthrough.md - text: Automatically check for an attachment before a message is sent + text: Automatically check for an attachment before a message is sent in Outlook - url: outlook/spam-reporting.md - text: Implement an integrated spam-reporting add-in + text: Implement an integrated spam-reporting Outlook add-in - url: word/import-template.md text: Import a Word document template with a Word add-in - - url: develop/create-sso-office-add-ins-nodejs.md - text: Use single sign-on authentication in an Office Add-in - title: Explore the code imageSrc: images/index-landing-page/i_reference.svg @@ -131,6 +133,9 @@ conceptualContent: # Card 5 - title: Publish links: + - url: /partner-center/marketplace-offers/open-a-developer-account + itemType: overview + text: Create a Partner Center account for Microsoft Marketplace - url: /partner-center/marketplace-offers/checklist itemType: overview text: Validate your Office Add-in diff --git a/docs/onenote/index.yml b/docs/onenote/index.yml index 46bb72f66f..c9954ec74c 100644 --- a/docs/onenote/index.yml +++ b/docs/onenote/index.yml @@ -1,15 +1,15 @@ ### YamlMime:Landing title: OneNote add-ins documentation # < 60 chars -summary: With OneNote add-ins, you can use familiar web technologies such as HTML, CSS, and JavaScript to build a solution that can run in OneNote on the web. Learn how to build, test, debug, and publish OneNote add-ins. # < 160 chars +summary: Build OneNote add-ins using familiar web technologies like HTML, CSS, and JavaScript. Learn how to build, test, debug, and publish OneNote add-ins. # < 160 chars metadata: title: OneNote add-ins documentation # Required; page title displayed in search results. Include the brand. < 60 chars. - description: Resources for learning about OneNote add-ins. # Required; article description that is displayed in search results. < 160 chars. + description: Learn how to build OneNote add-ins using web technologies. # Required; article description that is displayed in search results. < 160 chars. ms.service: onenote #Required ms.topic: landing-page # Required - ms.date: 07/22/2024 #Required; mm/dd/yyyy format. - ms.localizationpriority: high + ms.date: 09/24/2025 #Required; mm/dd/yyyy format. + ms.localizationpriority: medium # linkListType: architecture | concept | deploy | download | get-started | how-to-guide | learn | overview | quickstart | reference | sample | tutorial | video | whats-new @@ -24,8 +24,8 @@ landingContent: links: - text: Build your first OneNote add-in url: ../quickstarts/onenote-quickstart.md - - text: "Sample: Rubric Grader Task Pane Add-in" - url: https://github.com/OfficeDev/OneNote-Add-in-Rubric-Grader + - text: "Sample: Rubric grader task pane add-in" + url: https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/onenote-add-in-rubric-grader # Card (optional) - title: About OneNote add-ins @@ -64,7 +64,21 @@ landingContent: url: ../testing/test-debug-office-add-ins.md - text: Deploy and publish a OneNote add-in url: ../publish/publish.md + + # Card (optional) + - title: Resources + linkLists: - linkListType: reference links: + - text: Ask questions + url: https://stackoverflow.com/questions/tagged/office-js + - text: Request features + url: https://feedbackportal.microsoft.com/feedback/forum/c06dcc30-2e1c-ec11-b6e7-0022481f8472 + - text: Report issues + url: https://github.com/officedev/office-js/issues + - text: Join Office Add-ins community call + url: https://learn.microsoft.com/office/dev/add-ins/overview/office-add-ins-community-call - text: Office Add-ins additional resources url: ../resources/resources-links-help.md + - text: Download samples + url: https://developer.microsoft.com/microsoft-365/gallery/?search=&filterBy=OneNote,Samples diff --git a/docs/onenote/onenote-add-ins-page-content.md b/docs/onenote/onenote-add-ins-page-content.md index 2804db82eb..cfb0da8dd0 100644 --- a/docs/onenote/onenote-add-ins-page-content.md +++ b/docs/onenote/onenote-add-ins-page-content.md @@ -1,7 +1,7 @@ --- title: Work with OneNote page content description: Learn how to work with OneNote page content using the JavaScript API. -ms.date: 03/19/2019 +ms.date: 09/24/2025 ms.localizationpriority: medium --- @@ -45,12 +45,12 @@ The OneNote add-in JavaScript API supports the following HTML for creating and u > [!NOTE] > Importing HTML into OneNote consolidates whitespace. The resulting content is pasted into one outline. -OneNote does its best to translate HTML into page content while ensuring security for users. HTML and CSS standards do not exactly match OneNote's content model, so there will be differences in appearances, particularly with CSS stylings. We recommend using the JavaScript objects if specific formatting is needed. +OneNote does its best to translate HTML into page content while ensuring security for users. HTML and CSS standards don't exactly match OneNote's content model, so there will be differences in appearance, particularly with CSS styling. We recommend using the JavaScript objects if specific formatting is needed. -## Accessing page contents +## Access page content -You are only able to access *Page Content* via `Page#load` for the currently -active page. To change the active page, invoke `navigateToPage($page)`. + +You can only access *Page Content* via `Page#load` for the currently active page. To change the active page, invoke `navigateToPage($page)`. Metadata such as title can still be queried for any page. @@ -58,5 +58,5 @@ Metadata such as title can still be queried for any page. - [OneNote JavaScript API programming overview](onenote-add-ins-programming-overview.md) - [OneNote JavaScript API reference](../reference/overview/onenote-add-ins-javascript-reference.md) -- [Rubric Grader sample](https://github.com/OfficeDev/OneNote-Add-in-Rubric-Grader) +- [Sample: Rubric grader task pane add-in for OneNote on the web](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/onenote-add-in-rubric-grader) - [Office Add-ins platform overview](../overview/office-add-ins.md) diff --git a/docs/onenote/onenote-add-ins-programming-overview.md b/docs/onenote/onenote-add-ins-programming-overview.md index 93688bb672..713f0c2bea 100644 --- a/docs/onenote/onenote-add-ins-programming-overview.md +++ b/docs/onenote/onenote-add-ins-programming-overview.md @@ -1,7 +1,7 @@ --- title: OneNote JavaScript API programming overview description: Learn about the OneNote JavaScript API for OneNote add-ins on the web. -ms.date: 07/22/2024 +ms.date: 09/24/2025 ms.topic: overview ms.custom: scenarios:getting-started ms.localizationpriority: medium @@ -9,15 +9,15 @@ ms.localizationpriority: medium # OneNote JavaScript API programming overview -OneNote introduces a JavaScript API for OneNote add-ins on the web. You can create task pane add-ins, content add-ins, and add-in commands that interact with OneNote objects and connect to web services or other web-based resources. +The OneNote JavaScript API lets you build add-ins that extend OneNote on the web. You can create task pane add-ins, content add-ins, and add-in commands that interact with OneNote objects and connect to web services or other resources. [!INCLUDE [publish policies note](../includes/note-publish-policies.md)] ## Components of an Office Add-in -Add-ins consist of two basic components: +Office Add-ins have two main components: -- A **web application** consisting of a webpage and any required JavaScript, CSS, or other files. These files are hosted on a web server or web hosting service, such as Microsoft Azure. In OneNote on the web, the web application displays in a webview control or iframe. +- A **web application** with a webpage and any required JavaScript, CSS, or other files. These files are hosted on a web server or web hosting service, such as Microsoft Azure. In OneNote on the web, the web application displays in a webview control or iframe. - A **manifest** that specifies the URL of the add-in's webpage and any access requirements, settings, and capabilities for the add-in. This file is stored on the client. OneNote add-ins use the [add-in only manifest](../develop/add-in-manifests.md) format. @@ -29,12 +29,12 @@ Add-ins consist of two basic components: Add-ins use the runtime context of the Office application to access the JavaScript API. The API has two layers: -- A **application-specific API** for OneNote-specific operations, accessed through the `Application` object. +- An **application-specific API** for OneNote-specific operations, accessed through the `Application` object. - A **Common API** that's shared across Office applications, accessed through the `Document` object. -### Accessing the application-specific API through the *Application* object +### Access the application-specific API through the *Application* object -Use the `Application` object to access OneNote objects such as **Notebook**, **Section**, and **Page**. With application-specific APIs, you run batch operations on proxy objects. The basic flow goes something like this: +Use the `Application` object to access OneNote objects such as **Notebook**, **Section**, and **Page**. With application-specific APIs, you run batch operations on proxy objects. The basic flow works like this: 1. Get the application instance from the context. @@ -80,7 +80,7 @@ You can find supported OneNote objects and operations in the [API reference](../ Requirement sets are named groups of API members. Office Add-ins use requirement sets specified in the manifest or use a runtime check to determine whether an Office application supports APIs that an add-in needs. For detailed information about OneNote JavaScript API requirement sets, see [OneNote JavaScript API requirement sets](/javascript/api/requirement-sets/onenote/onenote-api-requirement-sets). -### Accessing the Common API through the *Document* object +### Access the Common API through the *Document* object Use the `Document` object to access the Common API, such as the [getSelectedDataAsync](/javascript/api/office/office.document#office-office-document-getselecteddataasync-member(1)) and [setSelectedDataAsync](/javascript/api/office/office.document#office-office-document-setselecteddataasync-member(1)) methods. @@ -112,7 +112,7 @@ OneNote add-ins support only the following Common APIs. | [Office.context.document.settings.set(name, value);](/javascript/api/office/office.settings#office-office-settings-set-member(1)) | Settings are supported by content add-ins only | | [Office.EventType.DocumentSelectionChanged](/javascript/api/office/office.documentselectionchangedeventargs) |*None*| -In general, you use the Common API to do something that isn't supported in the application-specific API. To learn more about using the Common API, see [Common JavaScript API object model](../develop/office-javascript-api-object-model.md). +In general, you use the Common API to do something that isn't supported in the application-specific API. For more about using the Common API, see [Common JavaScript API object model](../develop/office-javascript-api-object-model.md). @@ -127,4 +127,4 @@ The following diagram represents what's currently available in the OneNote JavaS - [Developing Office Add-ins](../develop/develop-overview.md) - [Build your first OneNote add-in](../quickstarts/onenote-quickstart.md) - [OneNote JavaScript API reference](../reference/overview/onenote-add-ins-javascript-reference.md) -- [Sample: Rubric Grader](https://github.com/OfficeDev/OneNote-Add-in-Rubric-Grader) +- [Sample: Rubric grader task pane add-in for OneNote on the web](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/onenote-add-in-rubric-grader) diff --git a/docs/outlook/add-and-remove-attachments-to-an-item-in-a-compose-form.md b/docs/outlook/add-and-remove-attachments-to-an-item-in-a-compose-form.md index f565d35b6a..b16c8abaf6 100644 --- a/docs/outlook/add-and-remove-attachments-to-an-item-in-a-compose-form.md +++ b/docs/outlook/add-and-remove-attachments-to-an-item-in-a-compose-form.md @@ -1,20 +1,24 @@ --- title: Add and remove attachments in an Outlook add-in description: Use various attachment APIs to manage the files or Outlook items attached to the item the user is composing. -ms.date: 06/04/2024 +ms.date: 03/12/2025 ms.topic: how-to ms.localizationpriority: medium --- # Manage an item's attachments in a compose form in Outlook -The Office JavaScript API provides several APIs you can use to manage an item's attachments when the user is composing. +The Office JavaScript API provides several APIs to manage an item's attachments when the user is composing a message or appointment. ## Attach a file or Outlook item -You can attach a file or Outlook item to a compose form by using the method that's appropriate for the type of attachment. +Attach a file or Outlook item to a compose form by using the method that's appropriate for the type of attachment. - [addFileAttachmentAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#methods): Attach a file. + + > [!NOTE] + > The `addFileAttachmentAsync` method was introduced in [requirement set 1.1](/javascript/api/requirement-sets/outlook/requirement-set-1.1/outlook-requirement-set-1.1) for Outlook on Windows (classic) and on Mac. Support for `addFileAttachmentAsync` in Outlook on the web and new Outlook on Windows was introduced in [requirement set 1.8](/javascript/api/requirement-sets/outlook/requirement-set-1.8/outlook-requirement-set-1.8). + - [addFileAttachmentFromBase64Async](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#methods): Attach a file using its Base64-encoded string. - [addItemAttachmentAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#methods): Attach an Outlook item. @@ -22,15 +26,15 @@ These are asynchronous methods, which means execution can go on without waiting If there are tasks that depend on the action to complete, you should carry out those tasks in a callback function. This callback function is optional and is invoked when the attachment upload has completed. The callback function takes an [AsyncResult](/javascript/api/office/office.asyncresult) object as an output parameter that provides any status, error, and returned value from adding the attachment. If the callback requires any extra parameters, you can specify them in the optional `options.asyncContext` parameter. `options.asyncContext` can be of any type that your callback function expects. -For example, you can define `options.asyncContext` as a JSON object that contains one or more key-value pairs. You can find more examples about passing optional parameters to asynchronous methods in the Office Add-ins platform in [Asynchronous programming in Office Add-ins](../develop/asynchronous-programming-in-office-add-ins.md#pass-optional-parameters-to-asynchronous-methods). The following example shows how to use the `asyncContext` parameter to pass two arguments to a callback function. +For example, you can define `options.asyncContext` as a JSON object that contains one or more key-value pairs. For more examples about passing optional parameters to asynchronous methods in the Office Add-ins platform, see [Asynchronous programming in Office Add-ins](../develop/asynchronous-programming-in-office-add-ins.md#pass-optional-parameters-to-asynchronous-methods). The following example shows how to use the `asyncContext` parameter to pass two arguments to a callback function. -```js +```javascript const options = { asyncContext: { var1: 1, var2: 2 } }; -Office.context.mailbox.item.addFileAttachmentAsync('https://contoso.com/rtm/icon.png', 'icon.png', options, callback); +Office.context.mailbox.item.addFileAttachmentAsync("https://contoso.com/rtm/icon.png", "icon.png", options, callback); ``` -You can check for success or error of an asynchronous method call in the callback function using the `status` and `error` properties of the `AsyncResult` object. If the attaching completes successfully, you can use the `AsyncResult.value` property to get the attachment ID. The attachment ID is an integer which you can subsequently use to remove the attachment. +To check for the outcome of an asynchronous method call in the callback function, use the `status` and `error` properties of the `AsyncResult` object. If the attaching completes successfully, use the `AsyncResult.value` property to get the attachment ID. The attachment ID is an integer which you can subsequently use to remove the attachment. > [!NOTE] > The attachment ID is valid only within the same session and isn't guaranteed to map to the same attachment across sessions. Examples of when a session is over include when the user closes the add-in, or if the user starts composing in an inline form and subsequently pops out the inline form to continue in a separate window. @@ -42,82 +46,75 @@ You can check for success or error of an asynchronous method call in the callbac You can attach a file to a message or appointment in a compose form by using the `addFileAttachmentAsync` method and specifying the URI of the file. You can also use the `addFileAttachmentFromBase64Async` method, specifying the Base64-encoded string as input. If the file is protected, you can include an appropriate identity or authentication token as a URI query string parameter. Exchange will make a call to the URI to get the attachment, and the web service which protects the file will need to use the token as a means of authentication. -The following JavaScript example is a compose add-in that attaches a file, picture.png, from a web server to the message or appointment being composed. The callback function takes `asyncResult` as a parameter, checks for the result status, and gets the attachment ID if the method succeeds. +> [!NOTE] +> +> - The URI of the file to be attached must support caching in production. The server hosting the image shouldn't return a `Cache-Control` header that specifies `no-cache`, `no-store`, or similar options in the HTTP response. However, when you're developing the add-in and making changes to files, caching can prevent you from seeing your changes. We recommend using `Cache-Control` headers during development. +> +> - The `addFileAttachmentAsync` method doesn't support bitmap (BMP) images if they're added as inline attachments. + +The following JavaScript example is a compose add-in that attaches a file, **picture.png**, from a web server to the message or appointment being composed. The callback function takes `asyncResult` as a parameter, checks for the result status, and gets the attachment ID if the method succeeds. + +```javascript +// Add the specified file attachment to the item +// being composed. +// When the attachment finishes uploading, the +// callback function is invoked and gets the attachment ID. +// You can optionally pass any object that you would +// access in the callback function as an argument to +// the asyncContext parameter. +Office.context.mailbox.item.addFileAttachmentAsync( + "https://webserver/picture.png", + "picture.png", + { asyncContext: { var1: 1, var2: 2 } }, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.error(asyncResult.error.message); + return; + } + + // Get the ID of the attached file. + const attachmentID = asyncResult.value; + console.log(`ID of added attachment: ${attachmentID}`); + } +); +``` -```js -Office.initialize = function () { - // Checks for the DOM to load using the jQuery ready method. - $(document).ready(function () { - // After the DOM is loaded, app-specific code can run. - // Add the specified file attachment to the item - // being composed. - // When the attachment finishes uploading, the - // callback function is invoked and gets the attachment ID. - // You can optionally pass any object that you would - // access in the callback function as an argument to - // the asyncContext parameter. - Office.context.mailbox.item.addFileAttachmentAsync( - `https://webserver/picture.png`, - 'picture.png', - { asyncContext: null }, - function (asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Failed){ - write(asyncResult.error.message); - } else { - // Get the ID of the attached file. - const attachmentID = asyncResult.value; - write('ID of added attachment: ' + attachmentID); - } - }); - }); -} +To add an inline Base64-encoded image to the body of a message or appointment being composed, use the [Body API](/javascript/api/outlook/office.body) methods, such as [prependAsync](/javascript/api/outlook/office.body#outlook-office-body-prependasync-member(1)), [setSignatureAsync](/javascript/api/outlook/office.body#outlook-office-body-setsignatureasync-member(1)), or [setAsync](/javascript/api/outlook/office.body#outlook-office-body-setasync-member(1)). -// Writes to a div with id='message' on the page. -function write(message){ - document.getElementById('message').innerText += message; -} -``` +> [!TIP] +> Before inserting the image inline using `Office.context.mailbox.item.body.setAsync`, you must first call `Office.context.mailbox.item.body.getAsync` to get the current body of the mail item. Otherwise, the image won't render in the body once it's inserted. For guidance, see the [Add inline Base64-encoded image to message or appointment body (Compose)](https://raw.githubusercontent.com/OfficeDev/office-js-snippets/refs/heads/main/samples/outlook/20-item-body/add-inline-base64-image.yaml) sample in [Script Lab](../overview/explore-with-script-lab.md). -To add an inline base64 image to the body of a message or appointment being composed, you must first get the current item body using the `Office.context.mailbox.item.body.getAsync` method before inserting the image using the `addFileAttachmentFromBase64Async` method. Otherwise, the image will not render in the body once it's inserted. For guidance, see the following JavaScript example, which adds an inline Base64 image to the beginning of an item body. +The following is an example of a Base64-encoded image prepended to the body of a mail item. -```js -const mailItem = Office.context.mailbox.item; +```javascript const base64String = "iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAnUExURQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN0S+bUAAAAMdFJOUwAQIDBAUI+fr7/P7yEupu8AAAAJcEhZcwAADsMAAA7DAcdvqGQAAAF8SURBVGhD7dfLdoMwDEVR6Cspzf9/b20QYOthS5Zn0Z2kVdY6O2WULrFYLBaLxd5ur4mDZD14b8ogWS/dtxV+dmx9ysA2QUj9TQRWv5D7HyKwuIW9n0vc8tkpHP0W4BOg3wQ8wtlvA+PC1e8Ao8Ld7wFjQtHvAiNC2e8DdqHqKwCrUPc1gE1AfRVgEXBfB+gF0lcCWoH2tYBOYPpqQCNwfT3QF9i+AegJfN8CtAWhbwJagtS3AbIg9o2AJMh9M5C+SVGBvx6zAfmT0r+Bv8JMwP4kyFPir+cswF5KL3WLv14zAFBCLf56Tw9cparFX4upgaJUtPhrOS1QlY5W+vWTXrGgBFB/b72ev3/0igUdQPppP/nfowfKUUEFcP207y/yxKmgAYQ+PywoAFOfCH3A2MdCFzD3kdADBvq10AGG+pXQBgb7pdAEhvuF0AIc/VtoAK7+JciAs38KIuDugyAC/v4hiMCE/i7IwLRBsh68N2WQjMVisVgs9i5bln8LGScNcCrONQAAAABJRU5ErkJggg=="; -// Get the current body of the message or appointment. -mailItem.body.getAsync(Office.CoercionType.Html, (bodyResult) => { - if (bodyResult.status === Office.AsyncResultStatus.Succeeded) { - // Insert the Base64 image to the beginning of the body. - const options = { isInline: true, asyncContext: bodyResult.value }; - mailItem.addFileAttachmentFromBase64Async(base64String, "sample.png", options, (attachResult) => { - if (attachResult.status === Office.AsyncResultStatus.Succeeded) { - let body = attachResult.asyncContext; - body = body.replace("

", `

`); - mailItem.body.setAsync(body, { coercionType: Office.CoercionType.Html }, (setResult) => { - if (setResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Inline Base64 image added to the body."); - } else { - console.log(setResult.error.message); - } - }); - } else { - console.log(attachResult.error.message); +// Add the Base64-encoded image to the beginning of the body. +Office.context.mailbox.item.addFileAttachmentFromBase64Async(base64String, "sample.png", { isInline: true }, (attachmentResult) => { + if (attachmentResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to attach file: ${attachmentResult.error.message}`); + return; + } + + Office.context.mailbox.item.body.prependAsync('', { coercionType: Office.CoercionType.Html }, (prependResult) => { + if (prependResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to prepend image to body: ${attachmentResult.error.message}`); + return; } - }); - } else { - console.log(bodyResult.error.message); - } + + console.log("Inline Base64-encoded image added to the beginning of the body."); + }) }); ``` ### Attach an Outlook item -You can attach an Outlook item (for example, email, calendar, or contact item) to a message or appointment in a compose form by specifying the Exchange Web Services (EWS) ID of the item and using the `addItemAttachmentAsync` method. You can get the EWS ID of an email, calendar, contact, or task item in the user's mailbox by using the [mailbox.makeEwsRequestAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox#methods) method and accessing the EWS operation [FindItem](/exchange/client-developer/web-service-reference/finditem-operation). The [item.itemId](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#properties) property also provides the EWS ID of an existing item in a read form. +To attach an Outlook item (for example, email, calendar, or contact item) to a message or appointment in a compose form, specify the Exchange Web Services (EWS) ID of the item and use the `addItemAttachmentAsync` method. To get the EWS ID of the item, use the [item.itemId](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#properties) property. -The following JavaScript function, `addItemAttachment`, extends the first example above, and adds an item as an attachment to the email or appointment that is being composed. The function takes as an argument the EWS ID of the item that is to be attached. If attaching succeeds, it gets the attachment ID for further processing, including removing that attachment in the same session. +The following JavaScript function, `addItemAttachment`, extends an earlier example, and adds an item as an attachment to the email or appointment being composed. The function takes the EWS ID of the item to be attached as an argument. If attaching succeeds, it gets the attachment ID for further processing. -```js +```javascript // Adds the specified item as an attachment to the composed item. // ID is the EWS ID of the item to be attached. function addItemAttachment(itemId) { @@ -130,16 +127,18 @@ function addItemAttachment(itemId) { // the asyncContext parameter. Office.context.mailbox.item.addItemAttachmentAsync( itemId, - 'Welcome email', - { asyncContext: null }, - function (asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Failed){ - write(asyncResult.error.message); - } else { - const attachmentID = asyncResult.value; - write('ID of added attachment: ' + attachmentID); + "Welcome email", + { asyncContext: { var1: 1, var2: 2 } }, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.error(asyncResult.error.message); + return; } - }); + + const attachmentID = asyncResult.value; + console.log(`ID of added attachment: ${attachmentID}`); + } + ); } ``` @@ -148,22 +147,25 @@ function addItemAttachment(itemId) { ## Get attachments -APIs to get attachments in compose mode are available from [requirement set 1.8](/javascript/api/requirement-sets/outlook/requirement-set-1.8/outlook-requirement-set-1.8). +The following APIs to get attachments in compose mode are available from [requirement set 1.8](/javascript/api/requirement-sets/outlook/requirement-set-1.8/outlook-requirement-set-1.8). - [getAttachmentsAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#methods) - [getAttachmentContentAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#methods) -You can use the [getAttachmentsAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#methods) method to get the attachments of the message or appointment being composed. +Use the [getAttachmentsAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#methods) method to get the attachments of the message or appointment being composed. -To get an attachment's content, you can use the [getAttachmentContentAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#methods) method. The supported formats are listed in the [AttachmentContentFormat](/javascript/api/outlook/office.mailboxenums.attachmentcontentformat) enum. +> [!NOTE] +> In Outlook on the web and the new Outlook on Windows, users can select the **Upload and share** option to upload an attachment to OneDrive and include a link to the file in the mail item. However, since only a link is included, `getAttachmentsAsync` doesn't return this type of attachment. + +To get an attachment's content, use the [getAttachmentContentAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#methods) method. The supported formats are listed in the [AttachmentContentFormat](/javascript/api/outlook/office.mailboxenums.attachmentcontentformat) enum. You should provide a callback function to check for the status and any error by using the `AsyncResult` output parameter object. You can also pass any additional parameters to the callback function by using the optional `asyncContext` parameter. The following JavaScript example gets the attachments and allows you to set up distinct handling for each supported attachment format. -```js +```javascript const item = Office.context.mailbox.item; -const options = {asyncContext: {currentItem: item}}; +const options = { asyncContext: { currentItem: item } }; item.getAttachmentsAsync(options, callback); function callback(result) { @@ -195,16 +197,19 @@ function handleAttachmentsCallback(result) { } ``` +> [!TIP] +> If the Outlook client in which your add-in is running doesn't support Mailbox requirement set 1.8, you can still get an attachment and its contents from an item being composed using Microsoft Graph or EWS. To learn more, see [Get an Outlook item's attachments from Exchange](get-attachments-of-an-outlook-item.md). + ## Remove an attachment -You can remove a file or item attachment from a message or appointment item in a compose form by specifying the corresponding attachment ID when using the [removeAttachmentAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#methods) method. +To remove a file or item attachment from a message or appointment item in a compose form, specify the corresponding attachment ID in the [removeAttachmentAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#methods) method. > [!IMPORTANT] > If you're using requirement set 1.7 or earlier, you should only remove attachments that the same add-in has added in the same session. Similar to the `addFileAttachmentAsync`, `addItemAttachmentAsync`, and `getAttachmentsAsync` methods, `removeAttachmentAsync` is an asynchronous method. You should provide a callback function to check for the status and any error by using the `AsyncResult` output parameter object. You can also pass any additional parameters to the callback function by using the optional `asyncContext` parameter. -The following JavaScript function, `removeAttachment`, continues to extend the examples above, and removes the specified attachment from the email or appointment that is being composed. The function takes as an argument the ID of the attachment to be removed. You can obtain the ID of an attachment after a successful `addFileAttachmentAsync`, `addFileAttachmentFromBase64Async`, or `addItemAttachmentAsync` method call, and use it in a subsequent `removeAttachmentAsync` method call. You can also call `getAttachmentsAsync` (introduced in requirement set 1.8) to get the attachments and their IDs for that add-in session. +The following JavaScript function, `removeAttachment`, continues to extend the examples above, and removes the specified attachment from the email or appointment being composed. The function takes as an argument the ID of the attachment to be removed. You can obtain the ID of an attachment after a successful `addFileAttachmentAsync`, `addFileAttachmentFromBase64Async`, or `addItemAttachmentAsync` method call, and use it in a subsequent `removeAttachmentAsync` method call. You can also call `getAttachmentsAsync` (introduced in requirement set 1.8) to get the attachments and their IDs for that add-in session. ```js // Removes the specified attachment from the composed item. @@ -217,13 +222,15 @@ function removeAttachment(attachmentId) { Office.context.mailbox.item.removeAttachmentAsync( attachmentId, { asyncContext: null }, - function (asyncResult) { + (asyncResult) => { if (asyncResult.status === Office.AsyncResultStatus.Failed) { - write(asyncResult.error.message); - } else { - write('Removed attachment with the ID: ' + asyncResult.value); + console.error(asyncResult.error.message); + return; } - }); + + console.log(`Removed attachment with the ID: ${asyncResult.value}`); + } + ); } ``` @@ -232,6 +239,6 @@ function removeAttachment(attachmentId) { ## See also -- [Create Outlook add-ins for compose forms](compose-scenario.md) +- [Get an Outlook item's attachments from Exchange](get-attachments-of-an-outlook-item.md) - [Asynchronous programming in Office Add-ins](../develop/asynchronous-programming-in-office-add-ins.md) - [Limits for activation and JavaScript API for Outlook add-ins](limits-for-activation-and-javascript-api-for-outlook-add-ins.md) diff --git a/docs/outlook/add-in-requirements.md b/docs/outlook/add-in-requirements.md deleted file mode 100644 index 01fdcee1ef..0000000000 --- a/docs/outlook/add-in-requirements.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Outlook add-in requirements -description: For Outlook add-ins to load and function properly, there are a number of requirements for both the servers and the clients. -ms.date: 02/29/2024 -ms.localizationpriority: high ---- - -# Outlook add-in requirements - -For Outlook add-ins to load and function properly, there are a number of requirements for both the servers and the clients. - -## Client requirements - -- The client must be one of the supported applications for Outlook add-ins. The following clients support add-ins. - - - Outlook on the web for Exchange 2016 or later - - Outlook.com - - [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) - - Outlook 2016 or later on Windows - - Outlook on Mac - - Outlook on Android - - Outlook on iOS - -- The client must be connected to an Exchange server or Microsoft 365 using a direct connection. When configuring the client, the user must choose an **Exchange**, **Office**, or **Outlook.com** account type. If the client is configured to connect with POP3 or IMAP, add-ins will not load. - -## Mail server requirements - -If the user is connected to Microsoft 365 or Outlook.com, mail server requirements are all taken care of already. However, for users connected to on-premises installations of Exchange Server, the following requirements apply. - -- The server must be Exchange 2016 or later. -- Exchange Web Services (EWS) must be enabled and must be exposed to the Internet. Many add-ins require EWS to function properly. -- The server must have a valid authentication certificate in order for the server to issue valid identity tokens. New installations of Exchange Server include a default authentication certificate. For more information, see [Digital certificates and encryption in Exchange 2016](/Exchange/architecture/client-access/certificates) and [Set-AuthConfig](/powershell/module/exchange/organization/Set-AuthConfig). -- To access add-ins from [AppSource](https://appsource.microsoft.com/marketplace/apps?product=office), the client access servers must be able to communicate with AppSource. - -## Add-in server requirements - -Add-in files (HTML, JavaScript, etc.) can be hosted on any web server platform desired. The only requirement is that the server must be configured to use HTTPS, and the SSL certificate must be trusted by the client. - -## See also - -- [Requirements for running Office Add-ins](../concepts/requirements-for-running-office-add-ins.md) -- [Office client application and platform availability for Office Add-ins (Outlook section)](/javascript/api/requirement-sets#outlook) -- [Outlook JavaScript API requirement set support](/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets#requirement-sets-supported-by-exchange-servers-and-outlook-clients) diff --git a/docs/outlook/add-mobile-support.md b/docs/outlook/add-mobile-support.md index 614cf48d06..3c781d80f2 100644 --- a/docs/outlook/add-mobile-support.md +++ b/docs/outlook/add-mobile-support.md @@ -1,13 +1,13 @@ ---- +--- title: Add support for add-in commands in Outlook on mobile devices description: Learn how to add support for Outlook on mobile devices including how to update the add-in manifest and change your code for mobile scenarios, if necessary. -ms.date: 07/18/2024 +ms.date: 08/01/2025 ms.localizationpriority: medium --- # Add support for add-in commands in Outlook on mobile devices -Using add-in commands in Outlook on mobile devices allows your users to access the same functionality (with some [limitations](#code-considerations)) that they already have in Outlook on the web, on Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic), and on Mac. Adding support for Outlook mobile requires updating the add-in manifest and possibly changing your code for mobile scenarios. +Implement add-in commands in Outlook on mobile devices to access the same functionality (with some [limitations](#code-considerations)) that you already have in Outlook on the web, on Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic), and on Mac. Adding support for Outlook mobile requires updating the add-in manifest and possibly changing your code for mobile scenarios. ## Update the manifest @@ -15,16 +15,18 @@ The first step to enabling add-in commands in Outlook mobile is to define them i # [Unified manifest for Microsoft 365](#tab/jsonmanifest) -1. In the "extensions.ribbons.requirements.formFactors" array, add "mobile" as an item. When you are finished, the array should look like the following. +[!INCLUDE [outlook-unified-manifest-mobile](../includes/outlook-unified-manifest-mobile.md)] + +1. In the [`"extensions.ribbons.requirements.formFactors"`](/microsoft-365/extensibility/schema/requirements-extension-element#formfactors) array, add `"mobile"` as an item. When you are finished, the array should look like the following. ```json "formFactors": [ "mobile", - + ] ``` -1. If your add-in uses Appointment Attendee mode, such as an add-in that integrates a provider of a note-taking or customer relationship management (CRM) application, add "logEventMeetingDetailsAttendee" to the "extensions.ribbons.contexts" array. The following is an example. +1. If your add-in uses Appointment Attendee mode, such as an add-in that integrates a provider of a note-taking or customer relationship management (CRM) application, add `"logEventMeetingDetailsAttendee"` to the [`"extensions.ribbons.contexts"`](/microsoft-365/extensibility/schema/extension-ribbons-array#contexts) array. The following is an example. ```json "contexts": [ @@ -33,7 +35,7 @@ The first step to enabling add-in commands in Outlook mobile is to define them i ], ``` -1. If your add-in uses an integrated online meeting provider, add "onlineMeetingDetailsOrganizer" to the "extensions.ribbons.contexts" array. The following is an example. +1. If your add-in uses an integrated online meeting provider, add `"onlineMeetingDetailsOrganizer"` to the `"extensions.ribbons.contexts"` array. The following is an example. ```json "contexts": [ @@ -42,13 +44,13 @@ The first step to enabling add-in commands in Outlook mobile is to define them i ], ``` -1. In the "extensions.ribbons.tabs" array, find the tab with the "builtInTabId" of "TabDefault". Add a child "customMobileRibbonGroups" array to it (as a peer of the existing "groups" property). Inside this array, create an object and do the following: +1. In the [`"extensions.ribbons.tabs"`](/microsoft-365/extensibility/schema/extension-ribbons-array#tabs) array, find the tab with the `"builtInTabId"` of `"TabDefault"`. Add a child `"customMobileRibbonGroups"` array to it (as a peer of the existing `"groups"` property). Inside this array, create an object and do the following: - - Set appropriate "id" and "label" values. - - Create an object in the "controls" array to represent a button and configure it as follows. - - Set appropriate "id" and "label" values. To ensure that the button fits correctly in the ribbon, we recommend that you limit the "label" to 16 characters. - - Set "buttonType" to "MobileButton". - - Assign a function to the "actionId" property. This should match the "id" of the object in the "extensions.runtimes.actions" array. + - Set appropriate `"id"` and `"label"` values. + - Create an object in the `"controls"` array to represent a button and configure it as follows. + - Set appropriate `"id"` and `"label"` values. To ensure that the button fits correctly in the ribbon, we recommend that you limit the `"label"` to 16 characters. + - Set `"type"` to `"mobileButton"`. + - Assign a function to the `"actionId"` property. This should match the `"id"` of the object in the `"extensions.runtimes.actions"` array. - Be sure you have all nine required icons. The following is an example. @@ -58,7 +60,7 @@ The first step to enabling add-in commands in Outlook mobile is to define them i { "builtInTabId": "TabDefault", "groups": [ - <-- non-mobile group objects omitted --> + <-- Non-mobile group objects omitted. --> ], "customMobileRibbonGroups": [ { @@ -68,7 +70,7 @@ The first step to enabling add-in commands in Outlook mobile is to define them i { "id": "mobileInsertMeetingButton", "label": "Add meeting", - "buttonType": "MobileButton", + "type": "mobileButton", "actionId": "insertContosoMeeting", "icons": [ { @@ -127,65 +129,66 @@ The first step to enabling add-in commands in Outlook mobile is to define them i # [Add-in only manifest](#tab/xmlmanifest) -The [VersionOverrides](/javascript/api/manifest/versionoverrides) v1.1 schema defines a new form factor for mobile, [MobileFormFactor](/javascript/api/manifest/mobileformfactor). +The [VersionOverrides](/javascript/api/manifest/versionoverrides) v1.1 schema defines a new form factor for mobile, [MobileFormFactor](/javascript/api/manifest/mobileformfactor). The `` element contains all of the information for loading the add-in in mobile clients. This way, you can define completely different UI elements and JavaScript files for the mobile experience. -This element contains all of the information for loading the add-in in mobile clients. This enables you to define completely different UI elements and JavaScript files for the mobile experience. +The following example shows a single task pane button in a `` element. This is very similar to the elements that appear in a [DesktopFormFactor](/javascript/api/manifest/desktopformfactor) element, with some notable differences. -The following example shows a single task pane button in a **\** element. +- The [OfficeTab](/javascript/api/manifest/officetab) element isn't used. +- The [ExtensionPoint](/javascript/api/manifest/extensionpoint) element must have only one child element. If your add-in implements the [MobileOnlineMeetingCommandSurface](/javascript/api/manifest/extensionpoint#mobileonlinemeetingcommandsurface) or [MobileLogEventAppointmentAttendee](/javascript/api/manifest/extensionpoint#mobilelogeventappointmentattendee) extension point, you must include a [Control](/javascript/api/manifest/control) child element. If your add-in implements the [MobileMessageReadCommandSurface](/javascript/api/manifest/extensionpoint#mobilemessagereadcommandsurface) extension point, you must include a [Group](/javascript/api/manifest/group) child element that contains multiple `` elements. +- There is no `Menu` type equivalent for the `` element. +- The [Supertip](/javascript/api/manifest/supertip) element isn't used. +- The required icon sizes are different. Mobile add-ins minimally must support 25x25, 32x32 and 48x48 pixel icons. For more information, see [Additional requirements for mobile form factors](/javascript/api/manifest/icon#additional-requirements-for-mobile-form-factors). ```xml - - ... - - - - - - - - ... + + + ... + + + ... + + + + + + + + + + ... + ``` -This is very similar to the elements that appear in a [DesktopFormFactor](/javascript/api/manifest/desktopformfactor) element, with some notable differences. - -- The [OfficeTab](/javascript/api/manifest/officetab) element isn't used. -- The [ExtensionPoint](/javascript/api/manifest/extensionpoint) element must have only one child element. If your add-in implements the [MobileOnlineMeetingCommandSurface](/javascript/api/manifest/extensionpoint#mobileonlinemeetingcommandsurface) or [MobileLogEventAppointmentAttendee](/javascript/api/manifest/extensionpoint#mobilelogeventappointmentattendee) extension point, you must include a [Control](/javascript/api/manifest/control) child element. If your add-in implements the [MobileMessageReadCommandSurface](/javascript/api/manifest/extensionpoint#mobilemessagereadcommandsurface) extension point, you must include a [Group](/javascript/api/manifest/group) child element that contains multiple **\** elements. -- There is no `Menu` type equivalent for the **\** element. -- The [Supertip](/javascript/api/manifest/supertip) element isn't used. -- The required icon sizes are different. Mobile add-ins minimally must support 25x25, 32x32 and 48x48 pixel icons. For more information, see [Additional requirements for mobile form factors](/javascript/api/manifest/icon#additional-requirements-for-mobile-form-factors). - --- ## Code considerations Designing an add-in for mobile introduces some additional considerations. -### Use REST instead of Exchange Web Services - -The [Office.context.mailbox.makeEwsRequestAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox#methods) method isn't supported in Outlook mobile. Add-ins should prefer to get information from the Office.js API when possible. If add-ins require information not exposed by the Office.js API, then they should use the [Outlook REST APIs](use-rest-api.md) to access the user's mailbox. +### Use Microsoft Graph -Mailbox requirement set 1.5 introduced a new version of [Office.context.mailbox.getCallbackTokenAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox#methods) that can request an access token compatible with the REST APIs, and a new [Office.context.mailbox.restUrl](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox#properties) property that can be used to find the REST API endpoint for the user. +Add-ins should prefer to get information from the Office.js API when possible. If your add-in requires information not exposed by the Office.js API, use [Microsoft Graph](/graph/overview) to access the user's mailbox. ### Pinch zoom diff --git a/docs/outlook/apis.md b/docs/outlook/apis.md index 2610d01cc8..184cbb300d 100644 --- a/docs/outlook/apis.md +++ b/docs/outlook/apis.md @@ -1,7 +1,7 @@ ---- +--- title: Outlook add-in APIs description: Learn how to reference the Outlook add-in APIs and declare permissions in your Outlook add-in. -ms.date: 04/12/2024 +ms.date: 01/07/2025 ms.topic: overview ms.localizationpriority: medium --- @@ -12,7 +12,7 @@ To use APIs in your Outlook add-in, you must specify the location of the Office. ## Office.js library -To interact with the [Outlook add-in API](/javascript/api/outlook), you need to use the JavaScript APIs in Office.js. The content delivery network (CDN) for the library is `https://appsforoffice.microsoft.com/lib/1/hosted/Office.js`. Add-ins submitted to AppSource must reference Office.js by this CDN; they can't use a local reference. +To interact with the [Outlook add-in API](/javascript/api/outlook), you need to use the JavaScript APIs in Office.js. The content delivery network (CDN) for the library is `https://appsforoffice.microsoft.com/lib/1/hosted/Office.js`. Add-ins submitted to Microsoft Marketplace must reference Office.js by this CDN; they can't use a local reference. Reference the CDN in a ``, then add the following code after it. This adds a reference to the **commands.js** file. +1. Locate ``, then add the following code after it. This adds a reference to the **commands.js** file. ```html @@ -659,7 +661,7 @@ In this section, learn how to display the logged appointment notes and other det 1. Open the **./src/taskpane/taskpane.html** file of your add-in project. -1. Locate ``, then add the following code after it. This references the **taskpane.js** file. +1. Locate ``, then add the following code after it. This references the **taskpane.js** file. ```html diff --git a/docs/outlook/notifications.md b/docs/outlook/notifications.md new file mode 100644 index 0000000000..3019fb00d5 --- /dev/null +++ b/docs/outlook/notifications.md @@ -0,0 +1,277 @@ +--- +title: Create notifications for your Outlook add-in +description: Learn about the types of notification messages you can create for your Outlook add-in. +ms.date: 05/29/2025 +ms.localizationpriority: medium +--- + +# Create notifications for your Outlook add-in + +Implement notification messages for your Outlook add-in to keep your users informed about important events, feedback, or errors with minimal disruption to their workflow. + +> [!NOTE] +> Support for the notifications API was introduced in Mailbox requirement set 1.3. Additional features were introduced in later requirement sets. To determine if your client supports these requirement sets, see [Outlook client support](/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets#outlook-client-support). + +## Supported Outlook surfaces and modes + +Notification messages are supported on messages and appointments in both read and compose modes. They're displayed above the body of the mail item. + +:::image type="content" source="../images/outlook-notification.png" alt-text="An insight notification displayed in an appointment in compose mode."::: + +To manage a notification on a mail item, call [Office.context.mailbox.item.notificationMessages](/javascript/api/requirement-sets/outlook/requirement-set-1.3/office.context.mailbox.item#properties) in your add-in's JavaScript code. This property returns a [NotificationMessages](/javascript/api/outlook/office.notificationmessages) object with methods to add, remove, get, or replace notifications. The following code shows how to use these methods to manage your add-in's notifications. + +```javascript +const notificationMessages = Office.context.mailbox.item.notificationMessages; + +// Sample informational message. +const notificationDetails = { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "This is a sample notification message.", + icon: "icon-16", + persistent: false +}; + +const notificationKey = "notification_01"; + +// Add a notification to the mail item. +notificationMessages.addAsync(notificationKey, notificationDetails, (result) => { + console.log("Added an informational notification."); +}); + +// Get all the notifications of the mail item. +notificationMessages.getAllAsync((result) => { + console.log(JSON.stringify(result.value)); +}); + +// Replace a notification. +const newNotification = { + type: Office.MailboxEnums.ItemNotificationMessageType.ErrorMessage, + message: "This is a sample error message." +}; + +notificationMessages.replaceAsync(notificationKey, newNotification, (result) => { + console.log("Replaced the existing notification."); +}); + +// Remove a notification. +notificationMessages.removeAsync(notificationKey, (result) => { + console.log("Removed the notification."); +}); +``` + +## Types of notifications + +A notification consists of a unique identifier, an icon, and a message. Depending on the type, it could also include a **Dismiss** action or a custom action. There are different [types of notifications](/javascript/api/outlook/office.mailboxenums.itemnotificationmessagetype) you can display to the user to fit your particular scenario. + +- [ErrorMessage](#errormessage) +- [InformationalMessage](#informationalmessage) +- [InsightMessage](#insightmessage) +- [ProgressIndicator](#progressindicator) + +The following sections describe each notification type, including its [properties](/javascript/api/outlook/office.notificationmessagedetails) and supported platforms. + +### ErrorMessage + +:::row::: + :::column::: + **Description** + :::column-end::: + :::column span="3"::: + Alerts the user about an error or failed operation. For example, use the `ErrorMessage` type to notify the user that their personalized signature wasn't successfully added to a message. + +:::image type="content" source="../images/outlook-error-notification.png" alt-text="An error message notification."::: + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Properties** + :::column-end::: + :::column span="3"::: + - Displays an error icon. This icon can't be customized. + - Includes a **Dismiss** action to close the notification. If a user doesn't dismiss the error notification, it remains visible until the user sees it once before switching to another mail item. + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Minimum supported requirement set** + :::column-end::: + :::column span="3"::: + [1.3](/javascript/api/requirement-sets/outlook/requirement-set-1.3/outlook-requirement-set-1.3) + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Supported platforms** + :::column-end::: + :::column span="3"::: + - Web + - Windows (new and classic) + - Mac + - Android + - iOS + :::column-end::: +:::row-end::: + +### InformationalMessage + +:::row::: + :::column::: + **Description** + :::column-end::: + :::column span="3"::: + Provides information or feedback to the user. For example, use the `InformationalMessage` type to notify the user that their file upload completed successfully. + +:::image type="content" source="../images/outlook-informational-notification.png" alt-text="An informational notification."::: + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Properties** + :::column-end::: + :::column span="3"::: + - Must specify an icon. Although an icon is required, the custom icon is currently displayed only in classic Outlook on Windows. On other platforms, an information icon is shown. + - Includes a **Dismiss** action to close the notification. + - Can be customized to persist even after a user switches to another mail item. The notification remains until the add-in removes it or the user selects **Dismiss**. + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Minimum supported requirement set** + :::column-end::: + :::column span="3"::: + [1.3](/javascript/api/requirement-sets/outlook/requirement-set-1.3/outlook-requirement-set-1.3) + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Supported platforms** + :::column-end::: + :::column span="3"::: + - Web + - Windows (new and classic) + - Mac + - Android + - iOS + :::column-end::: +:::row-end::: + +### InsightMessage + +:::row::: + :::column::: + **Description** + :::column-end::: + :::column span="3"::: + Provides information or feedback to the user with an option to perform an action. For example, use the `InsightMessage` type to recommend adding catering services to a meeting with external recipients. + +:::image type="content" source="../images/outlook-insight-notification.png" alt-text="An insight message notification."::: + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Properties** + :::column-end::: + :::column span="3"::: + - Must specify an icon. Although an icon is required, the custom icon is displayed only in classic Outlook on Windows. On other platforms, an information icon is shown. + - Includes an option to perform one [action](/javascript/api/outlook/office.notificationmessageaction). Currently, opening the add-in's task pane is the only supported action. + - Includes a **Dismiss** action to close the notification. + - Doesn't persist when a user switches to another mail item. + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Minimum supported requirement set** + :::column-end::: + :::column span="3"::: + [1.10](/javascript/api/requirement-sets/outlook/requirement-set-1.10/outlook-requirement-set-1.10) + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Supported platforms** + :::column-end::: + :::column span="3"::: + - Web + - Windows (new and classic) + - Mac + :::column-end::: +:::row-end::: + +### ProgressIndicator + +:::row::: + :::column::: + **Description** + :::column-end::: + :::column span="3"::: + Indicates the progress of an add-in operation. For example, use the `ProgressIndicator` to inform the user that their file is in the process of being attached to the mail item. + +:::image type="content" source="../images/outlook-progress-notification.png" alt-text="A progress indicator notification."::: + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Properties** + :::column-end::: + :::column span="3"::: + - In classic Outlook on Windows, displays a progress icon. On other platforms, displays an information icon. This icon can't be customized. + - Doesn't persist when a user switches to another mail item. + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Minimum supported requirement set** + :::column-end::: + :::column span="3"::: + [1.3](/javascript/api/requirement-sets/outlook/requirement-set-1.3/outlook-requirement-set-1.3) + :::column-end::: +:::row-end::: +:::row::: + :::column::: + **Supported platforms** + :::column-end::: + :::column span="3"::: + - Web + - Windows (new and classic) + - Mac + - Android + - iOS + :::column-end::: +:::row-end::: + +## Feature behaviors + +When creating and managing notifications for your add-in, be mindful of the following behaviors, limitations, and best practices. + +### Maximum number of notifications per mail item + +In Outlook on the web, on Windows (new and classic), and on Mac, you can add a maximum of five notifications per message. In Outlook on mobile devices, only one notification can be added to a message. Setting an additional notification replaces the existing one. + +### InsightMessage limitations + +Only one `InsightMessage` notification is allowed per add-in on a mail item. In Outlook on the web and new Outlook on Windows, the `InsightMessage` type is only supported in compose mode. + +### Notification icons and unified manifest for Microsoft 365 + +If your add-in uses the [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md), you can't customize the icon of an `InformationalMessage` or `InsightMessage` notification. The notification uses the first image specified in the ["icons"](/microsoft-365/extensibility/schema/extension-common-custom-group-controls-item#icons) array of the first [extensions.ribbons.tabs.groups.controls](/microsoft-365/extensibility/schema/extension-common-custom-group-controls-item) object of the manifest. Although this is the case, you must still specify a string in the [icon](/javascript/api/outlook/office.notificationmessagedetails#outlook-office-notificationmessagedetails-icon-member) property of your [NotificationMessageDetails](/javascript/api/outlook/office.notificationmessagedetails) object (for example, "icon-16"). + +### Notification icons in Outlook on mobile devices + +In compose mode, while the style of each notification type varies on other Outlook clients, notifications in Outlook on Android and on iOS all use the same style. The notification message always uses an information icon. + +### Notifications for multiple selected messages + +When managing notifications for multiple selected messages, only the `getAllAsync` method is supported. To learn more, see [Activate your Outlook add-in on multiple messages](item-multi-select.md). + +### Best practices for ProgressIndicator notifications + +When implementing a `ProgressIndicator` notification in your add-in, once the applicable operation or action completes, replace the progress notification with another notification type. This is a best practice to ensure that your users always get the latest status of an operation. + +## Try the code example in Script Lab + +Learn how you can use notifications in your add-in by trying out the [Work with notification messages](https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml) sample in [Script Lab for Outlook](https://appsource.microsoft.com/product/office/wa200001603). For more information on Script Lab, see [Explore Office JavaScript API using Script Lab](../overview/explore-with-script-lab.md). + +## See also + +- [Use the Office dialog API in Office Add-ins](../develop/dialog-api-in-office-add-ins.md) +- [Activate add-ins with events](../develop/event-based-activation.md) diff --git a/docs/outlook/on-new-compose-events-walkthrough.md b/docs/outlook/on-new-compose-events-walkthrough.md index e4eb7ce4e1..76192d6901 100644 --- a/docs/outlook/on-new-compose-events-walkthrough.md +++ b/docs/outlook/on-new-compose-events-walkthrough.md @@ -1,7 +1,7 @@ ---- +--- title: Automatically set the subject of a new message or appointment description: Learn how to implement an event-based add-in that automatically sets the subject of a new message or appointment. -ms.date: 04/12/2024 +ms.date: 08/01/2025 ms.topic: how-to ms.localizationpriority: medium --- @@ -13,7 +13,9 @@ Need to add a required disclaimer to all your messages? With an event-based add- The following sections teach you how to develop an add-in that handles the `OnNewMessageCompose` and `OnNewAppointmentOrganizer` events. By the end of this walkthrough, you'll have an add-in that automatically sets the subject of new messages and appointments being created. > [!NOTE] -> The `OnNewMessageCompose` and `OnNewAppointmentOrganizer` events were introduced in [requirement set 1.10](/javascript/api/requirement-sets/outlook/requirement-set-1.10/outlook-requirement-set-1.10). To verify that your Outlook client supports these events, see [Requirement sets supported by Exchange servers and Outlook clients](/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets#requirement-sets-supported-by-exchange-servers-and-outlook-clients). +> +> - The `OnNewMessageCompose` and `OnNewAppointmentOrganizer` events were introduced in [requirement set 1.10](/javascript/api/requirement-sets/outlook/requirement-set-1.10/outlook-requirement-set-1.10). To verify that your Outlook client supports these events, see [Requirement sets supported by Exchange servers and Outlook clients](/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets#requirement-sets-supported-by-exchange-servers-and-outlook-clients). +> - The `OnNewMessageCompose` event is now supported in Outlook on mobile devices. To learn how to implement this event in your Outlook mobile add-in, see [Implement event-based activation in Outlook mobile add-ins](mobile-event-based.md). ## Set up your environment @@ -25,19 +27,38 @@ To configure the manifest, select the tab for the type of manifest you're using. # [Unified manifest for Microsoft 365](#tab/jsonmanifest) +[!INCLUDE [outlook-unified-manifest-platforms](../includes/outlook-unified-manifest-platforms.md)] + 1. Open the **manifest.json** file. -1. Add the following object to the "extensions.runtimes" array. Note the following about this markup: +1. Navigate to the [`"authorization.permissions.resourceSpecific"`](/microsoft-365/extensibility/schema/root-authorization-permissions#resourcespecific) array. In the array object, replace the value of the `"name"` property with `"MailboxItem.ReadWrite.User"`. This is needed by the add-in to be able to set the subject of the mail item. + + ```json + ... + "authorization": { + "permissions": { + "resourceSpecific": [ + { + "name": "MailboxItem.ReadWrite.User", + "type": "Delegated" + } + ] + } + }, + ... + ``` + +1. Add the following object to the [`"extensions.runtimes"`](/microsoft-365/extensibility/schema/extension-runtimes-array?view=m365-app-prev&preserve-view=true) array. Note the following about this markup: - - The "minVersion" of the Mailbox requirement set is configured to "1.10" as this is the lowest version of the requirement set that supports the `OnNewMessageCompose` and `OnNewAppointmentOrganizer` events. - - The "id" of the runtime is set to the descriptive name "autorun_runtime". - - The "code" property has a child "page" property that is set to an HTML file and a child "script" property that is set to a JavaScript file. You'll create or edit these files in later steps. Office uses one of these values depending on the platform. + - The `"minVersion"` of the Mailbox requirement set is configured to `"1.10"` as this is the lowest version of the requirement set that supports the `OnNewMessageCompose` and `OnNewAppointmentOrganizer` events. + - The `"id"` of the runtime is set to the descriptive name `"autorun_runtime"`. + - The `"code"` property has a child `"page"` property that is set to an HTML file and a child `"script"` property that is set to a JavaScript file. You'll create or edit these files in later steps. Office uses one of these values depending on the platform. - Office on Windows executes the event handlers in a JavaScript-only runtime, which loads a JavaScript file directly. - Office on Mac and on the web, and [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) execute the handlers in a browser runtime, which loads an HTML file. That file, in turn, contains a ` ``` - > [!IMPORTANT] - > The **Don't Send** button customization and send mode option override features are currently in preview in Outlook on Mac. If you're testing these features in your add-in project, you must include a reference to the preview version of the Office JavaScript API in your **commands.html** file. - > - > ```html - > - > - > ``` - 1. Save your changes. ## Update webpack config settings @@ -642,24 +674,32 @@ If you implemented the optional steps to customize the **Don't Send** button or [!INCLUDE [outlook-manual-sideloading](../includes/outlook-manual-sideloading.md)] 1. In your preferred Outlook client, create a new message and set the subject. In the body, add some text. For example, "Here's a picture of the proposed logo." -1. Send the message. A dialog appears requesting you to add an attachment. Select **Don't Send** or **Add an attachment**. The option available to you depends on whether you implemented the optional step to customize the **Don't Send** button. +1. Send the message. A dialog appears requesting you to add an attachment. Select **Don't Send**, **Take Action**, or **Add an attachment**. The options available to you depend on your Outlook client and whether you implemented the optional step to customize the dialog button. - Default **Don't Send** button. ![Dialog requesting the user to add an attachment to the message.](../images/outlook-win-smart-alerts.png) - - Customized **Add an attachment** button. + - Default **Take Action** button. + + ![Dialog with a Take Action button that opens a task pane.](../images/outlook-win-smart-alerts-take-action.png) + + - Customized **Add an attachment** button. Applies to Outlook on the web, new Outlook on Windows, and classic Outlook on Windows (starting in Version 2412 (Build 18324.20000)). + + ![Dialog with a customized Take Action button requesting the user to add an attachment to the message.](../images/outlook-smart-alerts-custom-take-action.png) + + - Customized **Add an attachment** button. Applies to classic Outlook on Windows prior to Version 2412 (Build 18324.20000). ![Dialog with a customized Don't Send button requesting the user to add an attachment to the message.](../images/outlook-smart-alerts-custom-button.png) - > [!TIP] - > If you assign a task pane to the **Don't Send** button, closing the dialog also opens the specified task pane. + > [!NOTE] + > In supported versions of classic Outlook on Windows prior to Version 2410 (Build 18031.15000), if you assign a task pane to the **Don't Send** button, closing the dialog also opens the specified task pane. -1. Add an attachment to your message. If you implemented the optional step to customize the **Don't Send** button, use the task pane to add an attachment. +1. Add an attachment to your message. If you implemented the optional step to customize a dialog button, use the task pane to add an attachment. ![Task pane with an option to add an attachment.](../images/outlook-smart-alerts-task-pane.png) -1. Send the message. There should be no alert this time. +1. Send the message. If you implemented the optional step to programmatically send the message from the task pane, the message will send when you select **Add and send**. There should be no alert this time. 1. [!include[Instructions to stop web server and uninstall dev add-in](../includes/stop-uninstall-outlook-dev-add-in.md)] @@ -677,7 +717,13 @@ If you implemented the optional step to override the send mode option at runtime 1. Send the message. A dialog appears recommending to attach a copy of the image to the message. 1. Select **Send Anyway** to send the message as is, or select **Attach a copy** to include a copy before sending the message. - ![Smart Alerts dialog with the Send Anyway option available at runtime.](../images/outlook-smart-alerts-send-mode-override.png) + - Applies to Outlook on the web, new Outlook on Windows, and classic Outlook on Windows (starting in Version 2412 (Build 18324.20000)). + + ![Customized Smart Alerts dialog with the Send Anyway option available at runtime.](../images/outlook-smart-alerts-custom-button-and-override.png) + + - Applies to classic Outlook on Windows prior to Version 2412 (Build 18324.20000). + + ![Smart Alerts dialog with the Send Anyway option available at runtime in classic Outlook on Windows prior to Version 2412 (Build 18324.20000).](../images/outlook-smart-alerts-send-mode-override.png) > [!IMPORTANT] > If a Smart Alerts add-in that implements the override feature can't complete processing an event due to an error or is unavailable when the event occurs, it uses the send mode option specified in the manifest. @@ -685,10 +731,10 @@ If you implemented the optional step to override the send mode option at runtime ## See also - [Handle OnMessageSend and OnAppointmentSend events in your Outlook add-in with Smart Alerts](onmessagesend-onappointmentsend-events.md) -- [Configure your Outlook add-in for event-based activation](autolaunch.md) +- [Activate add-ins with events](../develop/event-based-activation.md) - [Office Add-in manifests](../develop/add-in-manifests.md) -- [Troubleshoot event-based and spam-reporting add-ins](troubleshoot-event-based-and-spam-reporting-add-ins.md) -- [Debug event-based and spam-reporting add-ins](debug-autolaunch.md) -- [AppSource listing options for your event-based Outlook add-in](autolaunch-store-options.md) +- [Troubleshoot event-based and spam-reporting add-ins](../testing/troubleshoot-event-based-and-spam-reporting-add-ins.md) +- [Debug event-based and spam-reporting add-ins](../testing/debug-autolaunch.md) +- [Microsoft Marketplace listing options for your event-based add-in](../publish/autolaunch-store-options.md) - [Office Add-ins code sample: Verify the color categories of a message or appointment before it's sent using Smart Alerts](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/outlook-check-item-categories) - [Office Add-ins code sample: Verify the sensitivity label of a message](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/outlook-verify-sensitivity-label) diff --git a/docs/outlook/spam-reporting.md b/docs/outlook/spam-reporting.md index ed292243d9..e0c70bf197 100644 --- a/docs/outlook/spam-reporting.md +++ b/docs/outlook/spam-reporting.md @@ -1,7 +1,7 @@ ---- +--- title: Implement an integrated spam-reporting add-in description: Learn how to implement an integrated spam-reporting add-in in Outlook. -ms.date: 08/27/2024 +ms.date: 08/26/2025 ms.topic: how-to ms.localizationpriority: medium --- @@ -17,7 +17,7 @@ The integrated spam-reporting feature eases the task of developing individual ad - Enable an organization's security operations center (SOC) or IT administrators to easily perform spam and phishing simulations for educational purposes. > [!NOTE] -> Integrated spam reporting was introduced in [Mailbox requirement set 1.14](/javascript/api/requirement-sets/outlook/requirement-set-1.14/outlook-requirement-set-1.14). For information on client support for this feature, see [Supported clients](#supported-clients). +> Integrated spam reporting was introduced in [Mailbox requirement set 1.14](/javascript/api/requirement-sets/outlook/requirement-set-1.14/outlook-requirement-set-1.14). Additional functionality was also added to subsequent requirement sets. To verify that an Outlook client supports these features, see [Supported clients](#supported-clients) and the relevant sections of this article for the features you want to implement. ## Supported clients @@ -25,16 +25,15 @@ The following table identifies which Outlook clients support the integrated spam | Client | Status | | ---- | ---- | -| **Outlook on the web** | Supported | -| [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) | Supported | +| **Outlook on the web** | Supported\* | +| [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) | Supported\* | | **classic Outlook on Windows**
Version 2404 (Build 17530.15000) | Supported | -| **Outlook on Mac**
Version 16.81.1217.0 or later | Preview (see [Preview the integrated spam-reporting feature in Outlook on Mac](#preview-the-integrated-spam-reporting-feature-in-outlook-on-mac)) | +| **Outlook on Mac**
Version 16.100 (25072537) | Supported | | **Outlook on Android** | Not available | | **Outlook on iOS** | Not available | -## Preview the integrated spam-reporting feature in Outlook on Mac - -To preview the integrated spam-reporting feature in Outlook on Mac, you must install Version 16.81.1217.0 or later. Then, join the [Microsoft 365 Insider program](https://insider.microsoft365.com/join/Mac) and select the **Beta Channel** option to access Office beta builds. +> [!NOTE] +> \* In Outlook on the web and the new Outlook on Windows, the integrated spam-reporting feature isn't supported for Microsoft 365 consumer accounts. ## Set up your environment @@ -51,7 +50,8 @@ To implement the integrated spam-reporting feature in your add-in, you must conf - The button of the spam-reporting add-in that always appears in a prominent spot on the Outlook ribbon. The following is an example of how the button of a spam-reporting add-in appears on the ribbon of the classic Outlook client on Windows. The ribbon UI may vary depending on the platform the user's Outlook client is running on. :::image type="content" source="../images/outlook-spam-ribbon-button.png" alt-text="A sample ribbon button of a spam-reporting add-in."::: -- The preprocessing dialog. This dialog is shown to the user when they select the add-in button. In this dialog, a user can provide additional information about the message they're reporting. When a user selects **Report** from the dialog, the [SpamReporting](/javascript/api/office/office.eventtype) event is activated and is then handled by the JavaScript event handler. The following is an example of a preprocessing dialog in Outlook on Windows. Note that the appearance of the dialog may vary depending on the platform the user's Outlook client is running on. + +- The preprocessing dialog. When a user selects the add-in button, a dialog appears with **Report** and **Don't Report** options. In this dialog, you can share information about the reporting process or implement input options to get information about a reported message. Input options include checkboxes, radio buttons, and a text box. When a user selects **Report** from the dialog, the [SpamReporting](/javascript/api/office/office.eventtype) event is activated and is then handled by the JavaScript event handler. The following is an example of a preprocessing dialog in classic Outlook on Windows. Note that the appearance of the dialog may vary depending on the platform the user's Outlook client is running on. :::image type="content" source="../images/outlook-spam-processing-dialog.png" alt-text="A sample preprocessing dialog of a spam-reporting add-in."::: @@ -60,16 +60,17 @@ Select the tab for the type of manifest you're using. # [Unified manifest for Microsoft 365](#tab/jsonmanifest) > [!NOTE] -> Implementing integrated spam reporting with the unified manifest for Microsoft 365 is in public developer preview. It's currently only available to use in classic Outlook on Windows. This shouldn't be used in production add-ins. We invite you to try it out in test or development environments. For more information, see the [Public developer preview app manifest schema](/microsoftteams/platform/resources/schema/manifest-schema-dev-preview). +> Implementing integrated spam reporting with the unified manifest for Microsoft 365 is currently only available in classic Outlook on Windows. For more information, see the [Microsoft 365 app manifest schema reference](/microsoft-365/extensibility/schema). 1. In your preferred code editor, open the add-in project you created. 1. Open the **manifest.json** file. -1. Add the following object to the "extensions.runtimes" array. Note the following about this markup. - - The "minVersion" of the Mailbox requirement set is configured to "1.14". This is the lowest version of the requirement set that supports the integrated spam-reporting feature. - - The "id" of the runtime is set to a unique descriptive name, "spam_reporting_runtime". - - The "code" property has a child "page" property that's set to an HTML file and a child "script" property that's set to a JavaScript file. You'll create or edit these files in later steps. - - The "lifetime" property is set to "short". This means that the runtime starts when the `SpamReporting` event occurs and shuts down when the event handler completes. - - The "actions" object specifies the event handler function that runs in the runtime. You'll create this function in a later step. +1. Update the [`"$schema"`](/microsoft-365/extensibility/schema/root#schema-5) property to use the latest version. For more information, see [Microsoft 365 app manifest schema reference](/microsoft-365/extensibility/schema). +1. Add the following object to the [`"extensions.runtimes"`](/microsoft-365/extensibility/schema/extension-runtimes-array) array. Note the following about this markup. + - The [`"minVersion"`](/microsoft-365/extensibility/schema/requirements-extension-element-capabilities#minversion) of the Mailbox requirement set is configured to `"1.14"`. This is the lowest version of the requirement set that supports the integrated spam-reporting feature. + - The [`"id"`](/microsoft-365/extensibility/schema/extension-runtimes-array#id) of the runtime is set to a unique descriptive name, `"spam_reporting_runtime"`. + - The [`"code"`](/microsoft-365/extensibility/schema/extension-runtimes-array#code) property has a child `"page"` property that's set to an HTML file and a child `"script"` property that's set to a JavaScript file. You'll create or edit these files in later steps. + - The [`"lifetime"`](/microsoft-365/extensibility/schema/extension-runtimes-array#lifetime) property is set to `"short"`. This means that the runtime starts when the `SpamReporting` event occurs and shuts down when the event handler completes. + - The [`"actions"`](/microsoft-365/extensibility/schema/extension-runtimes-array#actions) object specifies the event handler function that runs in the runtime. You'll create this function in a later step. ```json { @@ -97,19 +98,22 @@ Select the tab for the type of manifest you're using. }, ``` -1. Add the following object to the "extensions.ribbons" array. Note the following about this markup. - - The "contexts" array contains the "spamReportingOverride" string. This prevents the add-in button from appearing at the end of the ribbon or in the overflow section. - - The "fixedControls" array contains an object that configures the look and functionality of the add-in button on the ribbon. The name of the event handler specified in the "actionId" property must match the value used in the "id" property of the object in the "actions" array. While the "enabled" property must be specified in the array, its value doesn't affect the functionality of a spam-reporting add-in. - - The "spamPreProcessingDialog" object specifies the information and options that are shown in the preprocessing dialog. While you must specify a "title" and "description" for the dialog, you can optionally configure the following properties. - - The "spamReportingOptions" object. It provides a multiple-selection list of up to five choices. This helps a user identify the type of message they're reporting. - - The "spamFreeTextSectionTitle" property. It provides a text box for the user to add more information about the message they're reporting. - - The "spamMoreInfo" object. It includes a link in the dialog to provide informational resources to the user. +1. Add the following object to the [`"extensions.ribbons"`](/microsoft-365/extensibility/schema/extension-ribbons-array) array. Note the following about this markup. + - The [`"contexts"`](/microsoft-365/extensibility/schema/extension-ribbons-array#contexts) array contains the `"spamReportingOverride"` string. This prevents the add-in button from appearing at the end of the ribbon or in the overflow section. + - The [`"tabs"`](/microsoft-365/extensibility/schema/extension-ribbons-array#tabs) array must be specified in an `"extensions.ribbons"` object. However, because the button of a spam-reporting add-in is displayed in a specific spot on the ribbon, only an empty array is specified. + - The [`"fixedControls"`](/microsoft-365/extensibility/schema/extension-ribbons-array#fixedcontrols) array contains an object that configures the look and functionality of the add-in button on the ribbon. The name of the event handler specified in the [`"actionId"`](/microsoft-365/extensibility/schema/extension-ribbons-array-fixed-control-item#actionid) property must match the value used in the `"id"` property of the object in the `"actions"` array. While the [`"enabled"`](/microsoft-365/extensibility/schema/extension-ribbons-array-fixed-control-item#enabled) property must be specified in the array, its value doesn't affect the functionality of a spam-reporting add-in. + - The [`"spamPreProcessingDialog"`](/microsoft-365/extensibility/schema/extension-ribbons-array#spampreprocessingdialog) object specifies the information and options that are shown in the preprocessing dialog. While you must specify a [`"title"`](/microsoft-365/extensibility/schema/extension-ribbons-spam-pre-processing-dialog#title) and [`"description"`](/microsoft-365/extensibility/schema/extension-ribbons-spam-pre-processing-dialog#description) for the dialog, you can optionally configure the following properties. + - The [`"spamNeverShowAgainOption"`](/microsoft-365/extensibility/schema/extension-ribbons-spam-pre-processing-dialog#spamnevershowagainoption) property. It provides the option to suppress the preprocessing dialog for succeeding reports. This functionality is useful in scenarios where you don't need additional information from users. To learn more, see [Suppress the preprocessing dialog](#suppress-the-preprocessing-dialog). + - The [`"spamReportingOptions"`](/microsoft-365/extensibility/schema/extension-ribbons-spam-pre-processing-dialog-spam-reporting-options?view=m365-app-1.22&preserve-view=true) object. It provides a list of up to five choices that you can configure as radio buttons or checkboxes. This helps a user identify the type of message they're reporting. + - The [`"spamFreeTextSectionTitle"`](/microsoft-365/extensibility/schema/extension-ribbons-spam-pre-processing-dialog#spamfreetextsectiontitle) property. It provides a text box for the user to add more information about the message they're reporting. + - The [`"spamMoreInfo"`](/microsoft-365/extensibility/schema/extension-ribbons-spam-pre-processing-dialog-spam-more-info) object. It includes a link in the dialog to provide informational resources to the user. ```json { "contexts": [ "spamReportingOverride" ], + "tabs": [], "fixedControls": [ { "id": "spamReportingButton", @@ -140,13 +144,15 @@ Select the tab for the type of manifest you're using. "spamPreProcessingDialog": { "title": "Report Spam Message", "description": "Thank you for reporting this message.", + "spamNeverShowAgainOption": false, "spamReportingOptions": { "title": "Why are you reporting this email?", "options": [ "Received spam email.", "Received a phishing email.", "I'm not sure this is a legitimate email." - ] + ], + "type": "checkbox" }, "spamFreeTextSectionTitle": "Provide additional information, if any:", "spamMoreInfo": { @@ -164,23 +170,24 @@ Select the tab for the type of manifest you're using. Configure the [VersionOverridesV1_1](/javascript/api/manifest/versionoverrides-1-1-mail) node of your add-in only manifest accordingly. - To run a spam-reporting add-in in Outlook on the web and on Mac and in the new Outlook on Windows, you must specify the HTML file that references or contains the code to handle the spam-reporting event in the `resid` attribute of the [Runtime](/javascript/api/manifest/runtime) element. -- To run a spam-reporting add-in in classic Outlook on Windows, you must specify the JavaScript file that contains the code to handle the spam-reporting event in the [Override](/javascript/api/manifest/override) child element of the **\** element. -- To activate the add-in in the Outlook ribbon and prevent it from appearing at the end of the ribbon or in the overflow section, set the `xsi:type` attribute of the **\** element to [ReportPhishingCommandSurface](/javascript/api/manifest/extensionpoint#reportphishingcommandsurface). +- To run a spam-reporting add-in in classic Outlook on Windows, you must specify the JavaScript file that contains the code to handle the spam-reporting event in the [Override](/javascript/api/manifest/override) child element of the `` element. +- To activate the add-in in the Outlook ribbon and prevent it from appearing at the end of the ribbon or in the overflow section, set the `xsi:type` attribute of the `` element to [ReportPhishingCommandSurface](/javascript/api/manifest/extensionpoint#reportphishingcommandsurface). - To customize the ribbon button and preprocessing dialog, you must define the [ReportPhishingCustomization](/javascript/api/manifest/reportphishingcustomization) node. - - To configure the ribbon button, set the `xsi:type` attribute of the [Control](/javascript/api/manifest/control-button) element to `Button`. Then, set the `xsi:type` attribute of the [Action](/javascript/api/manifest/action) child element to `ExecuteFunction` and specify the name of the spam-reporting event handler in its **\** child element. + - To configure the ribbon button, set the `xsi:type` attribute of the [Control](/javascript/api/manifest/control-button) element to `Button`. Then, set the `xsi:type` attribute of the [Action](/javascript/api/manifest/action) child element to `ExecuteFunction` and specify the name of the spam-reporting event handler in its `` child element. - To customize the preprocessing dialog, configure the [PreProcessingDialog](/javascript/api/manifest/preprocessingdialog) element of your manifest. While the dialog must have a title and description, you can optionally include the following elements. - - A multiple-selection list of choices to help a user identify the type of message they're reporting. To learn how to configure these reporting options, see [ReportingOptions element](/javascript/api/manifest/reportingoptions). + - A list of choices to help a user identify the type of message they're reporting. You can configure these options as radio buttons or checkboxes. To learn more, see [ReportingOptions element](/javascript/api/manifest/reportingoptions). - A text box for the user to provide additional information about the message they're reporting. To learn how to implement a text box, see [FreeTextLabel element](/javascript/api/manifest/preprocessingdialog#child-elements). - Custom text and URL to provide informational resources to the user. To learn how to personalize these elements, see [MoreInfo element](/javascript/api/manifest/moreinfo). > [!NOTE] - > Depending on the Outlook client, the custom text specified in the **\** element appears before the URL that's provided in the **\** element or as link text for the URL. For more information, see [MoreInfoText](/javascript/api/manifest/moreinfo#moreinfotext). + > Depending on the Outlook client, the custom text specified in the `` element appears before the URL that's provided in the `` element or as link text for the URL. For more information, see [MoreInfoText](/javascript/api/manifest/moreinfo#moreinfotext). + - A "Don't show me this message again" checkbox to prevent the preprocessing dialog from appearing again. To learn how to implement this option, see [Suppress the preprocessing dialog](#suppress-the-preprocessing-dialog). -The following is an example of a **\** node configured for spam reporting. +The following is an example of a `` node configured for spam reporting. 1. In your preferred code editor, open the add-in project you created. 1. Open the **manifest.xml** file located at the root of your project. -1. Select the entire **\** node (including the open and close tags) and replace it with the following code. +1. Select the entire `` node (including the open and close tags) and replace it with the following code. ```xml @@ -194,7 +201,7 @@ The following is an example of a **\** node configured for sp + This is used by Outlook on the web and on Mac, and new Outlook on Windows. --> @@ -299,10 +306,8 @@ When your add-in is used to report a message, it generates a `SpamReporting` eve // TODO - Signal that the spam-reporting event has completed processing. } - // IMPORTANT: To ensure your add-in is supported in the Outlook client on Windows, remember to map the event handler name specified in the manifest to its JavaScript counterpart. - if (Office.context.platform === Office.PlatformType.PC || Office.context.platform == null) { - Office.actions.associate("onSpamReport", onSpamReport); - } + // IMPORTANT: To ensure your add-in is supported in Outlook, remember to map the event handler name specified in the manifest to its JavaScript counterpart. + Office.actions.associate("onSpamReport", onSpamReport); ``` 1. Save your changes. @@ -340,20 +345,24 @@ The following is an example of a spam-reporting event handler that calls the `ge }); } - // IMPORTANT: To ensure your add-in is supported in the Outlook client on Windows, remember to map the event handler name specified in the manifest to its JavaScript counterpart. - if (Office.context.platform === Office.PlatformType.PC || Office.context.platform == null) { - Office.actions.associate("onSpamReport", onSpamReport); - } + // IMPORTANT: To ensure your add-in is supported in Outlook, remember to map the event handler name specified in the manifest to its JavaScript counterpart. + Office.actions.associate("onSpamReport", onSpamReport); ``` 1. Save your changes. > [!NOTE] -> To configure single sign-on (SSO) or cross-origin resource sharing (CORS) in your spam-reporting add-in, you must add your add-in and its JavaScript file to a well-known URI. For guidance on how to configure this resource, see [Use single sign-on (SSO) or cross-origin resource sharing (CORS) in your event-based or spam-reporting Outlook add-in](use-sso-in-event-based-activation.md). +> To configure single sign-on (SSO) or cross-origin resource sharing (CORS) in your spam-reporting add-in, you must add your add-in and its JavaScript file to a well-known URI. For guidance on how to configure this resource, see [Use single sign-on (SSO) or cross-origin resource sharing (CORS) in your event-based or spam-reporting Outlook add-in](../develop/use-sso-in-event-based-activation.md). ### Signal when the event has been processed -Once the event handler has completed processing the message, it must call the [event.completed](/javascript/api/outlook/office.mailboxevent#outlook-office-mailboxevent-completed-member(1)) method. In addition to signaling to the add-in that the spam-reporting event has been processed, `event.completed` can also be used to customize a post-processing dialog to show to the user or perform additional operations on the message, such as deleting it from the inbox. For a list of properties you can include in a JSON object to pass as a parameter to the `event.completed` method, see [Office.SpamReportingEventCompletedOptions](/javascript/api/outlook/office.spamreportingeventcompletedoptions). +Once the event handler has completed processing the message, it must call the [event.completed](/javascript/api/outlook/office.mailboxevent#outlook-office-mailboxevent-completed-member(1)) method. In addition to signaling to the add-in that the spam-reporting event has been processed, `event.completed` can also be used to do the following: + +- Customize a post-processing dialog to show to the user. +- Perform additional operations on the message, such as deleting it from the inbox. +- [Open a task pane and pass information to it](#open-a-task-pane-after-reporting-a-message). + +For a list of properties you can include in a JSON object to pass as a parameter to the `event.completed` method, see [Office.SpamReportingEventCompletedOptions](/javascript/api/outlook/office.spamreportingeventcompletedoptions). > [!NOTE] > Code added after the `event.completed` call isn't guaranteed to run. @@ -396,26 +405,24 @@ Once the event handler has completed processing the message, it must call the [e }); } - // IMPORTANT: To ensure your add-in is supported in the Outlook client on Windows, remember to map the event handler name specified in the manifest to its JavaScript counterpart - if (Office.context.platform === Office.PlatformType.PC || Office.context.platform == null) { - Office.actions.associate("onSpamReport", onSpamReport); - } + // IMPORTANT: To ensure your add-in is supported in Outlook, remember to map the event handler name specified in the manifest to its JavaScript counterpart + Office.actions.associate("onSpamReport", onSpamReport); ``` > [!NOTE] - > If you're on classic Outlook on Windows Version 2308 (Build 16724.10000) or later, Outlook on Mac, Outlook on the web, or new Outlook on Windows, you must use the `moveItemTo` property in the `event.completed` call to specify the folder to which a reported message is moved once it's processed by your add-in. On earlier Outlook builds on Windows that support the integrated spam-reporting feature, you must use the `postProcessingAction` property. + > If you're on classic Outlook on Windows Version 2308 (Build 16724.10000) or later, Outlook on Mac, Outlook on the web, or the new Outlook on Windows, you must use the `moveItemTo` property in the `event.completed` call to specify the folder to which a reported message is moved once it's processed by your add-in. On earlier Outlook builds on Windows that support the integrated spam-reporting feature, you must use the `postProcessingAction` property. 1. Save your changes. -The following is a sample post-processing dialog shown to the user once the add-in completes processing a reported message in Outlook on Windows. Note that the appearance of the dialog may vary depending on the platform the user's Outlook client is running on. +The following is a sample post-processing dialog shown to the user once the add-in completes processing a reported message in classic Outlook on Windows. Note that the appearance of the dialog may vary depending on the platform the user's Outlook client is running on. :::image type="content" source="../images/outlook-spam-post-processing-dialog.png" alt-text="A sample of a post-processing dialog shown once a reported spam message has been processed by the add-in."::: > [!TIP] -> As you develop a spam-reporting add-in that will run in Outlook on Windows, keep the following in mind. +> As you develop a spam-reporting add-in that will run in classic Outlook on Windows, keep the following in mind. > > - Imports aren't currently supported in the JavaScript file that contains the code to handle the spam-reporting event. -> - Code included in the `Office.onReady()` and `Office.initialize` functions won't run. You must add any add-in startup logic, such as checking the user's Outlook version, to your event handlers instead. +> - When the JavaScript function specified in the manifest to handle the `SpamReporting` event runs, code in `Office.onReady()` and `Office.initialize` isn't run. We recommend adding any startup logic needed by the event handler, such as checking the user's Outlook version, to the event handler instead. ## Update the commands HTML file @@ -426,14 +433,6 @@ The following is a sample post-processing dialog shown to the user once the add- ``` - > [!NOTE] - > The integrated spam-reporting feature is currently in preview in Outlook on Mac. If you're testing the feature in this client, you must include a reference to the preview version of the Office JavaScript API in your **commands.html** file. - > - > ```html - > - > - > ``` - 1. Save your changes. ## Update the webpack config settings @@ -462,6 +461,111 @@ The following is a sample post-processing dialog shown to the user once the add- 1. In the preprocessing dialog, choose a reason for reporting the message and add information about the message, if configured. Then, select **Report**. 1. (Optional) In the post-processing dialog, select **OK**. +## Suppress the preprocessing dialog + +> [!NOTE] +> The "Don't show me this message again" option was introduced in [requirement set 1.15](/javascript/api/requirement-sets/outlook/requirement-set-1.15/outlook-requirement-set-1.15). Learn more about its [supported clients and platforms](/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets#outlook-client-support). + +Depending on your scenario, you might not need a user to provide additional information about a message they're reporting. If the preprocessing dialog of your spam-reporting add-in only provides information to the user, you can choose to include a "Don't show me this message again" option in the dialog. + +:::image type="content" source="../images/spam-reporting-suppress-dialog.png" alt-text="The 'Don't show me this message again' option in the preprocessing dialog."::: + +To implement this in your add-in, you must configure its manifest. The element or property to be configured differs depending on the type of manifest your add-in uses. + +- **Unified manifest for Microsoft 365**: Set the `"extensions.ribbons.spamPreProcessingDialog.spamNeverShowAgainOption"` property to `true`. The following code is an example. + + ```json + "extensions": [ + ... + "ribbons": [ + { + ... + "spamPreProcessingDialog": { + "title": "Report Spam Message", + "description": "Thank you for reporting this message.", + "spamNeverShowAgainOption": true, + "spamMoreInfo": { + "text": "Reporting unsolicited messages", + "url": "https://www.contoso.com/spamreporting" + } + } + } + ], + ... + ] + ``` + +- **Add-in only manifest**: In the [PreProcessingDialog](/javascript/api/manifest/preprocessingdialog) element, set the [NeverShowAgainOption](/javascript/api/manifest/preprocessingdialog#child-elements) child element to `true`. The following code is an example. + + ```xml + ... + + + <Description resid="PreProcessingDialog.Text"/> + <NeverShowAgainOption>true</NeverShowAgainOption> + <MoreInfo> + <MoreInfoText resid="MoreInfo.Label"/> + <MoreInfoUrl resid="MoreInfo.Url"/> + </MoreInfo> + </PreProcessingDialog> + ... + ``` + +Note the following behaviors when implementing this option in your add-in. + +- The "Don't show me this message again" option appears in the preprocessing dialog only if there are no user input options configured, such as reporting options or a text box. If your manifest also specifies user input options, they'll be shown in the dialog instead. +- The option to suppress the preprocessing dialog is applied on a per-machine and per-platform basis. +- After suppressing the preprocessing dialog, if a user reports a message and has the [Reading Pane](https://support.microsoft.com/office/2fd687ed-7fc4-4ae3-8eab-9f9b8c6d53f0) turned on, a progress notification is shown on the message while it's being processed. If the Reading Pane is turned off, no progress notification is shown. + + :::image type="content" source="../images/spam-reporting-progress-notification.png" alt-text="The progress notification shown after reporting a message while the Reading Pane is turned on."::: + + > [!NOTE] + > If you implement the "Don't show me this message again" option without configuring a post-processing dialog, a dialog with the following generic message is shown to the user after processing: "Thank you for reporting this message." It's good practice to configure a post-processing dialog to appear after a reported message is processed. + +### Reenable the preprocessing dialog + +To reenable the preprocessing dialog in classic Outlook on Windows after selecting the "Don't show me this message again" option, perform the following steps. + +1. Open the **Registry Editor** as an administrator. +1. Navigate to **HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Outlook\Options\WebExt\SpamDialog**. +1. Locate your spam-reporting add-in using its ID specified in the manifest. +1. Delete the entry of your add-in from the registry. + +The preprocessing dialog will appear the next time a message is reported. + +## Open a task pane after reporting a message + +> [!NOTE] +> The option to implement a task pane from the `event.completed` method was introduced in [requirement set 1.15](/javascript/api/requirement-sets/outlook/requirement-set-1.15/outlook-requirement-set-1.15). Learn more about its [supported clients and platforms](/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets#outlook-client-support). + +Instead of a post-processing dialog, you can implement a task pane to open after a user reports a message. For example, you can use the task pane to show additional information based on the user's input in the preprocessing dialog. Similar to the post-processing dialog, the task pane is implemented through the add-in's `event.completed` call. + +> [!NOTE] +> If both the post-processing dialog and task pane capabilities are configured in the `event.completed` call, the task pane is shown instead of the dialog. + +To configure a task pane to open after a message is reported, you must specify the ID of the task pane in the [commandId](/javascript/api/outlook/office.spamreportingeventcompletedoptions#outlook-office-spamreportingeventcompletedoptions-commandid-member) option of the `event.completed` call. The ID must match the task pane's ID in the manifest. The location of the ID varies depending on the manifest your add-in uses. + +- **Unified manifest for Microsoft 365**: The `"id"` property of the [`"extensions.ribbons.tabs.groups.controls"`](/microsoft-365/extensibility/schema/extension-common-custom-group-controls-item#id) object that represents the task pane. +- **Add-in only manifest**: The `id` attribute of the [Control](/javascript/api/manifest/control) element that represents the task pane. + +If you need to pass information to the task pane, specify any JSON data in the [contextData](/javascript/api/outlook/office.spamreportingeventcompletedoptions#outlook-office-spamreportingeventcompletedoptions-contextdata-member) option of the `event.completed` call. To retrieve the value of the `contextData` option, you must call [Office.context.mailbox.item.getInitializationContextAsync](/javascript/api/outlook/office.messageread#outlook-office-messageread-getinitializationcontextasync-member(1)) in the JavaScript implementation of your task pane. + +> [!IMPORTANT] +> To ensure that the task pane of the spam-reporting add-in opens and receives context data after a message is reported, you must set the `moveItemTo` option of the `event.completed` call to `Office.MailboxEnums.MoveSpamItemTo.NoMove`. + +The following code is an example. + +```javascript +... + event.completed({ + commandId: "msgReadOpenPaneButton", + contextData: JSON.stringify({ a: "aValue", b: "bValue" }), + moveItemTo: Office.MailboxEnums.MoveSpamItemTo.NoMove + }); +``` + +If another task pane is open or pinned at the time a message is reported, the open task pane is closed then the task pane of the spam-reporting add-in is shown. + ## Review feature behavior and limitations As you develop and test the integrated spam-reporting feature in your add-in, be mindful of its characteristics and limitations. @@ -474,31 +578,33 @@ As you develop and test the integrated spam-reporting feature in your add-in, be :::image type="content" source="../images/outlook-spam-timeout-dialog.png" alt-text="The dialog shown when a spam-reporting add-in times out."::: -- A spam-reporting add-in can be used to report a message even if the Reading Pane of the Outlook client is turned off. However, this isn't supported in Outlook on Mac. In Outlook on Mac, the Reading Pane must be turned on to use a spam-reporting add-in. -- In classic Outlook on Windows, only one message can be reported at a time. If a user attempts to report another message while the previous one is still being processed, a dialog will be shown to them to notify them of this. +- In classic Outlook on Windows, a spam-reporting add-in can be used to report a message even if the Reading Pane of the Outlook client is turned off. In Outlook on the web, on Mac, and in new Outlook on Windows, the spam-reporting add-in can be used if the Reading Pane is turned on or the message to be reported is open in another window. +- Only one message can be reported at a time. If you select multiple messages to report, the button of the spam-reporting add-in becomes unavailable. +- In classic Outlook on Windows, only one reported message can be processed at a time. If a user attempts to report another message while the previous one is still being processed, a dialog will be shown to notify them of this. :::image type="content" source="../images/outlook-spam-report-error.png" alt-text="The dialog shown when the user attempts to report another message while the previous one is still being processed."::: - This doesn't apply to Outlook on the web or on Mac, or to new Outlook on Windows. In these Outlook clients, a user can report a message from the Reading Pane and can simultaneously report each message that's open in a separate window. + This doesn't apply to Outlook on the web or on Mac, or to the new Outlook on Windows. In these Outlook clients, a user can report a message from the Reading Pane and can simultaneously report each message that's open in a separate window. - The add-in can still process the reported message even if the user navigates away from the selected message. In Outlook on Mac, this is only supported if a user reports a message while it's open in a separate window. If the user reports a message while viewing it from the Reading Pane and then navigates away from it, the reporting process is terminated. +- In Outlook on the web and the new Outlook on Windows, if a message is reported while it's open in a separate window, a post-processing dialog isn't shown to the user. - The buttons that appear in the preprocessing and post-processing dialogs aren't customizable. Additionally, the text and buttons in the timeout and ongoing report dialogs can't be modified. -- The integrated spam-reporting and [event-based activation](autolaunch.md) features must use the same runtime. Multiple runtimes aren't currently supported in Outlook. To learn more about runtimes, see [Runtimes in Office Add-ins](../testing/runtimes.md). -- A spam-reporting add-in only implements [function commands](../design/add-in-commands.md#types-of-add-in-commands). A task pane command can't be assigned to the spam-reporting button on the ribbon. If you want to implement a task pane in your add-in, you must configure it in your manifest as follows: +- The integrated spam-reporting and [event-based activation](../develop/event-based-activation.md) features must use the same runtime. Multiple runtimes aren't currently supported in Outlook. To learn more about runtimes, see [Runtimes in Office Add-ins](../testing/runtimes.md). +- A spam-reporting add-in only implements [function commands](../design/add-in-commands.md#types-of-add-in-commands). A task pane command can't be assigned to the spam-reporting button on the ribbon. If you want to implement a task pane separate from the reporting functionality of your add-in, you must configure it in your manifest as follows: - **Add-in only manifest**: Include the [Action element](/javascript/api/manifest/action#xsitype-is-showtaskpane) in the manifest and set its `xsi:type` attribute to `ShowTaskpane`. - - **Unified manifest for Microsoft 365**: Configure a task pane object in the "extensions.runtimes" and "extensions.ribbons" arrays. For guidance, see the "Add a task pane command" section of [Create add-in commands with the unified manifest for Microsoft 365](../develop/create-addin-commands-unified-manifest.md#add-a-task-pane-command). + - **Unified manifest for Microsoft 365**: Configure a task pane object in the `"extensions.runtimes"` and `"extensions.ribbons"` arrays. For guidance, see the "Add a task pane command" section of [Create add-in commands with the unified manifest for Microsoft 365](../develop/create-addin-commands-unified-manifest.md#add-a-task-pane-command). - Note that a separate button to activate the task pane will be added to the ribbon, but it won't appear in the dedicated spam-reporting area of the ribbon. + Note that a separate button to activate the task pane will be added to the ribbon, but it won't appear in the dedicated spam-reporting area of the ribbon. If you want to configure a task pane to open after a message is reported, see [Open a task pane after reporting a message](#open-a-task-pane-after-reporting-a-message). ## Troubleshoot your add-in -As you develop your spam-reporting add-in, you may need to troubleshoot issues, such as your add-in not loading. For guidance on how to troubleshoot a spam-reporting add-in, see [Troubleshoot event-based and spam-reporting add-ins](troubleshoot-event-based-and-spam-reporting-add-ins.md). +As you develop your spam-reporting add-in, you might need to troubleshoot issues, such as your add-in not loading. For guidance on how to troubleshoot a spam-reporting add-in, see [Troubleshoot event-based and spam-reporting add-ins](../testing/troubleshoot-event-based-and-spam-reporting-add-ins.md). ## See also - [Office Add-ins manifest](../develop/add-in-manifests.md) - [Runtimes in Office Add-ins](../testing/runtimes.md) -- [Troubleshoot event-based and spam-reporting add-ins](troubleshoot-event-based-and-spam-reporting-add-ins.md) +- [Troubleshoot event-based and spam-reporting add-ins](../testing/troubleshoot-event-based-and-spam-reporting-add-ins.md) - [ReportPhishingCommandSurface extension point](/javascript/api/manifest/extensionpoint#reportphishingcommandsurface) - [Office.MessageRead.getAsFileAsync](/javascript/api/outlook/office.messageread#outlook-office-messageread-getasfileasync-member(1)) - [Office.MailboxEnums.MoveSpamItemTo](/javascript/api/outlook/office.mailboxenums.movespamitemto) diff --git a/docs/outlook/testing-and-tips.md b/docs/outlook/testing-and-tips.md index e55a5c23f1..16702baec1 100644 --- a/docs/outlook/testing-and-tips.md +++ b/docs/outlook/testing-and-tips.md @@ -1,4 +1,4 @@ ---- +--- title: Deploy and install Outlook add-ins for testing description: Create a manifest file, deploy the add-in UI file to a web server, install the add-in in your mailbox, and then test the add-in. ms.date: 03/21/2023 @@ -72,7 +72,7 @@ Deciding what versions of the Outlook client to test depends on your development - If you're developing an add-in for private use, or only for members of your organization, then it is important to test the versions of Outlook that your company uses. Keep in mind that some users may use Outlook on the web, so testing your company's standard browser versions is also important. -- If you're developing an add-in to list in [AppSource](https://appsource.microsoft.com), you must test the required versions as specified in the [Commercial marketplace certification policies 1120.3](/legal/marketplace/certification-policies#11203-functionality). This includes: +- If you're developing an add-in to list in [Microsoft Marketplace](https://marketplace.microsoft.com), you must test the required versions as specified in the [Commercial marketplace certification policies 1120.3](/legal/marketplace/certification-policies#11203-functionality). This includes: - The latest version of Outlook on Windows and the version prior to the latest. - The latest version of Outlook on Mac. - The latest version of Outlook on iOS and Android (if your add-in [supports mobile form factor](add-mobile-support.md)). @@ -83,9 +83,9 @@ Deciding what versions of the Outlook client to test depends on your development ## Outlook on the web and Exchange server versions -Consumer and Microsoft 365 account users see the modern UI version when they access Outlook on the web and no longer see the classic version which has been deprecated. However, on-premises Exchange servers continue to support classic Outlook on the web. Therefore, during the validation process, your submission may receive a warning that the add-in is not compatible with classic Outlook on the web. In that case, you should consider testing your add-in in an on-premises Exchange environment. This warning won't block your submission to AppSource but your customers may experience a sub-optimal experience if they use Outlook on the web in an on-premises Exchange environment. +Consumer and Microsoft 365 account users see the modern UI version when they access Outlook on the web and no longer see the classic version which has been deprecated. However, on-premises Exchange servers continue to support classic Outlook on the web. Therefore, during the validation process, your submission may receive a warning that the add-in is not compatible with classic Outlook on the web. In that case, you should consider testing your add-in in an on-premises Exchange environment. This warning won't block your submission to Microsoft Marketplace but your customers may experience a sub-optimal experience if they use Outlook on the web in an on-premises Exchange environment. -To mitigate this, we recommend you test your add-in in Outlook on the web connected to your own private on-premises Exchange environment. For more information, see guidance on how to [Establish an Exchange 2016 or Exchange 2019 test environment](/Exchange/plan-and-deploy/plan-and-deploy?view=exchserver-2019&preserve-view=true#establish-an-exchange-2016-or-exchange-2019-test-environment) and how to manage [Outlook on the web in Exchange Server](/exchange/clients/outlook-on-the-web/outlook-on-the-web?view=exchserver-2019&preserve-view=true). +To mitigate this, we recommend you test your add-in in Outlook on the web connected to your own private on-premises Exchange environment. For more information, see [Establish an Exchange Server test environment](/Exchange/plan-and-deploy/plan-and-deploy#establish-an-exchange-server-test-environment) and [Outlook on the web in Exchange Server](/exchange/clients/outlook-on-the-web/outlook-on-the-web). Alternatively, you can opt to pay for and use a service that hosts and manages on-premises Exchange servers. A couple of options are: diff --git a/docs/outlook/tips-for-handling-date-values-in-outlook-add-ins.md b/docs/outlook/tips-for-handling-date-values-in-outlook-add-ins.md index 657012045d..e3be290aad 100644 --- a/docs/outlook/tips-for-handling-date-values-in-outlook-add-ins.md +++ b/docs/outlook/tips-for-handling-date-values-in-outlook-add-ins.md @@ -1,11 +1,11 @@ --- -title: Handling date values in Outlook add-ins +title: Handle date values in Outlook add-ins description: The Office JavaScript API uses the JavaScript Date object for most of the storage and retrieval of dates and times. -ms.date: 02/29/2024 +ms.date: 04/17/2025 ms.localizationpriority: medium --- -# Tips for handling date values in Outlook add-ins +# Handle date values in Outlook add-ins The Office JavaScript API uses the JavaScript [Date](https://www.w3schools.com/jsref/jsref_obj_date.asp) object for most of the storage and retrieval of dates and times. diff --git a/docs/outlook/troubleshoot-event-based-and-spam-reporting-add-ins.md b/docs/outlook/troubleshoot-event-based-and-spam-reporting-add-ins.md deleted file mode 100644 index 677724e811..0000000000 --- a/docs/outlook/troubleshoot-event-based-and-spam-reporting-add-ins.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Troubleshoot event-based and spam-reporting add-ins -description: Learn how to troubleshoot development errors in Outlook add-ins that implement event-based activation or integrated spam reporting. -ms.date: 05/20/2024 -ms.topic: troubleshooting -ms.localizationpriority: medium ---- - -# Troubleshoot event-based and spam-reporting add-ins - -As you develop your [event-based](autolaunch.md) or [spam-reporting](spam-reporting.md) add-in, you may encounter issues, such as your add-in not loading or an event not occurring. The following sections provide guidance on how to troubleshoot your add-in. - -## Review feature prerequisites - -- Verify that the add-in is installed on a supported Outlook client. Some Outlook clients only support certain events or aspects of event-based activation or integrated spam reporting. For more information, see [Supported events](autolaunch.md#supported-events) and [Implement an integrated spam-reporting add-in](spam-reporting.md). -- Verify that your Outlook client supports the minimum requirement set needed. - - Event-based activation was introduced in [requirement set 1.10](/javascript/api/requirement-sets/outlook/requirement-set-1.10/outlook-requirement-set-1.10), with additional events now supported in subsequent requirements sets. For more information, see [Supported events](autolaunch.md#supported-events) and [Requirement sets supported by Exchange servers and Outlook clients](/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets#requirement-sets-supported-by-exchange-servers-and-outlook-clients). If you're developing an add-in that handles the `OnMessageSend` and `OnAppointmentSend` events, see the "Supported clients and platform section" of [Handle OnMessageSend and OnAppointmentSend events in your Outlook add-in with Smart Alerts](onmessagesend-onappointmentsend-events.md#supported-clients-and-platforms). - - The integrated spam reporting feature was introduced in [requirement set 1.14](/javascript/api/requirement-sets/outlook/requirement-set-1.14/outlook-requirement-set-1.14). -- Review the expected behavior and limitations of the feature. - - - [Event-based activation behavior and limitations](autolaunch.md#event-based-activation-behavior-and-limitations) - - [Smart Alerts behavior and scenarios](onmessagesend-onappointmentsend-events.md#smart-alerts-feature-behavior-and-scenarios) - - [Integrated spam-reporting behavior and limitations](spam-reporting.md#review-feature-behavior-and-limitations) - -## Check manifest and JavaScript requirements - -- Ensure that the following conditions are met in your add-in's manifest. - - - Verify that your add-in's source file location URL is publicly available and isn't blocked by a firewall. This URL is specified in the [SourceLocation element](/javascript/api/manifest/sourcelocation) of the add-in only manifest or the "extensions.runtimes.code.page" property of the unified manifest for Microsoft 365. - - Verify that the **\<Runtimes\>** element (add-in only manifest) or "extensions.runtimes.code" property (unified manifest) correctly references the HTML or JavaScript file containing the event handlers. Classic Outlook on Windows uses the JavaScript file during runtime, while Outlook on the web, on new Mac UI, and [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) use the HTML file. For an example of how this is configured in the manifest, see the "Configure the manifest" section of [Automatically set the subject of a new message or appointment](on-new-compose-events-walkthrough.md#configure-the-manifest). - - For classic Outlook on Windows, you must bundle all your event-handling JavaScript code into this JavaScript file referenced in the manifest. Note that a large JavaScript bundle may cause issues with the performance of your add-in. We recommend preprocessing heavy operations, so that they're not included in your event-handling code. -- Verify that your event-handling JavaScript file referenced by the Outlook client on Windows calls `Office.actions.associate`. This ensures that the event handler name specified in the manifest is mapped to its JavaScript counterpart. - - > [!TIP] - > If your add-in has only one JavaScript file referenced by Outlook on the web, on Windows (new and classic), and on Mac, it's recommended to check on which platform the add-in is running to determine when to call `Office.actions.associate`, as shown in the following code. - > - > ```js - > if (Office.context.platform === Office.PlatformType.PC || Office.context.platform == null) { - > Office.actions.associate("onNewMessageComposeHandler", onNewMessageComposeHandler); - > Office.actions.associate("onNewAppointmentComposeHandler", onNewAppointmentComposeHandler); - > } - > ``` - -- The JavaScript code of event-based and spam-reporting add-ins that run in classic Outlook on Windows only supports [ECMAScript 2016](https://262.ecma-international.org/7.0/) and earlier specifications. Some examples of programming syntax to avoid are as follows. - - Avoid using `async` and `await` statements in your code. Including these in your JavaScript code will cause the add-in to time out. - - Avoid using the [conditional (ternary) operator](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) as it will prevent your add-in from loading. - - If your add-in has only one JavaScript file referenced by Outlook on the web, on Windows (new and classic), and on Mac, you must limit your code to ECMAScript 2016 to ensure that your add-in runs in classic Outlook on Windows. However, if you have a separate JavaScript file referenced by Outlook on the web, on Mac, and new Outlook on Windows, you can implement a later ECMAScript specification in that file. - -## Debug your add-in - -- As you make changes to your add-in, be aware that: - - If you update the manifest, [remove the add-in](sideload-outlook-add-ins-for-testing.md#remove-a-sideloaded-add-in), then sideload it again. If you're using Outlook on Windows, you must also close and reopen Outlook. - - If you make changes to files other than the manifest, close and reopen the Outlook client on Windows or on Mac, or refresh the browser tab running Outlook on the web. - - If you're still unable to see your changes after performing these steps, [clear your Office cache](../testing/clear-cache.md). -- As you test your add-in in classic Outlook on Windows: - - For event-based add-ins, check [Event Viewer](/shows/inside/event-viewer) for any reported add-in errors. - 1. In Event Viewer, select **Windows Logs** > **Application**. - 1. From the **Actions** panel, select **Filter Current Log**. - 1. From the **Logged** dropdown, select your preferred log time frame. - 1. Select the **Error** checkbox. - 1. In the **Event IDs** field, enter **63**. - 1. Select **OK** to apply your filters. - - :::image type="content" source="../images/outlook-event-based-logs.png" alt-text="A sample of Event Viewer's Filter Current Log settings configured to only show Outlook errors with event ID 63 that occurred in the last hour."::: - - - Verify that the **bundle.js** file is downloaded to the following folder in File Explorer. Replace text enclosed in `[]` with your applicable information. - - ```text - %LOCALAPPDATA%\Microsoft\Office\16.0\Wef\{[Outlook profile GUID]}\[Outlook mail account encoding]\Javascript\[Add-in ID]_[Add-in Version]_[locale] - ``` - - [!INCLUDE [outlook-bundle-js](../includes/outlook-bundle-js.md)] - -- As you test your add-in in Outlook on Windows (classic) or Mac, enable runtime logging to identify possible manifest and add-in installation issues. For guidance on how to use runtime logging, see [Debug your add-in with runtime logging](../testing/runtime-logging.md). -- Set breakpoints in your code to debug your add-in. For platform-specific instructions, see [Debug event-based and spam-reporting add-ins](debug-autolaunch.md). - -## Seek additional help - -If you still need help after performing the recommended troubleshooting steps, [open a GitHub issue](https://github.com/OfficeDev/office-js/issues/new?assignees=&labels=&template=bug_report.md&title=). Include screenshots, video recordings, or runtime logs to supplement your report. - -## See also - -- [Configure your Outlook add-in for event-based activation](autolaunch.md) -- [Implement an integrated spam-reporting add-in](spam-reporting.md) diff --git a/docs/outlook/troubleshoot-outlook-add-in-activation.md b/docs/outlook/troubleshoot-outlook-add-in-activation.md index 5fc7410108..b041f81ee9 100644 --- a/docs/outlook/troubleshoot-outlook-add-in-activation.md +++ b/docs/outlook/troubleshoot-outlook-add-in-activation.md @@ -1,7 +1,7 @@ --- title: Troubleshoot Outlook contextual add-in activation description: Possible reasons your contextual Outlook add-in doesn't activate as you expect. -ms.date: 07/18/2024 +ms.date: 07/14/2025 ms.topic: troubleshooting ms.localizationpriority: medium --- @@ -24,43 +24,15 @@ You can verify the version of Exchange by using one of the following approaches. - Alternatively, you can use the [Office.context.mailbox.diagnostics.hostVersion](/javascript/api/outlook/office.diagnostics#outlook-office-diagnostics-hostversion-member) property to verify the version. In Outlook on the web, on mobile devices, and in [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627), this property returns the version of the Exchange Server. -- If you can test the add-in on Outlook, you can use the following simple debugging technique that uses the Outlook object model and Visual Basic Editor. - - 1. First, verify that macros are enabled for Outlook. Choose **File**, **Options**, **Trust Center**, **Trust Center Settings**, **Macro Settings**. Ensure that **Notifications for all macros** is selected in the Trust Center. You should have also selected **Enable Macros** during Outlook startup. - - 1. On the **Developer** tab of the ribbon, choose **Visual Basic**. - - > [!NOTE] - > Not seeing the **Developer** tab? See [How to: Show the Developer Tab on the Ribbon](/visualstudio/vsto/how-to-show-the-developer-tab-on-the-ribbon) to turn it on. - - 1. In the Visual Basic Editor, choose **View**, **Immediate Window**. - - 1. Type the following in the Immediate window to display the version of the Exchange Server. The major version of the returned value must be equal to or greater than 15. - - - If there is only one Exchange account in the user's profile: - - ```vb - ?Session.ExchangeMailboxServerVersion - ``` - - - If there are multiple Exchange accounts in the same user profile (`emailAddress` represents a string that contains the user's primary SMTP address): - - ```vb - ?Session.Accounts.Item(emailAddress).ExchangeMailboxServerVersion - ``` - ## Is the add-in available? -Outlook on Windows (classic) and on Mac can make an add-in unavailable due to performance reasons, including exceeding usage thresholds for CPU core or memory, tolerance for crashes, and length of time to process all the regular expressions for an add-in. When this happens, Outlook on Windows (classic) and on Mac display a notification that it's making an add-in unavailable. - -> [!NOTE] -> Only Outlook on Windows (classic) and Outlook on Mac monitor resource usage. However, an add-in made unavailable in Outlook on Windows (classic) or Outlook on Mac also becomes unavailable in Outlook on the web, on mobile devices, and in [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627). - Check your list of installed add-ins to verify whether an add-in is available. For instructions on how to view your add-ins in Outlook, see [Use add-ins in Outlook](https://support.microsoft.com/office/1ee261f9-49bf-4ba6-b3e2-2ba7bcab64c8). +If you also use the classic Outlook on Mac client, resource usage limits apply to add-ins that could affect their availability across supported platforms. For more information, see [Resource usage limits for add-ins](../concepts/resource-limits-and-performance-optimization.md#resource-usage-limits-for-add-ins). + ## Does the tested item support Outlook add-ins? Is the selected item delivered by a version of Exchange Server that is at least Exchange 2016? -If your Outlook add-in is a read add-in and is supposed to be activated when the user is viewing a message (including email messages, meeting requests, responses, and cancellations) or appointment, even though these items generally support add-ins, there are exceptions. Check if the selected item is one of those [listed where Outlook add-ins don't activate](outlook-add-ins-overview.md#mailbox-items-available-to-add-ins). +If your Outlook add-in is a read add-in and is supposed to be activated when the user is viewing a message (including email messages, meeting requests, responses, and cancellations) or appointment, even though these items generally support add-ins, there are exceptions. Check if the selected item is one of those [listed where Outlook add-ins don't activate](outlook-add-ins-overview.md#add-in-activation-limitations). Also, because appointments are always saved in Rich Text Format, an [ItemHasRegularExpressionMatch](/javascript/api/manifest/rule#itemhasregularexpressionmatch-rule) rule that specifies a **PropertyName** value of **BodyAsHTML** wouldn't activate an add-in on an appointment or message that's saved in plain text or Rich Text Format. diff --git a/docs/outlook/understanding-outlook-add-in-permissions.md b/docs/outlook/understanding-outlook-add-in-permissions.md index b5e1fb3869..31c9eed223 100644 --- a/docs/outlook/understanding-outlook-add-in-permissions.md +++ b/docs/outlook/understanding-outlook-add-in-permissions.md @@ -1,7 +1,7 @@ ---- +--- title: Understanding Outlook add-in permissions description: Outlook add-ins specify the required permission level in their manifest, which include restricted, read item, read/write item, or read/write mailbox. -ms.date: 07/18/2024 +ms.date: 10/17/2024 ms.localizationpriority: medium --- @@ -9,11 +9,29 @@ ms.localizationpriority: medium Outlook add-ins specify the required permission level in their manifest. There are four available levels. -[!include[Table of Outlook permissions](../includes/outlook-permission-levels-table.md)] +|Permission level</br>canonical name|add-in only manifest name|unified manifest for Microsoft 365 name|Summary description| +|:-----|:-----|:-----|:-----| +|**restricted**|Restricted|MailboxItem.Restricted.User|Allows access to properties and methods that don't pertain to specific information about the user or mail item.| +|**read item**|ReadItem|MailboxItem.Read.User|In addition to what is allowed in **restricted**, it allows:<ul><li>regular expressions</li><li>Outlook add-in API read access</li><li>getting the item properties and the callback token</li><li>writing custom properties</li></ul>| +|**read/write item**|ReadWriteItem|MailboxItem.ReadWrite.User|In addition to what is allowed in **read item**, it allows:<ul><li>full Outlook add-in API access except `makeEwsRequestAsync`</li><li>setting the item properties</li></ul>| +|**read/write mailbox**|ReadWriteMailbox|Mailbox.ReadWrite.User|In addition to what is allowed in **read/write item**, it allows:<ul><li>creating, reading, writing items and folders</li><li>sending items</li><li>calling [makeEwsRequestAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox#methods)</li></ul>| + +Permissions are declared in the manifest. The markup varies depending on the type of manifest. + +- **Add-in only manifest**: Use the `<Permissions>` element. +- **Unified manifest for Microsoft 365**: Use the `"name"` property of an object in the [`"authorization.permissions.resourceSpecific"`](/microsoft-365/extensibility/schema/root-authorization-permissions#resourcespecific) array. + +> [!NOTE] +> +> - There's a supplementary permission needed for add-ins that use the append-on-send feature. With the add-in only manifest, specify the permission in the [ExtendedPermissions](/javascript/api/manifest/extendedpermissions) element. For details, see [Implement append-on-send in your Outlook add-in](../outlook/append-on-send.md). With the unified manifest, specify this permission with the name **Mailbox.AppendOnSend.User** in an additional object in the `"authorization.permissions.resourceSpecific"` array. +> - There's a supplementary permission needed for add-ins that use shared folders. With the add-in only manifest, specify the permission by setting the [SupportsSharedFolders](/javascript/api/manifest/supportssharedfolders) element to `true`. For details, see [Implement shared folders and shared mailbox scenarios in an Outlook add-in](../outlook/delegate-access.md). With the unified manifest, specify this permission with the name **Mailbox.SharedFolder** in an additional object in the `"authorization.permissions.resourceSpecific"` array. The four levels of permissions are cumulative: the **read/write mailbox** permission includes the permissions of **read/write item**, **read item** and **restricted**, **read/write item** includes **read item** and **restricted**, and the **read item** permission includes **restricted**. -You can see the permissions requested by a mail add-in before installing it from [AppSource](https://appsource.microsoft.com). You can also see the required permissions of installed add-ins in the Exchange Admin Center. +You can see the permissions requested by a mail add-in before installing it from [Microsoft Marketplace](https://marketplace.microsoft.com). You can also see the required permissions of installed add-ins in the Exchange Admin Center. + +> [!TIP] +> To make sure that your Outlook add-in specifies the correct permission level, verify the minimum permission level required by each API implemented by your add-in. For information on minimum permission levels, see [Outlook API reference](/javascript/api/outlook). ## restricted permission @@ -60,9 +78,9 @@ The **read item** permission is the next level of permission in the permissions ### Can do -- [Read all the properties](item-data.md) of the current item in a read or [compose form](get-and-set-item-data-in-a-compose-form.md), for example, [item.to](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#properties) in a read form and [item.to.getAsync](/javascript/api/outlook/office.recipients#outlook-office-recipients-getasync-member(1)) in a compose form. +- Read all the properties of the current item in a read or compose form. For example, [item.to](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item#properties) in a read form and [item.to.getAsync](/javascript/api/outlook/office.recipients#outlook-office-recipients-getasync-member(1)) in a compose form. -- [Get a callback token to get item attachments](get-attachments-of-an-outlook-item.md) or the full item with Exchange Web Services (EWS) or [Outlook REST APIs](use-rest-api.md). +- In Exchange on-premises environments, get a callback token to get the full mail item with Exchange Web Services (EWS). [!INCLUDE [legacy-exchange-token-deprecation](../includes/legacy-exchange-token-deprecation.md)] @@ -105,7 +123,7 @@ Specify **read/write item** permission in the manifest to request this permissio ### Can do -- [Read and write all item-level properties](item-data.md) of the item that is being viewed or composed in Outlook. +- Read and write all item-level properties of the item that is being viewed or composed in Outlook. - [Add or remove attachments](add-and-remove-attachments-to-an-item-in-a-compose-form.md) of that item. @@ -123,13 +141,13 @@ Specify **read/write item** permission in the manifest to request this permissio The **read/write mailbox** permission is the highest level of permission. -In addition to what the **read/write item** permission supports, the token provided by **mailbox.getCallbackTokenAsync** provides access to use Exchange Web Services (EWS) operations or Outlook REST APIs to do the following: +In Exchange on-premises environments, the token provided by **mailbox.getCallbackTokenAsync** provides access to use Exchange Web Services (EWS) operations or Outlook REST APIs to do the following: - Read and write all properties of any item in the user's mailbox. - Create, read, and write to any folder or item in that mailbox. -- Send an item from that mailbox +- Send an item from that mailbox. -Through **mailbox.makeEWSRequestAsync**, you can access the following EWS operations. +Through **mailbox.makeEwsRequestAsync**, you can access the following EWS operations. - [CopyItem](/exchange/client-developer/web-service-reference/copyitem-operation) - [CreateFolder](/exchange/client-developer/web-service-reference/createfolder-operation) diff --git a/docs/outlook/use-rest-api.md b/docs/outlook/use-rest-api.md index d68d3730cf..ebacc7e41f 100644 --- a/docs/outlook/use-rest-api.md +++ b/docs/outlook/use-rest-api.md @@ -1,7 +1,7 @@ ---- +--- title: Use the Outlook REST APIs from an Outlook add-in description: Learn how to use the Outlook REST APIs from an Outlook add-in to get an access token. -ms.date: 02/12/2024 +ms.date: 04/22/2025 ms.topic: how-to ms.localizationpriority: medium --- @@ -11,14 +11,16 @@ ms.localizationpriority: medium The [Office.context.mailbox.item](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox.item) namespace provides access to many of the common fields of messages and appointments. However, in some scenarios an add-in may need to access data that isn't exposed by the namespace. For example, the add-in may rely on custom properties set by an outside app, or it needs to search the user's mailbox for messages from the same sender. In these scenarios, the [Outlook REST APIs](/outlook/rest) is the recommended method to retrieve the information. > [!IMPORTANT] -> **Outlook REST v2.0 and beta endpoints deprecation** +> **Outlook REST v2.0 and beta endpoints are deprecated** > -> The Outlook REST v2.0 and beta endpoints will be [fully deprecated on March 31, 2024](https://devblogs.microsoft.com/microsoft365dev/outlook-rest-api-v2-0-and-beta-endpoints-decommissioning-update/). However, privately released and AppSource-hosted add-ins are able to use the REST service until [extended support ends for Outlook 2019 on October 14, 2025](/lifecycle/end-of-support/end-of-support-2025). Traffic from these add-ins is automatically identified for exemption. This exemption also applies to new add-ins developed after the decommission date. +> The Outlook REST v2.0 and beta endpoints are now [deprecated](https://devblogs.microsoft.com/microsoft365dev/final-reminder-outlook-rest-api-v2-0-and-beta-endpoints-decommissioning/). However, privately released and Microsoft Marketplace-hosted add-ins are still able to use the REST service until [extended support ends for Outlook 2019 on October 14, 2025](/lifecycle/end-of-support/end-of-support-2025). Traffic from these add-ins is automatically identified for exemption. This exemption also applies to new add-ins developed after March 31, 2024. > -> Although add-ins are able to use the REST service until 2025, we highly encourage you to migrate your add-ins to use [Microsoft Graph](/outlook/rest#outlook-rest-api-via-microsoft-graph). For guidance, see [Compare Microsoft Graph and Outlook REST API endpoints](/outlook/rest/compare-graph). +> Although add-ins are able to use the REST service until October 2025, we highly encourage you to migrate your add-ins to use [Microsoft Graph](microsoft-graph.md). ## Get an access token +[!INCLUDE [legacy-exchange-token-deprecation](../includes/legacy-exchange-token-deprecation.md)] + The Outlook REST APIs require a bearer token in the `Authorization` header. Typically apps use OAuth2 flows to retrieve a token. However, add-ins can retrieve a token without implementing OAuth2 by using the new [Office.context.mailbox.getCallbackTokenAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox#methods) method introduced in the Mailbox requirement set 1.5. By setting the `isRest` option to `true`, you can request a token compatible with the REST APIs. @@ -117,5 +119,5 @@ function getCurrentItem(accessToken) { ## See also -- For an example that calls the REST APIs from an Outlook add-in, see [command-demo](https://github.com/OfficeDev/outlook-add-in-command-demo) on GitHub. -- Outlook REST APIs are also available through the Microsoft Graph endpoint but there are some key differences, including how your add-in gets an access token. For more information, see [Outlook REST API via Microsoft Graph](/outlook/rest/index#outlook-rest-api-via-microsoft-graph). +- [Add-in Command sample](https://github.com/OfficeDev/outlook-add-in-command-demo) +- [Use the Microsoft Graph REST API from an Outlook add-in](microsoft-graph.md) diff --git a/docs/outlook/validate-an-identity-token.md b/docs/outlook/validate-an-identity-token.md index a8235441ac..60631443d4 100644 --- a/docs/outlook/validate-an-identity-token.md +++ b/docs/outlook/validate-an-identity-token.md @@ -12,7 +12,7 @@ ms.localizationpriority: medium Your Outlook add-in can send you an Exchange user identity token, but before you trust the request you must validate the token to ensure that it came from the Exchange server that you expect. Exchange user identity tokens are JSON Web Tokens (JWT). The steps required to validate a JWT are described in [RFC 7519 JSON Web Token (JWT)](https://www.rfc-editor.org/rfc/rfc7519.txt). -We suggest that you use a four-step process to validate the identity token and obtain the user's unique identifier. First, extract the JSON Web Token (JWT) from a base64 URL-encoded string. Second, make sure that the token is well-formed, that it is for your Outlook add-in, that it has not expired, and that you can extract a valid URL for the authentication metadata document. Next, retrieve the authentication metadata document from the Exchange server and validate the signature attached to the identity token. Finally, compute a unique identifier for the user by concatenating the user's Exchange ID with the URL of the authentication metadata document. +We suggest that you use a four-step process to validate the identity token and obtain the user's unique identifier. First, extract the JSON Web Token (JWT) from a Base64-encoded URL string. Second, make sure that the token is well-formed, that it is for your Outlook add-in, that it has not expired, and that you can extract a valid URL for the authentication metadata document. Next, retrieve the authentication metadata document from the Exchange server and validate the signature attached to the identity token. Finally, compute a unique identifier for the user by concatenating the user's Exchange ID with the URL of the authentication metadata document. ## Extract the JSON Web Token @@ -22,7 +22,7 @@ The token returned from [getUserIdentityTokenAsync](/javascript/api/requirement- {header}.{payload}.{signature} ``` -The header and payload should be base64-decoded to obtain a JSON representation of each part. The signature should be base64-decoded to obtain a byte array containing the binary signature. +The header and payload should be Base64-decoded to obtain a JSON representation of each part. The signature should be Base64-decoded to obtain a byte array containing the binary signature. For more information about the contents of the token, see [Inside the Exchange identity token](inside-the-identity-token.md). @@ -98,7 +98,7 @@ The authentication metadata document uses the following format. } ``` -The available signing keys are in the `keys` array. Select the correct key by ensuring that the `x5t` value in the `keyinfo` property matches the `x5t` value in the header of the token. The public key is inside the `value` property in the `keyvalue` property, stored as a base64-encoded byte array. +The available signing keys are in the `keys` array. Select the correct key by ensuring that the `x5t` value in the `keyinfo` property matches the `x5t` value in the header of the token. The public key is inside the `value` property in the `keyvalue` property, stored as a Base64-encoded byte array. After you have the correct public key, verify the signature. The signed data is the first two parts of the encoded token, separated by a period: diff --git a/docs/outlook/web-services.md b/docs/outlook/web-services.md index b38fa724f0..513b70813c 100644 --- a/docs/outlook/web-services.md +++ b/docs/outlook/web-services.md @@ -1,14 +1,14 @@ ---- +--- title: Use Exchange Web Services (EWS) from an Outlook add-in -description: Provides an example that shows how an Outlook add-in can request information from Exchange Web Services. -ms.date: 06/10/2024 +description: Provides an example that shows how an Outlook add-in in an Exchange on-premises environment can request information from Exchange Web Services. +ms.date: 10/17/2024 ms.topic: how-to ms.localizationpriority: medium --- -# Call web services from an Outlook add-in +# Use Exchange Web Services (EWS) from an Outlook add-in -Your add-in can use Exchange Web Services (EWS) from a computer that is running Exchange Server, a web service that is available on the server that provides the source location for the add-in's UI, or a web service that is available on the Internet. This article provides an example that shows how an Outlook add-in can request information from EWS. +Your Outlook add-in can use Exchange Web Services (EWS) from an environment that runs Exchange Server (on-premises). EWS is a web service that's available on the server that provides the source location for the add-in's UI. This article provides an example that shows how an Outlook add-in can request information from EWS. [!INCLUDE [legacy-exchange-token-deprecation](../includes/legacy-exchange-token-deprecation.md)] @@ -18,32 +18,32 @@ The way you call a web service varies based on where the web service is located. |:-----|:-----| |The Exchange server that hosts the client mailbox|Use the [mailbox.makeEwsRequestAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox#methods) method to call EWS operations that add-ins support. The Exchange server that hosts the mailbox also exposes EWS.| |The web server that provides the source location for the add-in UI|Call the web service by using standard JavaScript techniques. The JavaScript code in the UI frame runs in the context of the web server that provides the UI. Therefore, it can call web services on that server without causing a cross-site scripting error.| -|All other locations|Create a proxy for the web service on the web server that provides the source location for the UI. If you do not provide a proxy, cross-site scripting errors will prevent your add-in from running. One way to provide a proxy is by using JSON/P. For more information, see [Privacy and security for Office Add-ins](../concepts/privacy-and-security.md).| +|All other locations|Create a proxy for the web service on the web server that provides the source location for the UI. If you don't provide a proxy, cross-site scripting errors will prevent your add-in from running. One way to provide a proxy is by using JSON/P. For more information, see [Privacy and security for Office Add-ins](../concepts/privacy-and-security.md).| ## Using the makeEwsRequestAsync method to access EWS operations > [!IMPORTANT] > EWS calls and operations aren't supported in add-ins running in Outlook on Android and on iOS. -You can use the [mailbox.makeEwsRequestAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox#methods) method to make an EWS request to the Exchange server that hosts the user's mailbox. +You can use the [mailbox.makeEwsRequestAsync](/javascript/api/requirement-sets/outlook/preview-requirement-set/office.context.mailbox#methods) method to make an EWS request to the on-premises Exchange server that hosts the user's mailbox. -EWS supports different operations on an Exchange server; for example, item-level operations to copy, find, update, or send an item, and folder-level operations to create, get, or update a folder. To perform an EWS operation, create an XML SOAP request for that operation. When the operation finishes, you get an XML SOAP response that contains data that is relevant to the operation. EWS SOAP requests and responses follow the schema defined in the Messages.xsd file. Like other EWS schema files, the Message.xsd file is located in the IIS virtual directory that hosts EWS. +EWS supports different operations on an Exchange server; for example, item-level operations to copy, find, update, or send an item, and folder-level operations to create, get, or update a folder. To perform an EWS operation, create an XML SOAP request for that operation. When the operation finishes, you get an XML SOAP response that contains data that's relevant to the operation. EWS SOAP requests and responses follow the schema defined in the **Messages.xsd** file. Like other EWS schema files, the **Message.xsd** file is located in the IIS virtual directory that hosts EWS. To use the `makeEwsRequestAsync` method to initiate an EWS operation, provide the following: -- The XML for the SOAP request for that EWS operation, as an argument to the _data_ parameter +- The XML for the SOAP request for that EWS operation as an argument to the *data* parameter. -- A callback function (as the _callback_ argument) +- A callback function (as the *callback* argument). -- Any optional input data for that callback function (as the _userContext_ argument) +- Any optional input data for that callback function (as the *userContext* argument). -When the EWS SOAP request is complete, Outlook calls the callback function with one argument, which is an [AsyncResult](/javascript/api/office/office.asyncresult) object. The callback function can access two properties of the `AsyncResult` object: the `value` property, which contains the XML SOAP response of the EWS operation, and optionally, the `asyncContext` property, which contains any data passed as the `userContext` parameter. Typically, the callback function then parses the XML in the SOAP response to get any relevant information, and processes that information accordingly. +When the EWS SOAP request is complete, Outlook calls the callback function with one argument, which is an [AsyncResult](/javascript/api/office/office.asyncresult) object. The callback function can access two properties of the `AsyncResult` object: the `value` property, which contains the XML SOAP response of the EWS operation, and optionally, the `asyncContext` property, which contains any data passed as the `userContext` parameter. Typically, the callback function then parses the XML in the SOAP response to get any relevant information and processes that information accordingly. ## Tips for parsing EWS responses When parsing a SOAP response from an EWS operation, note the following browser-dependent issues. -- Specify the prefix for a tag name when using the DOM method `getElementsByTagName`, to include support for Internet Explorer and the Trident webview. +- Specify the prefix for a tag name when using the DOM method `getElementsByTagName` to include support for Internet Explorer and the Trident webview. `getElementsByTagName` behaves differently depending on browser type. For example, an EWS response can contain the following XML (formatted and abbreviated for display purposes). @@ -60,7 +60,7 @@ When parsing a SOAP response from an EWS operation, note the following browser-d ```js const mailbox = Office.context.mailbox; - mailbox.makeEwsRequestAsync(mailbox.item.itemId, function(result) { + mailbox.makeEwsRequestAsync(mailbox.item.itemId, (result) => { const response = $.parseXML(result.value); const extendedProps = response.getElementsByTagName("ExtendedProperty") }); @@ -70,7 +70,7 @@ When parsing a SOAP response from an EWS operation, note the following browser-d ```js const mailbox = Office.context.mailbox; - mailbox.makeEwsRequestAsync(mailbox.item.itemId, function(result) { + mailbox.makeEwsRequestAsync(mailbox.item.itemId, (result) => { const response = $.parseXML(result.value); const extendedProps = response.getElementsByTagName("t:ExtendedProperty") }); @@ -92,7 +92,7 @@ The following example calls `makeEwsRequestAsync` to use the [GetItem](/exchange - `sendRequest` – Calls `getSubjectRequest` to get the SOAP request for the selected item, then passes the SOAP request and the callback function, `callback`, to `makeEwsRequestAsync` to get the subject of the specified item. -- `callback` – Processes the SOAP response which includes any subject and other information about the specified item. +- `callback` – Processes the SOAP response, which includes any subject and other information about the specified item. ```js function getSubjectRequest(id) { @@ -139,13 +139,13 @@ function callback(asyncResult) { ## EWS operations that add-ins support -Outlook add-ins can access a subset of operations that are available in EWS via the `makeEwsRequestAsync` method. If you are unfamiliar with EWS operations and how to use the `makeEwsRequestAsync` method to access an operation, start with a SOAP request example to customize your _data_ argument. +Outlook add-ins can access a subset of operations that are available in EWS via the `makeEwsRequestAsync` method. If you're unfamiliar with EWS operations and how to use the `makeEwsRequestAsync` method to access an operation, start with a SOAP request example to customize your *data* argument. The following describes how you can use the `makeEwsRequestAsync` method. 1. In the XML, substitute any item IDs and relevant EWS operation attributes with appropriate values. -1. Include the SOAP request as an argument for the _data_ parameter of `makeEwsRequestAsync`. +1. Include the SOAP request as an argument for the *data* parameter of `makeEwsRequestAsync`. 1. Specify a callback function and call `makeEwsRequestAsync`. @@ -176,19 +176,19 @@ The following table lists the EWS operations that add-ins support. To see exampl |[UpdateItem operation](/exchange/client-developer/web-service-reference/updateitem-operation)|Modifies the properties of existing items in the Exchange store.| > [!NOTE] - > FAI (Folder Associated Information) items cannot be updated (or created) from an add-in. These hidden messages are stored in a folder and are used to store a variety of settings and auxiliary data. Attempting to use the UpdateItem operation will throw an ErrorAccessDenied error: "Office extension is not allowed to update this type of item". As an alternative, you may use the [EWS Managed API](/exchange/client-developer/exchange-web-services/get-started-with-ews-managed-api-client-applications) to update these items from a Windows client or a server application. Caution is recommended as internal, service-type data structures are subject to change and could break your solution. + > FAI (Folder Associated Information) items can't be updated (or created) from an add-in. These hidden messages are stored in a folder and are used to store a variety of settings and auxiliary data. Attempting to use the UpdateItem operation will throw an ErrorAccessDenied error: "Office extension is not allowed to update this type of item". As an alternative, you may use the [EWS Managed API](/exchange/client-developer/exchange-web-services/get-started-with-ews-managed-api-client-applications) to update these items from a Windows client or a server application. Caution is recommended as internal, service-type data structures are subject to change and could break your solution. ## Authentication and permission considerations for makeEwsRequestAsync -When you use the `makeEwsRequestAsync` method, the request is authenticated by using the email account credentials of the current user. The `makeEwsRequestAsync` method manages the credentials for you so that you do not have to provide authentication credentials with your request. +When you use the `makeEwsRequestAsync` method, the request is authenticated by using the email account credentials of the current user. The `makeEwsRequestAsync` method manages the credentials for you so that you don't have to provide authentication credentials with your request. > [!NOTE] -> The server administrator must use the [New-WebServicesVirtualDirectory](/powershell/module/exchange/client-access-servers/New-WebServicesVirtualDirectory?view=exchange-ps&preserve-view=true) or the [Set-WebServicesVirtualDirectory](/powershell/module/exchange/client-access-servers/Set-WebServicesVirtualDirectory?view=exchange-ps&preserve-view=true) cmdlet to set the _OAuthAuthentication_ parameter to `true` on the Client Access server EWS directory in order to enable the `makeEwsRequestAsync` method to make EWS requests. +> The server administrator must use the [New-WebServicesVirtualDirectory](/powershell/module/exchangepowershell/new-webservicesvirtualdirectory) or the [Set-WebServicesVirtualDirectory](/powershell/module/exchangepowershell/set-webservicesvirtualdirectory) cmdlet to set the *OAuthAuthentication* parameter to `true` on the Client Access server EWS directory in order to enable the `makeEwsRequestAsync` method to make EWS requests. To use the `makeEwsRequestAsync` method, your add-in must request the **read/write mailbox** permission in the manifest. The markup varies depending on the type of manifest. -- **Add-in only manifest**: Set the **\<Permissions\>** element to **ReadWriteMailbox**. -- **Unified manifest for Microsoft 365**: Set the "name" property of an object in the "authorization.permissions.resourceSpecific" array to "Mailbox.ReadWrite.User". +- **Add-in only manifest**: Set the `<Permissions>` element to **ReadWriteMailbox**. +- **Unified manifest for Microsoft 365**: Set the `"name"` property of an object in the [`"authorization.permissions.resourceSpecific"`](/microsoft-365/extensibility/schema/root-authorization-permissions#resourcespecific) array to `"Mailbox.ReadWrite.User"`. For information about using the **read/write mailbox** permission, see [read/write mailbox permission](understanding-outlook-add-in-permissions.md#readwrite-mailbox-permission). diff --git a/docs/overview/core-concepts-office-add-ins.md b/docs/overview/core-concepts-office-add-ins.md index eab72ff81f..1d27c0deb2 100644 --- a/docs/overview/core-concepts-office-add-ins.md +++ b/docs/overview/core-concepts-office-add-ins.md @@ -1,22 +1,74 @@ --- -layout: LandingPage -ms.topic: landing-page title: Development lifecycle overview description: Learn about the planning, developing, testing, and publishing lifecycle events. -ms.date: 06/23/2023 +ms.author: lindalu +ms.topic: overview +ms.date: 06/11/2025 ms.localizationpriority: high --- -# Development lifecycle overview +# Office Add-in development lifecycle -All Office Add-ins are built upon the Office Add-ins platform. They share a common framework through which certain capabilities can be implemented. This means that regardless of whether you're creating an add-in for Excel, Outlook, or another Office application, you can implement features such as dialog boxes, add-in commands, task panes, and single sign-on (SSO). +All Office Add-ins are built upon the Office Add-ins platform. They share a common framework through which add-in capabilities are implemented. This means that regardless of whether you're creating an add-in for Excel, Outlook, or another Office application, you can have features such as dialog boxes, add-in commands, task panes, and single sign-on (SSO). -For any add-in you build, you need to understand important concepts like Office application and platform availability, Office JavaScript API programming patterns, how to specify an add-in's settings and capabilities in the manifest file, how to test, debug, and publish an add-in, and more. Review the documentation listed in the following table. That gives you a good foundation for the application-specific documentation that corresponds to the add-in you're building, such as [Excel](../excel/index.yml). +For any add-in you build, you need to understand the following concepts. -| | | -| ------------- | ------------- | -| :::image type="icon" source="../images/i_best-practices_small.svg"::: | **Plan**<br>[Learn the best practices and system requirements for Office Add-ins.](../concepts/add-in-development-best-practices.md) | -| :::image type="icon" source="../images/i_code-blocks_small.svg"::: | **Develop**<br>[Learn the APIs and patterns to develop Office Add-ins.](../develop/develop-overview.md) | -| :::image type="icon" source="../images/i_recommended-testing_small.svg"::: | **Test and debug**<br>[Learn how to test and debug Office Add-ins.](../testing/test-debug-office-add-ins.md) | -| :::image type="icon" source="../images/i_deploy_small.svg"::: | **Publish**<br>[Learn how to deploy and publish Office Add-ins.](../publish/publish.md) | -| :::image type="icon" source="../images/i_reference_small.svg"::: | **Reference**<br>[View the reference documentation for the Office JavaScript APIs, the add-ins manifest, error code lists, and more.](../reference/javascript-api-for-office.md) | +- Office application and platform availability +- Office JavaScript API programming patterns +- How to specify an add-in's settings and capabilities in the manifest file +- Troubleshooting your add-in +- Publishing your add-in + +For the best foundation for these common features and application-specific implementations, review the following documentation. + +:::row::: + :::column span=""::: + :::image type="content" source="../images/office-add-ins-lifecycle-step-1-plan.png" alt-text="Illustration of a route winding through mountains." border="false"::: + :::column-end::: + :::column span="3"::: + <br>**Plan**<br> + [Learn the best practices and system requirements for Office Add-ins.](../concepts/add-in-development-best-practices.md) + :::column-end::: +:::row-end::: +:::row::: + :::column span=""::: + :::image type="content" source="../images/office-add-ins-lifecycle-step-2-develop.png" alt-text="Illustration of a plan, a cog, and a wrench." border="false"::: + :::column-end::: + :::column span="3"::: + <br>**Develop**<br> + [Learn the APIs and patterns to develop Office Add-ins.](../develop/develop-overview.md) + :::column-end::: +:::row-end::: +:::row::: + :::column span=""::: + :::image type="content" source="../images/office-add-ins-lifecycle-step-3-test-and-debug.png" alt-text="Illustration of an eye looking through a magnifying glass." border="false"::: + :::column-end::: + :::column span="3"::: + <br>**Test and debug**<br> + [Learn how to test and debug Office Add-ins.](../testing/test-debug-office-add-ins.md) + :::column-end::: +:::row-end::: +:::row::: + :::column span=""::: + :::image type="content" source="../images/office-add-ins-lifecycle-step-4-publish.png" alt-text="Illustration of a rocket ship being deployed." border="false"::: + :::column-end::: + :::column span="3"::: + <br>**Publish**<br> + [Learn how to deploy and publish Office Add-ins.](../publish/publish.md) + :::column-end::: +:::row-end::: +:::row::: + :::column span=""::: + :::image type="content" source="../images/office-add-ins-lifecycle-step-5-reference.png" alt-text="Illustration of a large reference book." border="false"::: + :::column-end::: + :::column span="3"::: + <br>**Reference**<br> + [View the reference documentation for the Office JavaScript APIs, the add-ins manifest, error code lists, and more.](../reference/javascript-api-for-office.md) + :::column-end::: +:::row-end::: + +## See also + +- [Office Dev Center](https://developer.microsoft.com/office) +- [Office Add-ins platform overview](../overview/office-add-ins.md) +- [Office client application and platform availability for Office Add-ins](/javascript/api/requirement-sets) diff --git a/docs/overview/explore-with-script-lab.md b/docs/overview/explore-with-script-lab.md index 38452150d1..0e9573b403 100644 --- a/docs/overview/explore-with-script-lab.md +++ b/docs/overview/explore-with-script-lab.md @@ -1,7 +1,7 @@ ---- +--- title: Explore Office JavaScript API using Script Lab description: Use Script Lab to explore the Office JS API and to prototype functionality. -ms.date: 09/05/2024 +ms.date: 03/21/2025 ms.topic: concept-article ms.custom: scenarios:getting-started ms.localizationpriority: high @@ -43,7 +43,7 @@ In addition to JavaScript or TypeScript code that calls the Office JS API, each #### Preview APIs -To call preview APIs within a snippet, you need to update the snippet's libraries to use the beta content delivery network (CDN) (`https://appsforoffice.microsoft.com/lib/beta/hosted/office.js`) and the preview type definitions `@types/office-js-preview`. Additionally, some preview APIs are only accessible if you've signed up for the [Microsoft 365 Insider program](https://insider.microsoft365.com) and are running an Insider build of Office. +To call preview APIs within a snippet, you need to update the snippet's libraries to use the beta content delivery network (CDN) (`https://appsforoffice.microsoft.com/lib/beta/hosted/office.js`) and the preview type definitions `@types/office-js-preview`. Additionally, some preview APIs are only accessible if you've signed up for the [Microsoft 365 Insider program](https://aka.ms/MSFT365InsiderProgram) and are running an Insider build of Office. ### Save and share snippets @@ -68,6 +68,14 @@ Script Lab for Outlook is available on the following clients. > [!IMPORTANT] > \* Script Lab no longer works with combinations of platform and Office version that use the Trident (Internet Explorer) webview to host add-ins. This includes perpetual versions of Office through Office 2019. For more information, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). +## Limitations + +Script Lab is designed for you to play with small code samples. Generally, a snippet should be at most a few hundred lines and a few thousand characters. + +Your snippet can use hard-coded data. A small amount of data (say, a few hundred characters) is OK to hard code in Script Lab. However, for larger pieces of data, we recommend that you store those externally then load them at runtime with a command like `fetch`. + +Keep your snippets and hard-coded data small since storing several large snippets could exceed Script Lab's storage and cause issues when loading Script Lab. + ## Next steps > [!div class="nextstepaction"] @@ -76,9 +84,17 @@ Script Lab for Outlook is available on the following clients. > [!div class="nextstepaction"] > [Get Script Lab for Outlook](https://appsource.microsoft.com/product/office/wa200001603) -Once you've prototyped your code in Script Lab, turn it into a real add-in with the steps in [Create a standalone Office Add-in from your Script Lab code](./create-an-office-add-in-from-script-lab.md). +Once you've prototyped your code in Script Lab, turn it into a real add-in with the steps in [Create a standalone Office Add-in from your Script Lab code](create-an-office-add-in-from-script-lab.md). + +## Issues + +If you find an issue or have feedback for us, let us know! + +- Issue in this article? See the "Office Add-ins feedback" section at the end of this article. +- Problem with a Script Lab code sample? Open a new issue in the [office-js-snippets GitHub repository](https://github.com/OfficeDev/office-js-snippets/issues). +- Feedback or issue with the Script Lab tool? Open a new issue in the [office-js GitHub repository](https://aka.ms/script-lab-issues). ## See also -- [Script Lab sample GitHub repository](https://github.com/OfficeDev/office-js-snippets#office-js-snippets) +- [Script Lab samples GitHub repository](https://github.com/OfficeDev/office-js-snippets#office-js-snippets) - [Developing Office Add-ins](../develop/develop-overview.md) diff --git a/docs/overview/learning-path-beginner.md b/docs/overview/learning-path-beginner.md index 7455add932..6478073299 100644 --- a/docs/overview/learning-path-beginner.md +++ b/docs/overview/learning-path-beginner.md @@ -1,7 +1,7 @@ ---- +--- title: Beginner's guide to Office Add-ins description: A recommended path for beginners through the learning resources for Office Add-ins. -ms.date: 08/22/2024 +ms.date: 06/25/2025 ms.topic: get-started ms.custom: scenarios:getting-started ms.localizationpriority: high @@ -43,7 +43,7 @@ You can't learn to drive by reading the owner's manual, so start coding with thi ## Step 5: Understand the JavaScript library -For an overview of the Office JavaScript library, see this tutorial from Microsoft Learn training: [Understand the Office JavaScript APIs](/training/modules/understand-office-javascript-apis/index). +For an overview of the Office JavaScript library, see [Develop Office Add-ins](../develop/develop-overview.md). Then return to Script Lab and use it like a playground: make your own code changes to the local copy of any samples you try and see how the results are affected. @@ -51,6 +51,10 @@ Then return to Script Lab and use it like a playground: make your own code chang Get an understanding of the purposes of the add-in manifest and an introduction to its XML markup or JSON in [Office Add-ins manifest](../develop/add-in-manifests.md). +## Step 7: Create a Partner Center account + +If you plan to [publish your add-in to Microsoft Marketplace](../publish/publish.md), create a [Partner Center account](/partner-center/marketplace-offers/open-a-developer-account). This could take some time. Get this process going as soon as possible to avoid release delays. + ## Next Steps Congratulations on finishing the beginner's learning path for Office Add-ins! Here are some suggestions for further exploration of our documentation: @@ -59,7 +63,7 @@ Congratulations on finishing the beginner's learning path for Office Add-ins! He - [OneNote quick start](../quickstarts/onenote-quickstart.md) - [Outlook tutorial](/outlook/add-ins/addin-tutorial) - - [PowerPoint tutorial](../tutorials/powerpoint-tutorial.md) + - [PowerPoint tutorial](../tutorials/powerpoint-tutorial-yo.md) - [Project quick start](../quickstarts/project-quickstart.md) - [Word tutorial](../tutorials/word-tutorial.md) diff --git a/docs/overview/learning-path-transition.md b/docs/overview/learning-path-transition.md index 54e9483f99..047fb7e464 100644 --- a/docs/overview/learning-path-transition.md +++ b/docs/overview/learning-path-transition.md @@ -1,7 +1,7 @@ ---- +--- title: VSTO add-in developer's guide to Office Web Add-ins description: A recommended path for experienced VSTO add-in developers to learning resources for Office Web Add-ins. -ms.date: 08/22/2024 +ms.date: 06/25/2025 ms.topic: get-started ms.custom: scenarios:getting-started ms.localizationpriority: high @@ -41,11 +41,11 @@ You've got the big picture now, so dive in with one of our quick starts. For pur ## Step 3: Code -You can't learn to drive by reading the owner's manual, so start coding with this [PowerPoint tutorial](../tutorials/powerpoint-tutorial.md?tabs=visualstudio). You'll be using the Office JavaScript library and some XML in the add-in's manifest. There's no need to memorize anything, because you'll be getting more background about both in a later step. +You can't learn to drive by reading the owner's manual, so start coding with this [PowerPoint tutorial](../tutorials/powerpoint-tutorial-vs.md). You'll be using the Office JavaScript library and some XML in the add-in's manifest. There's no need to memorize anything, because you'll be getting more background about both in a later step. ## Step 4: Understand the JavaScript library -Get the big picture of the Office JavaScript library with the [Understand the Office JavaScript APIs tutorial](/training/modules/intro-office-add-ins/3-apis) from Microsoft Learn training. +Get the big picture of the Office JavaScript library with the article [Develop Office Add-ins](../develop/develop-overview.md). Then, explore the Office JavaScript APIs with the [Script Lab tool](explore-with-script-lab.md) -- a sandbox for running and exploring the APIs. @@ -61,6 +61,10 @@ Get an understanding of the purposes of the web add-in manifest and an introduct You can reuse some of your VSTO add-in code in an Office web add-in by moving it to your web application's back end on the server and making it available to your JavaScript or TypeScript as a web API. For guidance, see [Tutorial: Share code between both a VSTO Add-in and an Office Add-in by using a shared code library](../tutorials/migrate-vsto-to-office-add-in-shared-code-library-tutorial.md). +## Step 7: Create a Partner Center account + +If you plan to [publish your add-in to Microsoft Marketplace](../publish/publish.md), create a [Partner Center account](/partner-center/marketplace-offers/open-a-developer-account). This could take some time. Get this process going as soon as possible to avoid release delays. + ## Next Steps Congratulations on finishing the VSTO add-in developer's learning path for Office Web Add-ins! Here are some suggestions for further exploration of our documentation: diff --git a/docs/overview/npm-warnings-advice.md b/docs/overview/npm-warnings-advice.md new file mode 100644 index 0000000000..e26817f19a --- /dev/null +++ b/docs/overview/npm-warnings-advice.md @@ -0,0 +1,60 @@ +--- +title: Warnings and dependencies in the Node.js and npm world +description: Learn about aspects of npm development that are disconcerting to COM and VSTO developers. +ms.date: 07/07/2025 +ms.localizationpriority: medium +--- + +# Warnings and dependencies in the Node.js and npm world + +COM and VSTO add-in developers who are new to the world of [Node Package Manager (npm)](https://www.npmjs.com/) and open source development are often surprised and alarmed at certain aspects of this kind of development. This article is intended to reassure such developers about things they may find disconcerting. + +## npm dependency tree + +npm is the standard package manager for the JavaScript runtime environment Node.js. It's used to streamline JavaScript development workflows by enabling developers to install open source libraries and tools (collectively called "packages"), and to manage package dependencies. + +The npm dependency tree is a hierarchical structure that represents all the packages your Node.js project depends on. Each node in the tree is a package, and its children are the packages it depends on. This structure can become deeply nested, especially in large projects or when using packages with many transitive dependencies. + +When you run `npm install`, npm reads the package.json and package-lock.json files in a development project to build this tree and fetch the required packages. + +## Understand `npm install` warnings + +When you run `npm install`, it's common to see a flurry of warnings in the console. This can be surprising at first, but it's a normal part of working in the Node.js and open source ecosystem. Microsoft tools that call `npm install`, including the [Yeoman Generator for Office Add-ins](../develop/yeoman-generator-overview.md), report these same warnings. + +It's beyond the scope of this article to discuss every kind of warning that `npm install` might report, but there are two kinds that are especially likely to be disconcerting to developers who are new to the Node.js world. + +### Deprecation warnings + +These warnings mean that the managers of a package somewhere in the dependency tree are no longer maintaining it and they may remove it from the Internet at some future time. Neither you, nor Microsoft, has any control over the package deprecation warnings, but you can almost always ignore them. Deprecation doesn't mean that the package has stopped working. It still works and because installation puts a copy of it on your computer, it'll continue to work with your project in the future even if the package is removed from the Internet. The package isn't a web service. + +It's very unlikely, but possible, that you'll see a deprecation warning for a package that's at the *top* of the dependency tree. These are the packages that are explicitly listed in the "dependencies" or "devDependencies" sections of the project's package.json file. You can ignore deprecation warnings for "devDependencies" for the same reason given earlier: the code is copied to your development computer. Packages in the "dependencies" section are used by your add-in at runtime, but even deprecation warnings for these can be ignored in projects that are created with Microsoft tools like the Yeoman Generator for Office Add-ins and [Microsoft 365 Agent Toolkit](../develop/agents-toolkit-overview.md) because these tools include copies of the libraries in bundles of JavaScript code that your add-in's web server will serve. + +> [!NOTE] +> One situation in which the deprecation of a library in the "dependencies" section is a matter of concern is the following: +> +> - The library is in the "dependencies" section only so you can use it while testing and debugging locally. +> - Your plan, when you deploy the add-in for staging or production, is to not include a copy of the library in the code that your server hosts. +> - Instead, you plan to have the add-in load the library from a web service that hosts npm libraries, such as unpkg.com or cdn.jsdelivr.net. +> +> If this describes your deployment strategy, then there's a danger that your deployed add-in will stop working if the deprecated library is removed from the web service. So, treat the deprecation warning as a notice that you need to redesign your add-in so that it doesn't use the deprecated library. + +### Security or audit warnings + +Security warnings, also called audit warnings, mean that there's a version of the package in the dependency tree that has a known security vulnerability that a hacker could take advantage of. Microsoft periodically checks for these warnings in projects created by our tools and fixes them, usually by updating the library to a newer version that doesn't have the vulnerability. But new vulnerabilities are discovered and reported almost daily to the security alert databases that `npm install` monitors, and Microsoft cannot always fix them right away. For this reason, it isn't uncommon that running `npm install` in an add-in project reports security vulnerabilities. + +When the dependency can be traced to a top-level package in the "devDependencies" section of package.json, then you can ignore it. The code is only running on your computer, and you're not going to hack yourself. + +If the dependency traces to a top-level package in the "dependencies" section, or you cannot determine the top-level package, then you should try to fix the vulnerability before you deploy the add-in to production. There's lots of good information on the Internet about how to deal with vulnerabilities in npm packages. We'll mention one technique here. Some vulnerabilities can be fixed automatically by npm. Just run the command `npm audit fix` in the folder where the package.json file is. If there's a newer version of the package that doesn't have the vulnerability and the newer version doesn't have any breaking changes relative to the vulnerable version, then npm will automatically update the package to the safe version. + +Another strategy is to take a few minutes every couple of weeks to create a new add-in project with the same Microsoft tool as you created your original project. (Choose the same options for project type,, language, Office application, etc.) If `npm install` no longer reports the security vulnerability on the new project, then Microsoft has fixed it in the project template. You can move the fix to your project with the following steps. + +1. Copy the "dependencies" section of from the new project over the same section in the **package.json** of the original project. +1. Delete the **node_modules** folder from the original project. +1. Run `npm install` in the original project. + +## Errors + +An npm *error*, as distinct from a warning, immediately stops the processing of the npm command, including `npm install`. You must diagnose and fix the problem. Sometimes the error is a side effect of a temporary network problem when npm tries to fetch a package. Try rerunning `npm install`. + +> [!NOTE] +> Running `npm install` is the last thing that the Yeoman Generator for Office Add-ins does when it creates a project. If an error is reported, you don't need to rerun the generator because the project has been fully created. You can just rerun `npm install` at the command line. diff --git a/docs/overview/office-add-in-code-samples.md b/docs/overview/office-add-in-code-samples.md index 49f21c6838..2576719ee5 100644 --- a/docs/overview/office-add-in-code-samples.md +++ b/docs/overview/office-add-in-code-samples.md @@ -1,7 +1,7 @@ --- title: Office Add-in code samples description: A list of Office Add-in code samples to help you learn and build your own add-ins. -ms.date: 07/24/2024 +ms.date: 09/27/2024 ms.localizationpriority: high --- @@ -34,7 +34,6 @@ If your development background is in building VSTO Add-ins, the following sample | [Open in Teams](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-open-in-teams) | Create a new Excel spreadsheet in Microsoft Teams containing data you define.| | [Insert an external Excel file and populate it with JSON data](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-insert-file) | Insert an existing template from an external Excel file into the currently open Excel workbook. Then, populate the template with data from a JSON web service. | | [Create custom contextual tabs on the ribbon](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/office-contextual-tabs) | Create a custom contextual tab on the ribbon in the Office UI. The sample creates a table, and when the user moves the focus inside the table, the custom tab is displayed. When the user moves outside the table, the custom tab is hidden. | -| [Use keyboard shortcuts for Office Add-in actions](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-keyboard-shortcuts) | Set up a basic Excel add-in project that utilizes keyboard shortcuts. | | [Custom function sample using web worker](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Excel-custom-functions/web-worker) | Use web workers in custom functions to prevent blocking the UI of your Office Add-in. | | [Use storage techniques to access data from an Office Add-in when offline](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/Excel.OfflineStorageAddin) | Implement localStorage to enable limited functionality for your Office Add-in when a user experiences lost connection. | | [Custom function batching pattern](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Excel-custom-functions/Batching)| Batch multiple calls into a single call to reduce the number of network calls to a remote service.| @@ -78,6 +77,7 @@ If your development background is in building VSTO Add-ins, the following sample | Name | Description | |:--------------------|:--------------------| | [Save custom settings in your Office Add-in](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/office-add-in-save-custom-settings) | Save custom settings inside an Office Add-in. The add-in stores data as key-value pairs, using the JavaScript API for Office property bag, browser cookies, web storage (localStorage and sessionStorage), or by storing the data in a hidden div in the document. | +| [Use keyboard shortcuts for Office Add-in actions](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/office-keyboard-shortcuts) | Create custom keyboard shortcuts to invoke certain actions for your Office Add-in. | ## Shared runtime diff --git a/docs/overview/office-add-ins-community-call.md b/docs/overview/office-add-ins-community-call.md index 5b309c0553..460226fd43 100644 --- a/docs/overview/office-add-ins-community-call.md +++ b/docs/overview/office-add-ins-community-call.md @@ -1,7 +1,7 @@ --- title: Microsoft Office Add-ins community call description: The monthly Microsoft Office Add-ins community call agenda, schedule, and resources. -ms.date: 04/17/2024 +ms.date: 10/08/2025 ms.localizationpriority: medium --- @@ -12,13 +12,9 @@ The Microsoft Office Add-ins community call is a monthly call where you can lear > [!IMPORTANT] > We have changed the schedule to 7:00 AM Pacific Time. If you still have the old calendar invite that starts at 8:00 AM Pacific Time, please remove it and download the latest one at <https://aka.ms/officeaddinscommunitycall>. -## Agenda for September 11, 2024 call -Here is the agenda for the September Office Add-ins community call. -* PowerPoint preview APIs and Ribbon 1.1 API updates​. -* Word API updates​. -* A new NAA sample for event-based Outlook add-ins​. -* Visual Studio Code extension: Office Add-ins Developer Kit (public preview​). -* Extend Teams apps to support Excel, PowerPoint, and Word add-ins (public preview).​ +## Agenda for November 12th, 2025 call + +The agenda for the November 12th Office Add-ins community call will be posted the week before the call. > [!NOTE] > For us to improve our community call experience and better understand our audience, we invite you to fill out this survey: [Office Add-ins Developer Community Survey](https://forms.office.com/r/YNDtW8wQ6U). @@ -38,4 +34,3 @@ Missed a previous community call? Check out the blog resources on the [Microsoft - [Microsoft 365 community YouTube channel](https://aka.ms/m365devyoutube) - [Microsoft 365 community site](https://aka.ms/m365pnp/community) - [Microsoft 365 community blog](https://aka.ms/m365pnp/community/blog) -- [Archived Office Add-ins community calls – June 10, 2020 - February 10, 2021](https://cdn.graph.office.net/prod/office/Office-Add-ins-Community-Call-Archive.pdf) diff --git a/docs/overview/office-add-ins.md b/docs/overview/office-add-ins.md index 55886c8a8a..9dba7f68e1 100644 --- a/docs/overview/office-add-ins.md +++ b/docs/overview/office-add-ins.md @@ -1,7 +1,7 @@ ---- +--- title: Office Add-ins platform overview description: Use familiar web technologies such as HTML, CSS, and JavaScript to extend and interact with Word, Excel, PowerPoint, OneNote, Project, and Outlook. -ms.date: 07/25/2024 +ms.date: 02/19/2025 ms.topic: overview ms.custom: scenarios:getting-started ms.localizationpriority: high @@ -31,11 +31,11 @@ Office Add-ins provide the following advantages over add-ins built using VBA, CO - Centralized deployment and distribution: Admins can deploy Office Add-ins centrally across an organization. -- Easy access via AppSource: You can make your solution available to a broad audience by submitting it to AppSource. +- Easy access via Microsoft Marketplace: You can make your solution available to a broad audience by submitting it to Microsoft Marketplace. - Based on standard web technology: You can use any library you like to build Office Add-ins. -![The reasons to use Office Add-ins: cross-platform, centralized deployment, easy access via AppSource, and built on standard web technologies.](../images/why.png) +![The reasons to use Office Add-ins: cross-platform, centralized deployment, easy access via Microsoft Marketplace, and built on standard web technologies.](../images/why.png) [!INCLUDE [new-outlook-vsto-com-support](../includes/new-outlook-vsto-com-support.md)] @@ -97,6 +97,9 @@ Users can run Outlook add-ins when they view, reply, or create emails, meeting r - Display contextually next to an Outlook item when you're viewing or composing it. - Perform a task when a specific event occurs, such as when a user creates a new message. +> [!NOTE] +> [!INCLUDE [Calendar add-ins not available in Teams](../includes/calendar-availability.md)] + For an overview of Outlook add-ins, see [Outlook add-ins overview](../outlook/outlook-add-ins-overview.md). ### Create new objects in Office documents diff --git a/docs/overview/set-up-your-dev-environment.md b/docs/overview/set-up-your-dev-environment.md index 180eac0f6d..e3f9d5d5bf 100644 --- a/docs/overview/set-up-your-dev-environment.md +++ b/docs/overview/set-up-your-dev-environment.md @@ -1,7 +1,7 @@ ---- +--- title: Set up your development environment description: Set up your developer environment to build Office Add-ins. -ms.date: 08/22/2024 +ms.date: 10/08/2025 ms.topic: install-set-up-deploy ms.localizationpriority: medium --- @@ -19,7 +19,7 @@ You need a Microsoft 365 account. You might qualify for a Microsoft 365 E5 devel There are three kinds of development environments to choose from. The scaffolding of Office Add-in projects that is created in the three environments is different, so if multiple people will be working on an add-in project, they must all use the same environment. - **Node.js environment**: Recommended. In this environment, your tools are installed and run at a command line. The server-side of the web application part of the add-in is written in JavaScript or TypeScript and is hosted in a Node.js runtime. There are many helpful add-in development tools in this environment, such as an Office linter and a bundler/task-runner called webpack. The project creation and scaffolding tool is a command line tool called the Office Yeoman Generator (also called "Yo Office"), though you can still use the Visual Studio Code extensions mentioned in the next option. -- **Visual Studio Code**: Choose this environment if you use Visual Studio Code and would prefer to create projects from extensions rather than command line tools. The project creation and scaffolding tools are the Teams Toolkit or Office Add-ins Development Kit extensions. +- **Visual Studio Code**: Choose this environment if you use Visual Studio Code and would prefer to create projects from extensions rather than command line tools. The project creation and scaffolding tools are Microsoft 365 Agents Toolkit or Office Add-ins Development Kit extensions. - **Visual Studio environment**: Choose this environment only if your development computer is Windows, and you want to develop the server-side of the add-in with a .NET based language and framework, such as ASP.NET. The add-in project templates in Visual Studio aren't updated as frequently as those in the Node.js environment. More information later on the **Visual Studio environment** tab. > [!NOTE] @@ -59,7 +59,7 @@ The project creation and scaffolding tool is [Yeoman generator for Office Add-in ### Install and use the Office JavaScript linter -Microsoft provides a JavaScript linter to help you catch common errors when using the Office JavaScript library. If you create an add-in project with either the [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md) or [Teams Toolkit](../develop/teams-toolkit-overview.md), then the linter is installed and configured for you. Skip to [Run the linter](#run-the-linter). +Microsoft provides a JavaScript linter to help you catch common errors when using the Office JavaScript library. If you create an add-in project with either the [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md) or [Agents Toolkit](../develop/agents-toolkit-overview.md), then the linter is installed and configured for you. Skip to [Run the linter](#run-the-linter). If you created your project manually, install and configure the linter with the following steps. @@ -70,17 +70,25 @@ If you created your project manually, install and configure the linter with the npm install eslint-plugin-office-addins --save-dev ``` -1. In the root of the project, create a text file named **.eslintrc.json**, if there isn't one already there. Be sure it has properties named `plugins` and `extends`, both of type array. The `plugins` array should include `"office-addins"` and the `extends` array should include `"plugin:office-addins/recommended"`. The following is a simple example. Your **.eslintrc.json** file may have additional properties and additional members of the two arrays. - - ```json - { - "plugins": [ - "office-addins" - ], - "extends": [ - "plugin:office-addins/recommended" - ] - } +1. In the root of the project, create a text file named **eslint.config.js** (or **.mjs**), if there isn't one already there. Be sure to inherit the recommended configuration for `eslint-plugin-office-addins`. The `plugins` object should include a mapping to the `eslint-plugin-office-addins` plugin object. The following is a simple example that includes settings for TypeScript. Your **eslint.config.js** file may have additional properties and configurations. + + ```js + const officeAddins = require("eslint-plugin-office-addins"); + const tsParser = require("@typescript-eslint/parser"); + const tsEsLint = require("typescript-eslint"); + + export default [ + ...tsEsLint.configs.recommended, + ...officeAddins.configs.recommended, + { + plugins: { + "office-addins": officeAddins, + }, + languageOptions: { + parser: tsParser, + }, + }, + ]; ``` 1. In the root of the project, open the **package.json** file and be sure that the `scripts` array has the following member. @@ -105,8 +113,8 @@ The main tools to be installed are: - npm - Visual Studio Code - A project creation tool: - - Teams Toolkit - - The Office Add-ins Development Kit for VS Code + - Microsoft 365 Agents Toolkit + - Office Add-ins Development Kit for VS Code This guide assumes that you know how to use a command-line tool. @@ -118,13 +126,13 @@ Get the latest version of Visual Studio Code from [Visual Studio Code homepage]( ### Install a project creation tool -You can create Office add-in projects in Visual Studio Code with either the Teams Toolkit or Office Add-ins Development Kit extensions. Currently, Teams Toolkit focuses on Outlook add-ins that use the modern unified manifest. The Office Add-ins Development Kit is in preview and only focuses on Excel, PowerPoint, and Word experiences. Both tools are being actively expanded with new samples and functionality. +You can create Office add-in projects in Visual Studio Code with either Agents Toolkit or Office Add-ins Development Kit extensions. The Office Add-ins Development Kit currently focuses on Excel, PowerPoint, and Word experiences. -#### Install Teams Toolkit +#### Install Agents Toolkit -Install [Visual Studio Code](https://code.visualstudio.com/) and then install the latest version of Teams Toolkit as described in [Install Teams Toolkit](/microsoftteams/platform/toolkit/install-teams-toolkit?tabs=vscode). +Install [Visual Studio Code](https://code.visualstudio.com/) and then install the latest version of Agents Toolkit as described in [Install Microsoft 365 Agents Toolkit](/microsoftteams/platform/toolkit/install-teams-toolkit?tabs=vscode). -#### Install the Office Add-ins Development Kit extension (preview) +#### Install the Office Add-ins Development Kit extension The Office Add-ins Development Kit extension for Visual Studio Code lets you create and run new add-ins directly from the IDE. For more information about the extension, see [Create Office Add-in projects using Office Add-ins Development Kit for Visual Studio Code](../develop/development-kit-overview.md). @@ -147,7 +155,7 @@ Install the latest version of Visual Studio from [Visual Studio Downloads](https ## Install Script Lab -Script Lab is a tool for quickly prototyping code that calls the Office JavaScript Library APIs. Script Lab is itself an Office Add-in and can be installed from AppSource at [Script Lab](https://appsource.microsoft.com/marketplace/apps?search=script%20lab&page=1). There's a version for Excel, PowerPoint, and Word, and a separate version for Outlook. For information about how to use Script Lab, see [Explore Office JavaScript API using Script Lab](explore-with-script-lab.md). +Script Lab is a tool for quickly prototyping code that calls the Office JavaScript Library APIs. Script Lab is itself an Office Add-in and can be installed from Microsoft Marketplace at [Script Lab](https://marketplace.microsoft.com/marketplace/apps?search=script%20lab&page=1). There's a version for Excel, PowerPoint, and Word, and a separate version for Outlook. For information about how to use Script Lab, see [Explore Office JavaScript API using Script Lab](explore-with-script-lab.md). ## Next steps @@ -155,7 +163,7 @@ Try creating your own add-in or use [Script Lab](explore-with-script-lab.md) to ### Create an Office Add-in -You can quickly create a basic add-in for Excel, OneNote, Outlook, PowerPoint, Project, or Word by completing a [5-minute quick start](../index.yml#get-started-with-office-add-ins). If you've previously completed a quick start and want to create a slightly more complex add-in, you should try a [tutorial](../index.yml#your-developer-journey). +You can quickly create a basic add-in for Excel, OneNote, Outlook, PowerPoint, Project, or Word by completing a [5-minute quick start](../index.yml). If you've previously completed a quick start and want to create a slightly more complex add-in, you should try a [tutorial](../index.yml). ### Explore the APIs with Script Lab diff --git a/docs/powerpoint/bind-shapes-in-presentation.md b/docs/powerpoint/bind-shapes-in-presentation.md new file mode 100644 index 0000000000..66b5551a64 --- /dev/null +++ b/docs/powerpoint/bind-shapes-in-presentation.md @@ -0,0 +1,160 @@ +--- +title: Bind to shapes in a PowerPoint presentation +description: Learn how to bind shapes and access them from your add-in to keep them up to date. +ms.topic: how-to +ms.date: 04/30/2025 +ms.localizationpriority: medium +--- + +# Bind to shapes in a PowerPoint presentation + +Your PowerPoint add-in can bind to shapes to consistently access them through an identifier. The add-in establishes a binding by calling [BindingCollection.add](/javascript/api/powerpoint/powerpoint.bindingcollection#powerpoint-powerpoint-bindingcollection-add-member(1)) and assigning a unique identifier. Use the identifier at any time to reference the shape and access its properties. Creating bindings provides the following value to your add-in. + +- Establishes a relationship between the add-in and the shape in the document. Bindings are persisted in the document and can be accessed at a later time. +- Enables access to shape properties to read or update, without requiring the user to select any shapes. + +The following image shows how an add-in might bind to two shapes on a slide. Each shape has a binding ID created by the add-in: `star` and `pie`. Using the binding ID, the add-in can access the desired shape to update properties. + +:::image type="content" source="../images/powerpoint-bind-shapes.png" alt-text="Binding to a star shape with the ID 'star' and binding to a pie chart with the ID 'pie'."::: + +## Scenario: Use bindings to sync with a data source + +A common scenario for using bindings is to keep shapes up to date with a data source. Often when creating a presentation, users copy and paste images from the data source into the presentation. Over time, to keep the images up to date, they will manually copy and paste the latest images from the data source. An add-in can help automate this process by retrieving up-to-date images from the data source on the user’s behalf. When a shape fill needs updating, the add-in uses the binding to find the correct shape and update the shape fill with the newer image. + +In a general implementation, there are two components to consider for binding a shape in PowerPoint and updating it with a new image from a data source. + +1. **The data source**. This is any source of data or asset library such as Microsoft SharePoint or Microsoft OneDrive. +1. **The PowerPoint add-in**. The add-in gets data from the data source based on what the user needs. It converts the data to a Base64-encoded image. This is the only fill type the bound shape can accept. It inserts a shape upon the user’s request and binds it with a unique identifier. Then it fills the shape with the Base64 image based on the original data source. Shapes are updated upon the user’s request and the add-in uses the binding identifier to find the shape and update the image with the last saved Base64 image. + +> [!NOTE] +> You decide the implementation details of how to sync updates from the data source and how to get or create images. This article only describes how to use the Office JS APIs in your add-in to bind a shape and update it with latest images. + +## Create a bound shape in PowerPoint + +Use the `PowerPoint.BindingCollection.add()` method for the presentation to create a binding which refers to a particular shape. + +:::image type="content" source="../images/powerpoint-steps-to-bind-shape.png" alt-text="Add-in creates a Base64-encoded image from data source, then creates the shape from the image and adds a unique ID."::: + +The following sample shows how to create a shape on the first selected slide. + +```javascript +await PowerPoint.run(async (context) => { + const slides = context.presentation.getSelectedSlides(); + + // Insert new shape on first selected slide. + const myShape = slides + .getItemAt(0) + .shapes.addGeometricShape(PowerPoint.GeometricShapeType.rectangle, { + top: 100, + left: 30, + width: 200, + height: 200 + }); + + // Fill shape with a Base64-encoded image. + // Note: The image is typically created from a data source request. + const productsImage = "...Base64 image data..."; + myShape.fill.setImage(productsImage); +}); +``` + +Call `BindingCollection.add` to add the binding to the bindings collection in PowerPoint. The following sample shows how to add a new binding for a shape to the bindings collection. + +```javascript +// Create a binding ID to track the shape for later updates. +const bindingId = "productChart"; +// Create binding by adding the new shape to the bindings collection. +context.presentation.bindings.add(myShape, PowerPoint.BindingType.shape, bindingId); +``` + +## Refresh a bound shape with updated data + +After there's an update to the image data, refresh the shape image by finding it via the binding identifier. The following code sample shows how to find a bound shape with the identifier and fill it with an updated image. The image is updated by the add-in based on the data source request or provided by the data source directly. + +```javascript +async function updateBinding(bindingId, image) { + await PowerPoint.run(async (context) => { + try { + // Get the shape based on binding ID. + const myShape = context.presentation.bindings + .getItem(bindingId) + .getShape(); + + // Update the shape to latest image. + myShape.fill.setImage(image); + await context.sync(); + + } catch (err) { + console.error(err); + } + }); +} +``` + +## Delete a binding + +The following sample shows how to delete a binding by deleting it from the bindings collection. + +```javascript +async function deleteBinding(bindingId) { + await PowerPoint.run(async (context) => { + context.presentation.bindings.getItemAt(bindingId).delete(); + await context.sync(); + }); +} +``` + +## Load bindings + +When a user opens a presentation and your add-in first loads, you can load all the bindings to continue working with them. The following code shows how to load all bindings in a presentation and display them in the console. + +```javascript +async function loadBindings() { + await PowerPoint.run(async (context) => { + try { + let myBindings = context.presentation.bindings; + myBindings.load("items"); + await context.sync(); + + // Log all binding IDs to console. + if (myBindings.items.length > 0) { + myBindings.items.forEach(async (binding) => { + console.log(binding.id); + }); + } + } catch (err) { + console.error(err); + } + }); +} +``` + +## Error handling when a binding or shape is deleted + +When a shape is deleted, its associated binding is also removed from the PowerPoint binding collection. Any object references you have to the binding, or shape, will return errors if you access any properties or methods on those objects. Be sure to handle potential error scenarios for a deleted shape if your add-in keeps Binding or Shape objects. + +The following code shows one approach to error handling when a binding object references a deleted binding. Use a try/catch statement and then call a function to reload all binding and shape references when an error occurs. + +```javascript +async function getShapeFromBindingID(id) { + await PowerPoint.run(async (context) => { + try { + const binding = context.presentation.bindings.getItemAt(id); + const shape = binding.getShape(); + + await context.sync(); + return shape; + } catch (err) { + console.log(err); + return undefined; + } + }); +} +``` + +## See also + +When maintaining freshness on shapes, you may also want to check the zOrder. See the [zOrderPosition](/javascript/api/powerpoint/powerpoint.shape) property for more information. + +- [Work with shapes using the PowerPoint JavaScript API](shapes.md) +- [Bind to regions in a document or spreadsheet](../develop/bind-to-regions-in-a-document-or-spreadsheet.md) diff --git a/docs/powerpoint/core-concepts.md b/docs/powerpoint/core-concepts.md new file mode 100644 index 0000000000..fefecb8c7b --- /dev/null +++ b/docs/powerpoint/core-concepts.md @@ -0,0 +1,42 @@ +--- +title: PowerPoint JavaScript object model in Office Add-ins +description: Learn about the key components in the PowerPoint-specific JavaScript object model. +ms.date: 06/18/2025 +ms.topic: concept-article +ms.localizationpriority: high +--- + +# PowerPoint JavaScript object model in Office Add-ins + +This article describes concepts that are fundamental to using the [PowerPoint JavaScript API](../reference/overview/powerpoint-add-ins-reference-overview.md) to build add-ins. + +## Office.js APIs for PowerPoint + +A PowerPoint add-in interacts with objects in PowerPoint by using the Office JavaScript API. This includes two JavaScript object models: + +- **PowerPoint JavaScript API**: The [PowerPoint JavaScript API](/javascript/api/powerpoint) provides strongly-typed objects that work with the presentation, slides, tables, shapes, formatting, and more. To learn about the asynchronous nature of the PowerPoint APIs and how they work with the presentation, see [Using the application-specific API model](../develop/application-specific-api-model.md). + +- **Common APIs**: The [Common API](/javascript/api/office) give access to features such as UI, dialogs, and client settings that are common across multiple Office applications. To learn more about using the Common API, see [Common JavaScript API object model](../develop/office-javascript-api-object-model.md). + +While you'll likely use the PowerPoint JavaScript API to develop the majority of functionality in add-ins that target PowerPoint, you'll also use objects in the Common API. For example: + +- [Office.Context](/javascript/api/office/office.context): The `Office.Context` object represents the runtime environment of the add-in and provides access to key objects of the API. It consists of presentation configuration details such as `contentLanguage` and `officeTheme` and also provides information about the add-in's runtime environment such as `host` and `platform`. Additionally, it provides the `requirements.isSetSupported()` method, which you can use to check whether a specified requirement set is supported by the PowerPoint application where the add-in is running. +- [Office.Document](/javascript/api/office/office.document): The `Office.Document` object provides the `getFileAsync()` method, which you can use to download the PowerPoint file where the add-in is running. It also provides the `getActiveViewAsync()` method, which you can use to check whether the presentation is in a "read" or "edit" view. "edit" corresponds to any of the views in which you can edit slides: Normal, Slide Sorter, or Outline View. "read" corresponds to either Slide Show or Reading View. + +## PowerPoint-specific object model + +To understand the PowerPoint APIs, you must understand how key components of a presentation are related to one another. + +- The presentation contains slides and presentation-level entities such as settings and custom XML parts. +- A slide contains content like shapes, text, and tables. +- A layout determines how a slide's content is organized and displayed. + +For the full set of objects supported by the PowerPoint JavaScript API, see [PowerPoint JavaScript API](/javascript/api/powerpoint). + +## See also + +- [PowerPoint JavaScript API overview](../reference/overview/powerpoint-add-ins-reference-overview.md) +- [Build your first PowerPoint add-in](../quickstarts/powerpoint-quickstart-yo.md) +- [PowerPoint add-in tutorial](../tutorials/powerpoint-tutorial-yo.md) +- [PowerPoint JavaScript API reference](/javascript/api/powerpoint) +- [Learn about the Microsoft 365 Developer Program](https://aka.ms/m365devprogram) diff --git a/docs/powerpoint/insert-slides-into-presentation.md b/docs/powerpoint/insert-slides-into-presentation.md index 16f86bf832..22b0dfafc4 100644 --- a/docs/powerpoint/insert-slides-into-presentation.md +++ b/docs/powerpoint/insert-slides-into-presentation.md @@ -13,12 +13,12 @@ The slide insertion APIs are primarily used in presentation template scenarios: There are two steps to inserting slides from one presentation into another. -1. Convert the source presentation file (.pptx) into a base64-formatted string. -1. Use the `insertSlidesFromBase64` method to insert one or more slides from the base64 file into the current presentation. +1. Convert the source presentation file (.pptx) into a Base64-formatted string. +1. Use the `insertSlidesFromBase64` method to insert one or more slides from the Base64 file into the current presentation. -## Convert the source presentation to base64 +## Convert the source presentation to Base64 -There are many ways to convert a file to base64. Which programming language and library you use, and whether to convert on the server-side of your add-in or the client-side is determined by your scenario. Most commonly, you'll do the conversion in JavaScript on the client-side by using a [FileReader](https://developer.mozilla.org/docs/Web/API/FileReader) object. The following example shows this practice. +There are many ways to convert a file to Base64. Which programming language and library you use, and whether to convert on the server-side of your add-in or the client-side is determined by your scenario. Most commonly, you'll do the conversion in JavaScript on the client-side by using a [FileReader](https://developer.mozilla.org/docs/Web/API/FileReader) object. The following example shows this practice. 1. Begin by getting a reference to the source PowerPoint file. In this example, we will use an `<input>` control of type `file` to prompt the user to choose a file. Add the following markup to the add-in page. @@ -46,9 +46,9 @@ There are many ways to convert a file to base64. Which programming language and 3. Add the following code. Note the following about this code. - - The `reader.readAsDataURL` method converts the file to base64 and stores it in the `reader.result` property. When the method completes, it triggers the `onload` event handler. + - The `reader.readAsDataURL` method converts the file to Base64 and stores it in the `reader.result` property. When the method completes, it triggers the `onload` event handler. - The `onload` event handler trims metadata off of the encoded file and stores the encoded string in a global variable. - - The base64-encoded string is stored globally because it will be read by another function that you create in a later step. + - The Base64-encoded string is stored globally because it will be read by another function that you create in a later step. ```javascript let chosenFileBase64; @@ -70,7 +70,7 @@ There are many ways to convert a file to base64. Which programming language and ## Insert slides with insertSlidesFromBase64 -Your add-in inserts slides from another PowerPoint presentation into the current presentation with the [Presentation.insertSlidesFromBase64](/javascript/api/powerpoint/powerpoint.presentation#powerpoint-powerpoint-presentation-insertslidesfrombase64-member(1)) method. The following is a simple example in which all of the slides from the source presentation are inserted at the beginning of the current presentation and the inserted slides keep the formatting of the source file. Note that `chosenFileBase64` is a global variable that holds a base64-encoded version of a PowerPoint presentation file. +Your add-in inserts slides from another PowerPoint presentation into the current presentation with the [Presentation.insertSlidesFromBase64](/javascript/api/powerpoint/powerpoint.presentation#powerpoint-powerpoint-presentation-insertslidesfrombase64-member(1)) method. The following is a simple example in which all of the slides from the source presentation are inserted at the beginning of the current presentation and the inserted slides keep the formatting of the source file. Note that `chosenFileBase64` is a global variable that holds a Base64-encoded version of a PowerPoint presentation file. ```javascript async function insertAllSlides() { diff --git a/docs/powerpoint/powerpoint-add-ins.md b/docs/powerpoint/powerpoint-add-ins.md index e50087fcdd..50a0af0d49 100644 --- a/docs/powerpoint/powerpoint-add-ins.md +++ b/docs/powerpoint/powerpoint-add-ins.md @@ -1,7 +1,7 @@ ---- +--- title: PowerPoint add-ins description: Learn how to use PowerPoint add-ins to build engaging solutions for presentations across platforms including Windows, iPad, Mac, and in a browser. -ms.date: 07/18/2022 +ms.date: 06/05/2025 ms.topic: overview ms.custom: scenarios:getting-started ms.localizationpriority: high @@ -11,133 +11,98 @@ ms.localizationpriority: high You can use PowerPoint add-ins to build engaging solutions for your users' presentations across platforms including Windows, iPad, Mac, and in a browser. You can create two types of PowerPoint add-ins: -- Use **content add-ins** to add dynamic HTML5 content to your presentations. For example, see the [LucidChart Diagrams for PowerPoint](https://appsource.microsoft.com/product/office/wa104380117) add-in, which you can use to inject an interactive diagram from LucidChart into your deck. +- Use **task pane add-ins** to bring in reference information or insert data into the presentation via a service. For example, see the [Pexels - Free Stock Photos](https://appsource.microsoft.com/product/office/wa104379997) add-in, which you can use to add professional photos to your presentation. To create your own task pane add-in, you can start with [Build your first PowerPoint task pane add-in](../quickstarts/powerpoint-quickstart-yo.md). -- Use **task pane add-ins** to bring in reference information or insert data into the presentation via a service. For example, see the [Pexels - Free Stock Photos](https://appsource.microsoft.com/product/office/wa104379997) add-in, which you can use to add professional photos to your presentation. +- Use **content add-ins** to add dynamic HTML5 content to your presentations. For example, see the [LucidChart Diagrams for PowerPoint](https://appsource.microsoft.com/product/office/wa104380117) add-in, which injects interactive diagrams from LucidChart into your deck. To create your own content add-in, start with [Build your first PowerPoint content add-in](../quickstarts/powerpoint-quickstart-content.md). ## PowerPoint add-in scenarios -The code examples in this article demonstrate some basic tasks for developing add-ins for PowerPoint. Please note the following: - -- To display information, these examples use the `app.showNotification` function, which is included in the Visual Studio Office Add-ins project templates. If you aren't using Visual Studio to develop your add-in, you'll need replace the `showNotification` function with your own code. - -- Several of these examples also use a `Globals` object that is declared beyond the scope of these functions as: - `var Globals = {activeViewHandler:0, firstSlideId:0};` - -- To use these examples, your add-in project must [reference Office.js v1.1 library or later](../develop/referencing-the-javascript-api-for-office-library-from-its-cdn.md). - -## Detect the presentation's active view and handle the ActiveViewChanged event - -If you are building a content add-in, you will need to get the presentation's active view and handle the `ActiveViewChanged` event, as part of your `Office.Initialize` handler. - -> [!NOTE] -> In PowerPoint on the web, the [Document.ActiveViewChanged](/javascript/api/office/office.document) event will never fire as Slide Show mode is treated as a new session. In this case, the add-in must fetch the active view on load, as shown in the following code sample. +The code examples in this article demonstrate some basic tasks that can be useful when developing add-ins for PowerPoint. -In the following code sample: +## Add a new slide then navigate to it -- The `getActiveFileView` function calls the [Document.getActiveViewAsync](/javascript/api/office/office.document#office-office-document-getactiveviewasync-member(1)) method to return whether the presentation's current view is "edit" (any of the views in which you can edit slides, such as **Normal** or **Outline View**) or "read" (**Slide Show** or **Reading View**). - -- The `registerActiveViewChanged` function calls the [addHandlerAsync](/javascript/api/office/office.document#office-office-document-addhandlerasync-member(1)) method to register a handler for the [Document.ActiveViewChanged](/javascript/api/office/office.document) event. +In the following code sample, the `addAndNavigateToNewSlide` function calls the [SlideCollection.add](/javascript/api/powerpoint/powerpoint.slidecollection#powerpoint-powerpoint-slidecollection-add-member(1)) method to add a new slide to the presentation. The function then calls the [Presentation.setSelectedSlides](/javascript/api/powerpoint/powerpoint.presentation#powerpoint-powerpoint-presentation-setselectedslides-member(1)) method to navigate to the new slide. ```js -//general Office.initialize function. Fires on load of the add-in. -Office.initialize = function(){ - - //Gets whether the current view is edit or read. - const currentView = getActiveFileView(); - - //register for the active view changed handler - registerActiveViewChanged(); - - //render the content based off of the currentView - //.... -} - -function getActiveFileView() -{ - Office.context.document.getActiveViewAsync(function (asyncResult) { - if (asyncResult.status == "failed") { - app.showNotification("Action failed with error: " + asyncResult.error.message); - } - else { - app.showNotification(asyncResult.value); - } - }); - -} - -function registerActiveViewChanged() { - Globals.activeViewHandler = function (args) { - app.showNotification(JSON.stringify(args)); - } - - Office.context.document.addHandlerAsync(Office.EventType.ActiveViewChanged, Globals.activeViewHandler, - function (asyncResult) { - if (asyncResult.status == "failed") { - app.showNotification("Action failed with error: " + asyncResult.error.message); - } - else { - app.showNotification(asyncResult.status); - } - }); +async function addAndNavigateToNewSlide() { + // Adds a new slide then navigates to it. + await PowerPoint.run(async (context) => { + const slideCountResult = context.presentation.slides.getCount(); + context.presentation.slides.add(); + await context.sync(); + + const newSlide = context.presentation.slides.getItemAt(slideCountResult.value); + newSlide.load("id"); + await context.sync(); + + console.log(`Added slide - ID: ${newSlide.id}`); + + // Navigate to the new slide. + context.presentation.setSelectedSlides([newSlide.id]); + await context.sync(); + }); } ``` ## Navigate to a particular slide in the presentation -In the following code sample, the `getSelectedRange` function calls the [Document.getSelectedDataAsync](/javascript/api/office/office.document#office-office-document-getselecteddataasync-member(1)) method to get the JSON object returned by `asyncResult.value`, which contains an array named `slides`. The `slides` array contains the ids, titles, and indexes of selected range of slides (or of the current slide, if multiple slides are not selected). It also saves the id of the first slide in the selected range to a global variable. +In the following code sample, the `getSelectedSlides` function calls the [Presentation.getSelectedSlides](/javascript/api/powerpoint/powerpoint.presentation#powerpoint-powerpoint-presentation-getselectedslides-member(1)) method to get the selected slides then logs their IDs. The function can then act on the current slide (or first slide from the selection). ```js -function getSelectedRange() { - // Get the id, title, and index of the current slide (or selected slides) and store the first slide id */ - Globals.firstSlideId = 0; +async function getSelectedSlides() { + // Gets the ID of the current slide (or selected slides). + await PowerPoint.run(async (context) => { + const selectedSlides = context.presentation.getSelectedSlides(); + selectedSlides.load("items/id"); + await context.sync(); + + if (selectedSlides.items.length === 0) { + console.warn("No slides were selected."); + return; + } - Office.context.document.getSelectedDataAsync(Office.CoercionType.SlideRange, function (asyncResult) { - if (asyncResult.status == "failed") { - app.showNotification("Action failed with error: " + asyncResult.error.message); - } - else { - Globals.firstSlideId = asyncResult.value.slides[0].id; - app.showNotification(JSON.stringify(asyncResult.value)); - } + console.log("IDs of selected slides:"); + selectedSlides.items.forEach(item => { + console.log(item.id); }); -} -``` -In the following code sample, the `goToFirstSlide` function calls the [Document.goToByIdAsync](/javascript/api/office/office.document#office-office-document-gotobyidasync-member(1)) method to navigate to the first slide that was identified by the `getSelectedRange` function shown previously. + // Navigate to first selected slide. + const currentSlide = selectedSlides.items[0]; + console.log(`Navigating to slide with ID ${currentSlide.id} ...`); + context.presentation.setSelectedSlides([currentSlide.id]); -```js -function goToFirstSlide() { - Office.context.document.goToByIdAsync(Globals.firstSlideId, Office.GoToType.Slide, function (asyncResult) { - if (asyncResult.status == "failed") { - app.showNotification("Action failed with error: " + asyncResult.error.message); - } - else { - app.showNotification("Navigation successful"); - } - }); + // Perform actions on current slide... + }); } ``` ## Navigate between slides in the presentation -In the following code sample, the `goToSlideByIndex` function calls the `Document.goToByIdAsync` method to navigate to the next slide in the presentation. +In the following code sample, the `goToSlideByIndex` function calls the `Presentation.setSelectedSlides` method to navigate to the first slide in the presentation, which has the index 0. The maximum slide index you can navigate to in this sample is `slideCountResult.value - 1`. ```js -function goToSlideByIndex() { - const goToFirst = Office.Index.First; - const goToLast = Office.Index.Last; - const goToPrevious = Office.Index.Previous; - const goToNext = Office.Index.Next; - - Office.context.document.goToByIdAsync(goToNext, Office.GoToType.Index, function (asyncResult) { - if (asyncResult.status == "failed") { - app.showNotification("Action failed with error: " + asyncResult.error.message); - } - else { - app.showNotification("Navigation successful"); - } - }); +async function goToSlideByIndex() { + await PowerPoint.run(async (context) => { + // Gets the number of slides in the presentation. + const slideCountResult = context.presentation.slides.getCount(); + await context.sync(); + + if (slideCountResult.value === 0) { + console.warn("There are no slides."); + return; + } + + const slide = context.presentation.slides.getItemAt(0); // First slide + //const slide = context.presentation.slides.getItemAt(slideCountResult.value - 1); // Last slide + slide.load("id"); + await context.sync(); + + console.log(`Slide ID: ${slide.id}`); + + // Navigate to the slide. + context.presentation.setSelectedSlides([slide.id]); + await context.sync(); + }); } ``` @@ -147,16 +112,15 @@ In the following code sample, the `getFileUrl` function calls the [Document.get ```js function getFileUrl() { - //Get the URL of the current file. - Office.context.document.getFilePropertiesAsync(function (asyncResult) { - const fileUrl = asyncResult.value.url; - if (fileUrl == "") { - app.showNotification("The file hasn't been saved yet. Save the file and try again"); - } - else { - app.showNotification(fileUrl); - } - }); + // Gets the URL of the current file. + Office.context.document.getFilePropertiesAsync(function (asyncResult) { + const fileUrl = asyncResult.value.url; + if (fileUrl === "") { + console.warn("The file hasn't been saved yet. Save the file and try again."); + } else { + console.log(`File URL: ${fileUrl}`); + } + }); } ``` @@ -168,30 +132,108 @@ Your add-in can create a new presentation, separate from the PowerPoint instance PowerPoint.createPresentation(); ``` -The `createPresentation` method can also create a copy of an existing presentation. The method accepts a base64-encoded string representation of an .pptx file as an optional parameter. The resulting presentation will be a copy of that file, assuming the string argument is a valid .pptx file. The [FileReader](https://developer.mozilla.org/docs/Web/API/FileReader) class can be used to convert a file into the required base64-encoded string, as demonstrated in the following example. +The `createPresentation` method can also create a copy of an existing presentation. The method accepts a Base64-encoded string representation of an .pptx file as an optional parameter. The resulting presentation will be a copy of that file, assuming the string argument is a valid .pptx file. The [FileReader](https://developer.mozilla.org/docs/Web/API/FileReader) class can be used to convert a file into the required Base64-encoded string, as demonstrated in the following example. ```js -const myFile = document.getElementById("file"); +const myFile = document.getElementById("file") as HTMLInputElement; const reader = new FileReader(); reader.onload = function (event) { - // strip off the metadata before the base64-encoded string + // Strip off the metadata before the Base64-encoded string. const startIndex = reader.result.toString().indexOf("base64,"); const copyBase64 = reader.result.toString().substr(startIndex + 7); PowerPoint.createPresentation(copyBase64); }; -// read in the file as a data URL so we can parse the base64-encoded string +// Read in the file as a data URL so we can parse the Base64-encoded string. reader.readAsDataURL(myFile.files[0]); ``` +To see a full code sample that includes an HTML implementation, see [Create presentation](https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/document/create-presentation.yaml). + +## Detect the presentation's active view and handle the ActiveViewChanged event + +If you're building a [content add-in](../design/content-add-ins.md), you'll need to get the presentation's active view and handle the [Document.ActiveViewChanged](/javascript/api/office/office.eventtype#fields) event as part of your [Office.onReady](/javascript/api/office#office-office-onready-function(1)) call. + +> [!NOTE] +> In PowerPoint on the web, the `Document.ActiveViewChanged` event will never fire because **Slide Show** mode is treated as a new session. In this case, the add-in must fetch the active view on load, as shown in the following code sample. + +Note the following about the code sample: + +- The `getActiveFileView` function calls the [Document.getActiveViewAsync](/javascript/api/office/office.document#office-office-document-getactiveviewasync-member(1)) method to return whether the presentation's current view is "edit" (any of the view where you can edit slides, such as **Normal**, **Slide Sorter**, or **Outline**) or "read" (**Slide Show** or **Reading View**), represented by the [ActiveView](/javascript/api/office/office.activeview) enum. +- The `registerActiveViewChanged` function calls the [Document.addHandlerAsync](/javascript/api/office/office.document#office-office-document-addhandlerasync-member(1)) method to register a handler for the `Document.ActiveViewChanged` event. +- To display information, this example uses the `showNotification` function, which is included in the Visual Studio Office Add-ins project templates. If you aren't using Visual Studio to develop your add-in, you'll need to replace the `showNotification` function with your own code. + +```js +// General Office.onReady function. Called after the add-in loads and Office JS is initialized. +Office.onReady(() => { + // Get whether the current view is edit or read. + const currentView = getActiveFileView(); + + // Register the active view changed handler. + registerActiveViewChanged(); + + // Render the content based off of the current view. + if (currentView === Office.ActiveView.Read) { + // Handle read view. + console.log('Current view is read.'); + // You can add any specific logic for the read view here. + } else { + // Handle edit view. + console.log('Current view is edit.'); + // You can add any specific logic for the edit view here. + } +}); + +// Gets the active file view. +function getActiveFileView() { + console.log('Getting active file view...'); + Office.context.document.getActiveViewAsync(function (result) { + if (result.status === Office.AsyncResultStatus.Succeeded) { + console.log('Active view:', result.value); + return result.value; + } else { + console.error('Error getting active view:', result.error.message); + showNotification('Error:', result.error.message); + return null; + } + }); +} + +// Registers the ActiveViewChanged event. +function registerActiveViewChanged() { + console.log('Registering ActiveViewChanged event handler...'); + Office.context.document.addHandlerAsync( + Office.EventType.ActiveViewChanged, + activeViewHandler, + function (result) { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error('Failed to register active view changed handler:', result.error.message); + showNotification('Error:', result.error.message); + } else { + console.log('Active view changed handler registered successfully.'); + } + }); +} + +// ActiveViewChanged event handler. +function activeViewHandler(eventArgs) { + console.log('Active view changed:', JSON.stringify(eventArgs)); + showNotification('Active view changed', `The active view has changed to: ${eventArgs.activeView}`); + // You can add logic here based on the new active view. +} +``` + ## See also - [Developing Office Add-ins](../develop/develop-overview.md) - [Learn about the Microsoft 365 Developer Program](https://aka.ms/m365devprogram) +- PowerPoint quick starts + - [Build your first PowerPoint content add-in](../quickstarts/powerpoint-quickstart-content.md) + - [Build your first PowerPoint task pane add-in](../quickstarts/powerpoint-quickstart-yo.md) - [PowerPoint Code Samples](https://developer.microsoft.com/microsoft-365/gallery/?filterBy=Samples,PowerPoint) - [How to save add-in state and settings per document for content and task pane add-ins](../develop/persisting-add-in-state-and-settings.md#how-to-save-add-in-state-and-settings-per-document-for-content-and-task-pane-add-ins) - [Read and write data to the active selection in a document or spreadsheet](../develop/read-and-write-data-to-the-active-selection-in-a-document-or-spreadsheet.md) -- [Get the whole document from an add-in for PowerPoint or Word](../powerpoint/get-the-whole-document-from-an-add-in-for-powerpoint.md) +- [Get the whole document from an add-in for PowerPoint or Word](../develop/get-the-whole-document-from-an-add-in-for-powerpoint-or-word.md) - [Use document themes in your PowerPoint add-ins](use-document-themes-in-your-powerpoint-add-ins.md) diff --git a/docs/powerpoint/shapes.md b/docs/powerpoint/shapes.md index 42b9c4264a..695fc875a5 100644 --- a/docs/powerpoint/shapes.md +++ b/docs/powerpoint/shapes.md @@ -1,7 +1,7 @@ --- title: Work with shapes using the PowerPoint JavaScript API description: Learn how to add, remove, and format shapes on PowerPoint slides. -ms.date: 03/14/2023 +ms.date: 05/06/2025 ms.localizationpriority: medium --- @@ -102,6 +102,74 @@ await PowerPoint.run(async (context) => { }); ``` +## Group and ungroup shapes + +In PowerPoint, you can group several shapes and treat them like a single shape. You can subsequently ungroup grouped shapes. To learn more about grouping objects in the PowerPoint UI, see [Group or ungroup shapes, pictures, or other objects](https://support.microsoft.com/office/a7374c35-20fe-4e0a-9637-7de7d844724b). + +### Group shapes + +To group shapes with the JavaScript API, use [ShapeCollection.addGroup](/javascript/api/powerpoint/powerpoint.shapecollection#powerpoint-powerpoint-shapecollection-addgroup-member(1)). + +The following code sample shows how to group existing shapes of type [GeometricShape](/javascript/api/powerpoint/powerpoint.shapetype) found on the current slide. + +```typescript +// Groups the geometric shapes on the current slide. +await PowerPoint.run(async (context) => { + // Get the shapes on the current slide. + context.presentation.load("slides"); + const slide = context.presentation.getSelectedSlides().getItemAt(0); + slide.load("shapes/items/type,shapes/items/id"); + await context.sync(); + + const shapes = slide.shapes; + const shapesToGroup = shapes.items.filter((item) => item.type === PowerPoint.ShapeType.geometricShape); + if (shapesToGroup.length === 0) { + console.warn("No shapes on the current slide, so nothing to group."); + return; + } + + // Group the geometric shapes. + console.log(`Number of shapes to group: ${shapesToGroup.length}`); + const group = shapes.addGroup(shapesToGroup); + group.load("id"); + await context.sync(); + + console.log(`Grouped shapes. Group ID: ${group.id}`); +}); +``` + +### Ungroup shapes + +To ungroup shapes with the JavaScript API, get the [group](/javascript/api/powerpoint/powerpoint.shape#powerpoint-powerpoint-shape-group-member) property from the group's `Shape` object then call [ShapeGroup.ungroup](/javascript/api/powerpoint/powerpoint.shapegroup#powerpoint-powerpoint-shapegroup-ungroup-member(1)). + +The following code sample shows how to ungroup the first shape group found on the current slide. + +```js +// Ungroups the first shape group on the current slide. +await PowerPoint.run(async (context) => { + // Get the shapes on the current slide. + context.presentation.load("slides"); + const slide = context.presentation.getSelectedSlides().getItemAt(0); + slide.load("shapes/items/type,shapes/items/id"); + await context.sync(); + + const shapes = slide.shapes; + const shapeGroups = shapes.items.filter((item) => item.type === PowerPoint.ShapeType.group); + if (shapeGroups.length === 0) { + console.warn("No shape groups on the current slide, so nothing to ungroup."); + return; + } + + // Ungroup the first grouped shapes. + const firstGroupId = shapeGroups[0].id; + const shapeGroupToUngroup = shapes.getItem(firstGroupId); + shapeGroupToUngroup.group.ungroup(); + await context.sync(); + + console.log(`Ungrouped shapes with group ID: ${firstGroupId}`); +}); +``` + ## Delete shapes Shapes are removed from the slide with the `Shape` object's `delete` method. @@ -123,3 +191,9 @@ await PowerPoint.run(async (context) => { await context.sync(); }); ``` + +## See also + +- [Work with tables using the PowerPoint JavaScript API](work-with-tables.md) +- [Bind to shapes in a PowerPoint presentation](bind-shapes-in-presentation.md) +- [Group or ungroup shapes, pictures, or other objects](https://support.microsoft.com/office/a7374c35-20fe-4e0a-9637-7de7d844724b) diff --git a/docs/powerpoint/work-with-tables.md b/docs/powerpoint/work-with-tables.md new file mode 100644 index 0000000000..fcde64bb4f --- /dev/null +++ b/docs/powerpoint/work-with-tables.md @@ -0,0 +1,432 @@ +--- +title: Work with tables using the PowerPoint JavaScript API +description: Learn how to create tables and control formatting using the PowerPoint JavaScript API. +ms.topic: how-to +ms.date: 05/02/2025 +ms.localizationpriority: medium +--- + +# Work with tables using the PowerPoint JavaScript API + +This article provides code samples that show how to create tables and control formatting by using the PowerPoint JavaScript API. + +## Create an empty table + +To create an empty table, call the [ShapeCollection.addTable()](/javascript/api/powerpoint/powerpoint.shapecollection#powerpoint-powerpoint-shapecollection-addtable-member(1)) method and specify how many rows and columns the table needs. The following code sample shows how to create a table with 3 rows and 4 columns. + +```javascript +await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table (which is a type of Shape). + const shape = shapes.addTable(3, 4); + await context.sync(); +}); +``` + +The previous sample doesn't specify any options, so the table defaults to formatting provided by PowerPoint. The following image shows an example of an empty table created with default formatting in PowerPoint. + +:::image type="content" source="../images/powerpoint-table-empty.png" alt-text="An empty PowerPoint table with blue and white cells."::: + +## Specify values + +You can populate the table with string values when you create it. To do this provide a 2-dimensional array of values in the [TableAddOptions](/javascript/api/powerpoint/powerpoint.tableaddoptions) object. The following code sample creates a table with string values from "1" to "12". Note the following: + +- An empty cell must be specified as an empty string "". If a value is undefined or missing, `addTable` throws an error. +- The outer array contains a list of rows. Each row is an inner array containing a list of string cell values. +- The function named `insertTableOnCurrentSlide` is used in other samples in this article. + +```javascript +async function run() { + const options: PowerPoint.TableAddOptions = { + values: [ + ["1", "2", "", "4"], // Cell 3 is blank. + ["5", "6", "7", "8"], + ["9", "10", "11", "12"] + ], + }; + + await insertTableOnCurrentSlide(3, 4, options); +} + +async function insertTableOnCurrentSlide(rowCount: number, columnCount: number, options: PowerPoint.TableAddOptions) { + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table (which is a type of Shape). + const shape = shapes.addTable(rowCount, columnCount, options); + await context.sync(); + }); +} +``` + +The previous sample creates a table with values as shown in the following image. + +:::image type="content" source="../images/powerpoint-table-numbers.png" alt-text="PowerPoint table with values from 1 to 12 in cells."::: + +## Specify cell formatting + +You can specify cell formatting when you create a table, including border style, fill style, font style, horizontal alignment, indent level, and vertical alignment. These formats are specified by the [TableCellProperties](/javascript/api/powerpoint/powerpoint.tablecellproperties) object. + +### Uniform cell formatting + +Uniform cell formatting applies to the entire table. For example, if you set the uniform font color to white, all table cells will use the white font. Uniform cell formatting is useful for controlling the default formatting you want on the entire table. + +Specify uniform cell formatting for the entire table using the [TableAddOptions.uniformCellProperties](/javascript/api/powerpoint/powerpoint.tableaddoptions#powerpoint-powerpoint-tableaddoptions-uniformcellproperties-member) property. The following code sample shows how to set all table cells to dark slate blue fill color and bold white font. + +```javascript +const rowCount = 3; +const columnCount = 4; +const options: PowerPoint.TableAddOptions = { + values: [ + ["1", "2", "", "4"], + ["5", "6", "7", "8"], + ["9", "10", "11", "12"] + ], + uniformCellProperties: { + fill: { color: "darkslateblue" }, + font: { bold: true, color: "white" } + } +}; +await insertTableOnCurrentSlide(rowCount, columnCount, options); +``` + +The previous sample creates a table as shown in the following image. + +:::image type="content" source="../images/powerpoint-table-uniform-cell-format.png" alt-text="A PowerPoint table using a dark slate blue fill color and bold white font."::: + +### Specific cell formatting + +Specific cell formatting applies to individual cells and overrides the uniform cell formatting, if any. Set individual cell formatting by using the [TableAddOptions.specificCellProperties](/javascript/api/powerpoint/powerpoint.tableaddoptions#powerpoint-powerpoint-tableaddoptions-specificcellproperties-member) property. The following code sample shows how to set the fill color to black for the cell at row 1, column 1. + +Note the `specificCellProperties` must be a 2D array that matches the 2D size of the table exactly. The sample first creates the entire empty 2D array of objects. Then it sets the specific cell format at row 1, column 1, after the options object is created. + +```javascript +const rowCount = 3; +const columnCount = 4; +// Compact syntax to create a 2D array filled with empty and distinct objects. +const specificCellProperties = Array(rowCount).fill("").map(_ => Array(columnCount).fill("").map(_ => ({}))); +const options: PowerPoint.TableAddOptions = { + values: [ + ["1", "2", "", "4"], + ["5", "6", "7", "8"], + ["9", "10", "11", "12"] + ], + uniformCellProperties: { + fill: { color: "darkslateblue" }, + font: { bold: true, color: "white" } + }, + specificCellProperties // Array values are empty objects at this point. +}; +// Set fill color for specific cell at row 1, column 1. +options.specificCellProperties[1][1] = { + fill: { color: "black" } +}; +await insertTableOnCurrentSlide(rowCount, columnCount, options); + +``` + +The previous sample creates a table with a specific format applied to the cell in row 1, column 1 as shown in the following image. + +:::image type="content" source="../images/powerpoint-table-specific-cell-format.png" alt-text="A PowerPoint table with the cell in row 1 column 1 formatted with a black background."::: + +The previous sample uses the [font](/javascript/api/powerpoint/powerpoint.tablecellproperties#powerpoint-powerpoint-tablecellproperties-font-member) property which is of type [FontProperties](/javascript/api/powerpoint/powerpoint.fontproperties). The `font` property allows you to specify many properties, such as bold, italic, name, color, and more. The following code sample shows how to specify multiple properties for a font for a cell. + +```javascript +options.specificCellProperties[1][1] = { + font: { + color: "orange", + name: "Arial", + size: 50, + allCaps: true, + italic: true + } +}; +``` + +You can also specify a [fill](/javascript/api/powerpoint/powerpoint.tablecellproperties#powerpoint-powerpoint-tablecellproperties-fill-member) property which is of type [FillProperties](/javascript/api/powerpoint/powerpoint.fillproperties). The `fill` property can specify a color and the transparency percentage. The following code sample shows how to create a fill for all table cells using the color "dark red" and a 50% transparency. + +```javascript +uniformCellProperties: { + fill: { + color: "darkred", + transparency: 0.5 + } +} +``` + +## Borders + +Use the [TableCellProperties.borders](/javascript/api/powerpoint/powerpoint.tablecellproperties#powerpoint-powerpoint-tablecellproperties-borders-member) object to define borders for cells in the table. The following code sample shows how to set the borders of a cell in row 1 by column 1 to a red border with weight 3. + +```javascript +const columnCount = 3; +const rowCount = 3; +// Compact syntax to create a 2D array filled with empty and distinct objects. +const specificCellProperties = Array(rowCount).fill(undefined).map(_ => Array(columnCount).fill(undefined).map(_ => ({}))); +const options: PowerPoint.TableAddOptions = { + values: [ + ["1", "2", "3"], + ["4", "5", "6"], + ["7", "8", "9"] + ], + uniformCellProperties: { + fill: { + color: "lightcyan", + transparency: 0.5 + }, + }, + specificCellProperties +}; +options.specificCellProperties[1][1] = { + font: { + color: "red", + name: "Arial", + size: 50, + allCaps: true, + italic: true + }, + borders: { + bottom: { + color: "red", + weight: 3 + }, + left: { + color: "red", + weight: 3 + }, + right: { + color: "red", + weight: 3 + }, + top: { + color: "red", + weight: 3 + } + } +}; +await insertTableOnCurrentSlide(rowCount, columnCount, options); +``` + +## Horizontal and vertical alignment + +Use the [TableCellProperties.horizontalAlignment](/javascript/api/powerpoint/powerpoint.tablecellproperties#powerpoint-powerpoint-tablecellproperties-horizontalalignment-member) property to control text alignment in a cell. The following example shows how to set horizontal alignment to left, right, and center for three cells in a table. For a list of all alignment options, see the [ParagraphHorizontalAlignment](/javascript/api/powerpoint/powerpoint.paragraphhorizontalalignment) enum. + +```javascript +const rowCount = 3; +const columnCount = 3; +// Compact syntax to create a 2D array filled with empty and distinct objects. +const specificCellProperties = Array(rowCount).fill("").map(_ => Array(columnCount).fill("").map(_ => ({}))); +const options: PowerPoint.TableAddOptions = { + values: [ + ["Left aligned, top", "\n\n", ""], + ["Centered", "\n\n", ""], + ["Right aligned, bottom", "\n\n", ""] + ], + uniformCellProperties: { + fill: { color: "lightblue" }, + borders: { + bottom: { + color: "black", + weight: 3 + }, + left: { + color: "black", + weight: 3 + }, + right: { + color: "black", + weight: 3 + }, + top: { + color: "black", + weight: 3 + } + } + }, + specificCellProperties // Array values are empty objects at this point. +}; +options.specificCellProperties[0][0] = { + horizontalAlignment: PowerPoint.ParagraphHorizontalAlignment.left, + verticalAlignment: PowerPoint.TextVerticalAlignment.top +}; +options.specificCellProperties[1][0] = { + horizontalAlignment: PowerPoint.ParagraphHorizontalAlignment.center, + verticalAlignment: PowerPoint.TextVerticalAlignment.middle +}; +options.specificCellProperties[2][0] = { + horizontalAlignment: PowerPoint.ParagraphHorizontalAlignment.right, + verticalAlignment: PowerPoint.TextVerticalAlignment.bottom +}; +await insertTableOnCurrentSlide(3, 3, options); +``` + +The previous sample creates a table with left/top, centered, and right/bottom text alignment as shown in the following image. + +:::image type="content" source="../images/powerpoint-table-alignment-settings.png" alt-text="A PowerPoint table with three cells containing left, top aligned text, centered text, and right, bottom aligned text."::: + +## Specify row and column widths + +Specify row and column widths using the [TableAddOptions.rows](/javascript/api/powerpoint/powerpoint.tableaddoptions#powerpoint-powerpoint-tableaddoptions-rows-member) and [TableAddOptions.columns](/javascript/api/powerpoint/powerpoint.tableaddoptions#powerpoint-powerpoint-tableaddoptions-columns-member) properties. The `rows` property is an array of [TableRowProperties](/javascript/api/powerpoint/powerpoint.tablerowproperties) that you use to set each row's [rowHeight](/javascript/api/powerpoint/powerpoint.tablerowproperties#powerpoint-powerpoint-tablerowproperties-rowheight-member) property. Similarly, the `columns` property is an array of [TableColumnProperties](/javascript/api/powerpoint/powerpoint.tablecolumnproperties) you use to set each column's [columnWidth](/javascript/api/powerpoint/powerpoint.tablecolumnproperties#powerpoint-powerpoint-tablecolumnproperties-columnwidth-member) property. The width or height is set in points. + +The height or width that you set may not be honored by PowerPoint if it needs to fit the text. For example, if the text is too wide for a column, PowerPoint will increase the row height so that it can wrap the text to the next line. Similarly, the column width will increase if the specified size is smaller than a single character in the specified font size. + +The following code example shows how to set row height and column width for a new table. Note that the rows and columns properties must be set to an array of objects equal to their count. + +```javascript +const columnCount = 3; +const rowCount = 3; +const options: PowerPoint.TableAddOptions = { + values: [ + ["Width 72pt", "Width 244pt", "Width 100pt"], + ["", "", ""], + ["", "^\n\nHeight 200 pt\n\nv", ""] + ], + // Initialize columns with an array of empty objects for each column. + columns: Array(columnCount).fill("").map(_ => ({})), + rows: Array(columnCount).fill("").map(_ => ({})), + uniformCellProperties: { + fill: { color: "lightcyan" }, + horizontalAlignment: PowerPoint.ParagraphHorizontalAlignment.center, + verticalAlignment: PowerPoint.TextVerticalAlignment.middle, + borders: { + bottom: { + color: "black", + weight: 3 + }, + left: { + color: "black", + weight: 3 + }, + right: { + color: "black", + weight: 3 + }, + top: { + color: "black", + weight: 3 + } + } + } +}; +options.columns[0].columnWidth = 72; +options.columns[1].columnWidth = 244; +options.columns[2].columnWidth = 100; +options.rows[2].rowHeight = 200; +await insertTableOnCurrentSlide(rowCount, columnCount, options); +``` + +The previous sample creates a table with three custom column widths, and one custom row height, as shown in the following image. + +:::image type="content" source="../images/powerpoint-table-height-width-settings.png" alt-text="A PowerPoint table with different width columns and different height rows."::: + +## Specify merged areas + +A merged area is two or more cells combined so that they share a single value and format. In appearance the merged area spans multiple rows or columns. A merged area is indexed by its upper left table cell location (row, column) when setting its value or format. The upper left cell of the merged area is always used to set the value and formatting. All other cells in the merged area must be empty strings with no formatting applied. + +To specify a merged area, provide the upper left location where the area starts (row, column) and the length of the area in rows and columns. The following diagram shows an example of these values for a merged area that is 3 rows by 2 columns in size. Note that merged areas can't overlap with each other. + +Use the [TableAddOptions.mergedAreas](/javascript/api/powerpoint/powerpoint.tableaddoptions#powerpoint-powerpoint-tableaddoptions-mergedareas-member) property to specify one or more merged areas. The following code sample shows how to create a table with two merged areas. About the code sample, note the following: + +- The values property must only specify the value for the upper left corner of the merged area. All other cell values in the merged area must specify empty strings (""). + +- Each merged area must specify the upper left corner location (row, column) and the length in cells of the merged area in terms of row count and column count. + +```javascript +const rowCount = 3; +const columnCount = 4; +// Compact syntax to create a 2D array filled with empty and distinct objects. +const specificCellProperties = Array(rowCount).fill("").map(_ => Array(columnCount).fill("").map(_ => ({}))); +const options: PowerPoint.TableAddOptions = { + values: [ + ["1", "This is a merged cell", "", "4"], + ["5", "6", "This is also a merged cell", "8"], + ["9", "10", "", "12"] + ], + uniformCellProperties: { + fill: { color: "darkslateblue" }, + font: { bold: true, color: "white" }, + borders: { + bottom: { + color: "black", + weight: 3 + }, + left: { + color: "black", + weight: 3 + }, + right: { + color: "black", + weight: 3 + }, + top: { + color: "black", + weight: 3 + } + } + }, + mergedAreas: [{ rowIndex: 0, columnIndex: 1, rowCount: 1, columnCount: 2 }, + { rowIndex: 1, columnIndex: 2, rowCount: 2, columnCount: 1 } + ], + specificCellProperties // Array values are empty objects at this point. +}; +// Set fill color for specific cell at row 1, column 1. +options.specificCellProperties[1][1] = { + fill: { color: "black" } +}; +await insertTableOnCurrentSlide(rowCount, columnCount, options); +``` + +The previous sample creates a table with two merged areas as shown in the following image. + +:::image type="content" source="../images/powerpoint-table-merged-cells.png" alt-text="A PowerPoint table showing merged cells."::: + +## Get and set table cell values + +After a table is created, you can get or set string values in the cells. Note that this is the only part of a table you can change. You can't change borders, fonts, widths, or other cell properties. If you need to update a table, delete it and recreate it. The following code sample shows how to find an existing table and set a new value for a cell in the table. + +```javascript +await PowerPoint.run(async (context) => { + // Load shapes. + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + shapes.load("items"); + await context.sync(); + // Find the first shape of type table. + const shape = shapes.items.find((shape) => shape.type === PowerPoint.ShapeType.table) + const table = shape.getTable(); + table.load(); + await context.sync(); + // Set the value of the specified table cell. + const cell = table.getCellOrNullObject(1, 1); + cell.text = "A new value"; +}); +``` + +You can also get the following read-only properties from the table. + +- **rowCount** +- **columnCount** + +The following sample shows how to get the table properties and log them to the console. The sample also shows how to get the merged areas in the table. + +```javascript +await PowerPoint.run(async (context) => { + // Load shapes. + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + shapes.load("items"); + await context.sync(); + // Find the first shape of type table. + const shape = shapes.items.find((shape) => shape.type === PowerPoint.ShapeType.table) + const table = shape.getTable(); + // Load row and column counts. + table.load("rowCount, columnCount"); + // Load the merged areas. + const mergedAreas = table.getMergedAreas(); + mergedAreas.load("items"); + await context.sync(); + // Log the table properties. + console.log(mergedAreas); + console.log(table.rowCount); + console.log(table.columnCount); +}); +``` diff --git a/docs/project/create-a-project-add-in-that-uses-rest-with-an-on-premises-odata-service.md b/docs/project/create-a-project-add-in-that-uses-rest-with-an-on-premises-odata-service.md index c0c7444c5f..66b19d9870 100644 --- a/docs/project/create-a-project-add-in-that-uses-rest-with-an-on-premises-odata-service.md +++ b/docs/project/create-a-project-add-in-that-uses-rest-with-an-on-premises-odata-service.md @@ -1,7 +1,7 @@ ---- +--- title: Create a Project add-in that uses REST with an on-premises Project Server OData service description: Learn how to build a task pane add-in for Project Professional that compares cost and work data in the active project with the averages for all projects in the current Project Web App instance. -ms.date: 02/21/2024 +ms.date: 07/16/2025 ms.localizationpriority: medium --- @@ -13,16 +13,16 @@ The code in this article is based on a sample developed by Saurabh Sanghvi and A ## Prerequisites -The following are the prerequisites for creating a Project task pane add-in that reads the **ProjectData** service of a Project Web App instance in an on-premises installation of Project Server. +The following are prerequisites for creating a Project task pane add-in that reads the **ProjectData** service of a Project Web App instance in an on-premises installation of Project Server. -- Project Professional is required to connect with Project Web App. The development computer must have Project Professional installed to enable **F5** debugging with Visual Studio. +- Project Professional is required to connect with Project Web App. The development computer must have Project Professional installed to enable <kbd>F5</kbd> debugging with Visual Studio. > [!NOTE] - > Project Standard can also host task pane add-ins, but cannot sign in to Project Web App. + > Project Standard can also host task pane add-ins, but can't sign in to Project Web App. -- Visual Studio 2015 with Office Developer Tools for Visual Studio includes templates for creating Office and SharePoint Add-ins. Ensure that you have installed the most recent version of Office Developer Tools; see the *Tools* section of the [Office Add-ins and SharePoint downloads](https://developer.microsoft.com/office/docs). +- Visual Studio 2015 with Office Developer Tools for Visual Studio includes templates for creating Office and SharePoint Add-ins. Make sure you've installed the most recent version of Office Developer Tools; see the *Tools* section of the [Office Add-ins and SharePoint downloads](https://developer.microsoft.com/office/docs). -- The procedures and code examples in this article access the **ProjectData** service of Project Server in a local domain. The jQuery methods in this article do not work with Project on the web. +- The procedures and code examples in this article access the **ProjectData** service of Project Server in a local domain. The jQuery methods in this article don't work with Project on the web. Verify that the **ProjectData** service is accessible from your development computer. @@ -30,7 +30,7 @@ The following are the prerequisites for creating a Project task pane add-in that 1. To enable your browser to directly show the XML data from a REST query, turn off the feed reading view. For information about how to do this in Internet Explorer, see Procedure 1, step 4 in [Query OData feeds for Project reporting data](/previous-versions/office/project-odata/jj163048(v=office.15)). -1. Query the **ProjectData** service by using your browser with the following URL: **http://ServerName /ProjectServerName /_api/ProjectData**. For example, if the Project Web App instance is `http://MyServer/pwa`, the browser shows the following results. +1. Query the **ProjectData** service by using your browser with the following URL: `http://ServerName /ProjectServerName /_api/ProjectData`. For example, if the Project Web App instance is `http://MyServer/pwa`, the browser shows the following results. ```xml <?xml version="1.0" encoding="utf-8"?> @@ -50,7 +50,7 @@ The following are the prerequisites for creating a Project task pane add-in that </service> ``` -1. You may have to provide your network credentials to see the results. If the browser shows "Error 403, Access Denied," either you do not have logon permission for that Project Web App instance, or there is a network problem that requires administrative help. +1. You may need to provide your network credentials to see the results. If the browser shows "Error 403, Access Denied," either you don't have logon permission for that Project Web App instance, or there's a network problem that requires administrative help. ## Use Visual Studio to create a task pane add-in for Project @@ -68,7 +68,7 @@ Office Developer Tools for Visual Studio includes a template for task pane add-i 1. To place both of the Visual Studio projects in the same directory, select **Create directory for solution**, and then browse to the location you want. -1. In the **Name** field, typeHelloProjectOData, and then choose **OK**. +1. In the **Name** field, type HelloProjectOData, and then choose **OK**. *Figure 1. Create an Office Add-in* @@ -88,7 +88,7 @@ Office Developer Tools for Visual Studio includes a template for task pane add-i Visual Studio creates the **HelloProjectOdata** project and the **HelloProjectODataWeb** project. -The **AddIn** folder (see the next screenshot) contains the App.css file for custom CSS styles. In the **Home** subfolder , the Home.html file contains references to the CSS files and the JavaScript files that the add-in uses, and the HTML5 content for the add-in. Also, the Home.js file is for your custom JavaScript code. The **Scripts** folder includes the jQuery library files. The **Office** subfolder includes the JavaScript libraries such as office.js and project-15.js, plus the language libraries for standard strings in the Office Add-ins. In the **Content** folder, the Office.css file contains the default styles for all of the Office Add-ins. +The **AddIn** folder (see the next screenshot) contains the App.css file for custom CSS styles. In the **Home** subfolder, the Home.html file contains references to the CSS files and the JavaScript files that the add-in uses, and the HTML5 content for the add-in. Also, the Home.js file is for your custom JavaScript code. The **Scripts** folder includes the jQuery library files. The **Office** subfolder includes the JavaScript libraries such as office.js and project-15.js, plus the language libraries for standard strings in the Office Add-ins. In the **Content** folder, the Office.css file contains the default styles for all Office Add-ins. *Figure 4. View the default web project files in Solution Explorer* @@ -102,7 +102,7 @@ For more information about the manifest, see [Office Add-ins manifest](../develo 1. In Visual Studio, open the HelloProjectOData.xml file. -1. The default display name is the name of the Visual Studio project ("HelloProjectOData"). For example, change the default value of the **\<DisplayName\>** element to"Hello ProjectData". +1. The default display name is the name of the Visual Studio project ("HelloProjectOData"). For example, change the default value of the `<DisplayName>` element to"Hello ProjectData". 1. The default description is also "HelloProjectOData". For example, change the default value of the Description element to "Test REST queries of the ProjectData service". @@ -112,11 +112,11 @@ The following steps show how to add an icon file to the Visual Studio solution. 1. In **Solution Explorer**, go to the folder named Images. -1. To be displayed in the **Office Add-ins** drop-down list, the icon must be 32 x 32 pixels. Use your own 32 x 32 icon; or, copy the following image to a file named **NewIcon.png**, and then add that file to the `HelloProjectODataWeb\Images` folder. +1. To be displayed in the **Office Add-ins** drop-down list, the icon must be 32 x 32 pixels. Use your own 32 x 32 icon; or, copy the following image to a file named **NewIcon.png**, and then add that file to the `HelloProjectODataWeb\Images` folder. ![Icon for the HelloProjectOData app.](../images/pj15-hello-project-data-new-icon.jpg) -1. In the HelloProjectOData.xml, add an **\<IconUrl\>** element below the **\<Description\>** element, where the value of the icon URL is the relative path to the 32x32 icon file. For example, add the following line: `<IconUrl DefaultValue="~remoteAppUrl/Images/NewIcon.png" />`. The HelloProjectOData.xml file now contains the following (your **\<Id\>** value will be different): +1. In the HelloProjectOData.xml, add an `<IconUrl>` element below the `<Description>` element, where the value of the icon URL is the relative path to the 32x32 icon file. For example, add the following line: `<IconUrl DefaultValue="~remoteAppUrl/Images/NewIcon.png" />`. The HelloProjectOData.xml file now contains the following (your `<Id>` value will be different): ```XML <?xml version="1.0" encoding="UTF-8"?> @@ -143,17 +143,17 @@ The following steps show how to add an icon file to the Visual Studio solution. ## Create the HTML content for the HelloProjectOData add-in -The **HelloProjectOData** add-in is a sample that includes debugging and error output; it is not intended for production use. Before you start coding the HTML content, design the UI and user experience for the add-in, and outline the JavaScript functions that interact with the HTML code. For more information, see [Design guidelines for Office Add-ins](../design/add-in-design.md). +The **HelloProjectOData** add-in is a sample that includes debugging and error output; it isn't intended for production use. Before you start coding the HTML content, design the UI and user experience for the add-in, and outline the JavaScript functions that interact with the HTML code. For more information, see [Design guidelines for Office Add-ins](../design/add-in-design.md). -The task pane shows the add-in display name at the top, which is the value of the **\<DisplayName\>** element in the manifest. The **body** element in the HelloProjectOData.html file contains the other UI elements, as follows: +The task pane shows the add-in display name at the top, which is the value of the `<DisplayName>` element in the manifest. The **body** element in the HelloProjectOData.html file contains the other UI elements, as follows: - A subtitle indicates the general functionality or type of operation, for example, **ODATA REST QUERY**. -- The **Get ProjectData Endpoint** button calls the `setOdataUrl` function to get the endpoint of the **ProjectData** service, and display it in a text box. If Project is not connected with Project Web App, the add-in calls an error handler to display a pop-up error message. +- The **Get ProjectData Endpoint** button calls the `setOdataUrl` function to get the endpoint of the **ProjectData** service and display it in a text box. If Project isn't connected with Project Web App, the add-in calls an error handler to display a pop-up error message. - The **Compare All Projects** button is disabled until the add-in gets a valid OData endpoint. When you select the button, it calls the `retrieveOData` function, which uses a REST query to get project cost and work data from the **ProjectData** service. -- A table displays the average values for project cost, actual cost, work, and percent complete. The table also compares the current active project values with the average. If the current value is greater than the average for all projects, the value is displayed as red. If the current value is less than the average, the value is displayed as green. If the current value is not available, the table displays a blue **NA**. +- A table displays the average values for project cost, actual cost, work, and percent complete. The table also compares the current active project values with the average. If the current value is greater than the average for all projects, the value is displayed as red. If the current value is less than the average, the value is displayed as green. If the current value isn't available, the table displays a blue **NA**. The `retrieveOData` function calls the `parseODataResult` function, which calculates and displays values for the table. @@ -169,7 +169,7 @@ The task pane shows the add-in display name at the top, which is the value of th > [!NOTE] > Before you deploy the add-in, change the office.js reference and the jQuery reference to the content delivery network (CDN) reference. The CDN reference provides the most recent version and better performance. - The **HelloProjectOData** add-in also uses a **SurfaceErrors.js** file, which displays errors in a pop-up message. Copy the code from the [SurfaceErrors.js file section](#surfaceerrorsjs-file) of this article into the **Scripts\Office** folder of the **HelloProjectODataWeb** project as a new file named **SurfaceErrors.js**. + The **HelloProjectOData** add-in also uses a **SurfaceErrors.js** file, which displays errors in a pop-up message. Copy the code from the [SurfaceErrors.js file section](#surfaceerrorsjs-file) of this article to the **Scripts\Office** folder of the **HelloProjectODataWeb** project as a new file named **SurfaceErrors.js**. Following is the updated HTML code for the **head** element, with the additional line for the **SurfaceErrors.js** file. @@ -207,7 +207,7 @@ The task pane shows the add-in display name at the top, which is the value of th </html> ``` -1. In the **body** element, delete the existing code from the template, and then add the code for the user interface. If an element is to be filled with data or manipulated by a jQuery statement, the element must include a unique **id** attribute. In the following code, the **id** attributes for the **button**, **span**, and **td** (table cell definition) elements that jQuery functions use are shown in bold font. +1. In the **body** element, delete the existing code from the template and add the code for the user interface. If an element is to be filled with data or manipulated by a jQuery statement, the element must include a unique **id** attribute. In the following code, the **id** attributes for the **button**, **span**, and **td** (table cell definition) elements that jQuery functions use are shown in bold font. The following HTML adds a graphic image (**NewLogo.png**), which could be a company logo. @@ -267,7 +267,7 @@ The task pane shows the add-in display name at the top, which is the value of th ## Create the JavaScript code for the add-in -The template for a Project task pane add-in includes default initialization code that's designed to demonstrate basic get and set actions for data in a document for an Office add-in that uses the [Common APIs](../develop/office-javascript-api-object-model.md). Because Project doesn't support actions that write to the active project, and the **HelloProjectOData** add-in doesn't use the `getSelectedDataAsync` method, you can delete the script within the `Office.initialize` function, and delete the `setData` function and `getData` function in the default HelloProjectOData.js file. +The template for a Project task pane add-in includes default initialization code that's designed to demonstrate basic get and set actions for data in a document for an Office add-in that uses the [Common APIs](../develop/office-javascript-api-object-model.md). Because Project doesn't support actions that write to the active project, and the **HelloProjectOData** add-in doesn't use the `getSelectedDataAsync` method, you can delete the script within the `Office.initialize` function and delete the `setData` function and `getData` function in the default HelloProjectOData.js file. The JavaScript includes global constants for the REST query and global variables that are used in several functions. The **Get ProjectData Endpoint** button calls the `setOdataUrl` function, which initializes the global variables and determines whether Project is connected with Project Web App. @@ -275,7 +275,7 @@ The remainder of the HelloProjectOData.js file includes two functions: the `retr ### Procedure 5. Create the JavaScript code -1. Delete all code in the default HelloProjectOData.js file, and then add the global variables and `Office.initialize` function. Variable names that are all capitals imply that they are constants; they are later used with the `_pwa` variable to create the REST query in this example. +1. Delete all code in the default HelloProjectOData.js file and add the global variables and `Office.initialize` function. Variable names that are all capitals imply that they are constants; they're later used with the `_pwa` variable to create the REST query in this example. ```js let PROJDATA = "/_api/ProjectData"; @@ -297,10 +297,10 @@ The remainder of the HelloProjectOData.js file includes two functions: the `retr }); ``` -1. Add `setOdataUrl` and related functions. The `setOdataUrl` function calls `getProjectGuid` and `getDocumentUrl` to initialize the global variables. In the [getProjectFieldAsync method](/javascript/api/office/office.document), the anonymous function for the *callback* parameter enables the **Compare All Projects** button by using the `removeAttr` method in the jQuery library, and then displays the URL of the **ProjectData** service. If Project is not connected with Project Web App, the function throws an error, which displays a pop-up error message. The SurfaceErrors.js file includes the `throwError` function. +1. Add `setOdataUrl` and related functions. The `setOdataUrl` function calls `getProjectGuid` and `getDocumentUrl` to initialize the global variables. In the [getProjectFieldAsync method](/javascript/api/office/office.document), the anonymous function for the *callback* parameter enables the **Compare All Projects** button by using the `removeAttr` method in the jQuery library, and then displays the URL of the **ProjectData** service. If Project isn't connected with Project Web App, the function throws an error, which displays a pop-up error message. The SurfaceErrors.js file includes the `throwError` function. > [!NOTE] - > If you run Visual Studio on the Project Server computer, to use **F5** debugging, uncomment the code after the line that initializes the `_pwa` global variable. To enable using the jQuery `ajax` method when debugging on the Project Server computer, you must set the `localhost` value for the PWA URL.If you run Visual Studio on a remote computer, the `localhost` URL is not required. Before you deploy the add-in, comment out that code. + > If you run Visual Studio on the Project Server computer, to use **F5** debugging, uncomment the code after the line that initializes the `_pwa` global variable. To enable using the jQuery `ajax` method when debugging on the Project Server computer, you must set the `localhost` value for the PWA URL.If you run Visual Studio on a remote computer, the `localhost` URL isn't required. Before you deploy the add-in, comment out that code. ```js function setOdataUrl() { @@ -363,7 +363,7 @@ The remainder of the HelloProjectOData.js file includes two functions: the `retr > [!NOTE] > The following code works with an on-premises installation of Project Server. For Project on the web, you can use OAuth for token-based authentication. For more information, see [Addressing same-origin policy limitations in Office Add-ins](../develop/addressing-same-origin-policy-limitations.md). - In the `ajax` call, you can use either the *headers* parameter or the *beforeSend* parameter. The *complete* parameter is an anonymous function so that it is in the same scope as the variables in `retrieveOData`. The function for the *complete* parameter displays results in the `odataText` control and also calls the `parseODataResult` method to parse and display the JSON response. The *error* parameter specifies the named `getProjectDataErrorHandler` function, which writes an error message to the `odataText` control and also uses the `throwError` function to display a pop-up message. + In the `ajax` call, you can use either the *headers* parameter or the *beforeSend* parameter. The *complete* parameter is an anonymous function so that it's in the same scope as the variables in `retrieveOData`. The function for the *complete* parameter displays results in the `odataText` control and also calls the `parseODataResult` method to parse and display the JSON response. The *error* parameter specifies the named `getProjectDataErrorHandler` function, which writes an error message to the `odataText` control and also uses the `throwError` function to display a pop-up message. ```js // Functions to get and parse the Project Server reporting data./ @@ -376,7 +376,7 @@ The remainder of the HelloProjectOData.js file includes two functions: the `retr accept.toLocaleLowerCase(); // Enable cross-origin scripting (required by jQuery 1.5 and later). - // This does not work with Project on the web. + // This doesn't work with Project on the web. $.support.cors = true; $.ajax({ @@ -421,7 +421,7 @@ The remainder of the HelloProjectOData.js file includes two functions: the `retr 1. Add the `parseODataResult` function, which deserializes and processes the JSON response from the OData service. The `parseODataResult` function calculates average values of the cost and work data to an accuracy of one or two decimal places, formats values with the correct color and adds a unit ( **$**, **hrs**, or **%**), and then displays the values in specified table cells. - If the GUID of the active project matches the `ProjectId` value, the `myProjectIndex` variable is set to the project index. If `myProjectIndex` indicates the active project is published on Project Server, the `parseODataResult` method formats and displays cost and work data for that project. If the active project is not published, values for the active project are displayed as a blue **NA**. + If the GUID of the active project matches the `ProjectId` value, the `myProjectIndex` variable is set to the project index. If `myProjectIndex` indicates the active project is published on Project Server, the `parseODataResult` method formats and displays cost and work data for that project. If the active project isn't published, values for the active project are displayed as a blue **NA**. ```js // Calculate the average values of actual cost, cost, work, and percent complete @@ -534,7 +534,7 @@ The remainder of the HelloProjectOData.js file includes two functions: the `retr ## Test the HelloProjectOData add-in -To test and debug the **HelloProjectOData** add-in with Visual Studio, Project Professional must be installed on the development computer. To enable different test scenarios, ensure that you can choose whether Project opens for files on the local computer or connects with Project Web App. The following are example steps. +To test and debug the **HelloProjectOData** add-in with Visual Studio, Project Professional must be installed on the development computer. To enable different test scenarios, make sure you can choose whether Project opens for files on the local computer or connects with Project Web App. The following are example steps. 1. On the **File** tab, choose the **Info** tab in the Backstage view, and then choose **Manage Accounts**. @@ -544,9 +544,9 @@ To test and debug the **HelloProjectOData** add-in with Visual Studio, Project P Basic tests should include the following: -- Run the add-in from Visual Studio, and then open a published project from Project Web App that contains cost and work data. Verify that the add-in displays the **ProjectData** endpoint and correctly displays the cost and work data in the table. You can use the output in the **odataText** control to check the REST query and other information. +- Run the add-in from Visual Studio and open a published project from Project Web App that contains cost and work data. Verify that the add-in displays the **ProjectData** endpoint and correctly displays the cost and work data in the table. You can use the output in the **odataText** control to check the REST query and other information. -- Run the add-in again, where you choose the local computer profile in the **Login** dialog box when Project starts. Open a local .mpp file, and then test the add-in. Verify that the add-in displays an error message when you try to get the **ProjectData** endpoint. +- Run the add-in again, where you choose the local computer profile in the **Login** dialog box when Project starts. Open a local .mpp file and test the add-in. Verify that the add-in displays an error message when you try to get the **ProjectData** endpoint. - Run the add-in again, where you create a project that has tasks with cost and work data. You can save the project to Project Web App, but don't publish it. Verify that the add-in displays data from Project Server, but **NA** for the current project. @@ -554,7 +554,7 @@ Basic tests should include the following: 1. Run Project Professional, connect with Project Web App, and then create a test project. Assign tasks to local resources or to enterprise resources, set various values of percent complete on some tasks, and then publish the project. Quit Project, which enables Visual Studio to start Project for debugging the add-in. -1. In Visual Studio, press **F5**. Log on to Project Web App, and then open the project that you created in the previous step. You can open the project in read-only mode or in edit mode. +1. In Visual Studio, press <kbd>F5</kbd>. Log on to Project Web App, and then open the project that you created in the previous step. You can open the project in read-only mode or in edit mode. 1. On the **PROJECT** tab of the ribbon, in the **Office Add-ins** drop-down list, select **Hello ProjectData** (see Figure 5). The **Compare All Projects** button should be disabled. @@ -570,7 +570,7 @@ Basic tests should include the following: ![View results of the REST query.](../images/pj15-hello-project-data-rest-results.png) -1. Examine output in the text box. It should show the document path, REST query, status information, and JSON results from the calls to `ajax` and `parseODataResult`. The output helps to understand, create, and debug code in the `parseODataResult` function such as `projCost += Number(res.d.results[i].ProjectCost);`. +1. Examine the output in the text box. It should show the document path, REST query, status information, and JSON results from the calls to `ajax` and `parseODataResult`. The output helps you understand, create, and debug code in the `parseODataResult` function such as `projCost += Number(res.d.results[i].ProjectCost);`. Following is an example of the output with line breaks and spaces added to the text for clarity, for three projects in a Project Web App instance. @@ -620,13 +620,13 @@ Basic tests should include the following: ]}} ``` -1. Stop debugging (press **Shift + F5**), and then press **F5** again to run a new instance of Project. In the **Login** dialog box, choose the local **Computer** profile, not Project Web App. Create or open a local project .mpp file, open the **Hello ProjectData** task pane, and then select **Get ProjectData Endpoint**. The add-in should show a **No connection!** error (see Figure 7), and the **Compare All Projects** button should remain disabled. +1. Stop debugging (press <kbd>Shift</kbd>+<kbd>F5</kbd>), and then press <kbd>F5</kbd> again to run a new instance of Project. In the **Login** dialog box, choose the local **Computer** profile, not Project Web App. Create or open a local project .mpp file, open the **Hello ProjectData** task pane, and then select **Get ProjectData Endpoint**. The add-in should show a **No connection!** error (see Figure 7), and the **Compare All Projects** button should remain disabled. *Figure 7. Use the add-in without a Project web app connection* ![Use the app without a Project Web App connection.](../images/pj15-hello-project-data-no-connection.png) -1. Stop debugging, and then press **F5** again. Log on to Project Web App, and then create a project that contains cost and work data. You can save the project, but don't publish it. +1. Stop debugging and press <kbd>F5</kbd> again. Log on to Project Web App and create a project that contains cost and work data. You can save the project, but don't publish it. In the **Hello ProjectData** task pane, when you select **Compare All Projects**, you should see a blue **NA** for fields in the **Current** column (see Figure 8). @@ -634,7 +634,7 @@ Basic tests should include the following: ![Compare an unpublished project with others.](../images/pj15-hello-project-data-not-published.png) -Even if your add-in is working correctly in the previous tests, there are other tests that should be run. For example: +Even if your add-in works correctly in the previous tests, there are other tests that should be run. For example: - Open a project from Project Web App that has no cost or work data for the tasks. You should see values of zero in the fields in the **Current** column. @@ -765,7 +765,7 @@ Office.initialize = function (reason) { // Set the global variables, enable the Compare All Projects button, // and display the URL of the ProjectData service. -// Display an error if Project is not connected with Project Web App. +// Display an error if Project isn't connected with Project Web App. function setOdataUrl() { Office.context.document.getProjectFieldAsync( Office.ProjectProjectFields.ProjectServerUrl, @@ -966,7 +966,7 @@ function parseODataResult(oDataResult, currentProjectGuid) { document.getElementById("CurrentProjectPercentComplete").style.color = "green" } } - else { // The current project is not published. + else { // The current project isn't published. document.getElementById("CurrentProjectCost").innerHTML = "NA"; document.getElementById("CurrentProjectCost").style.color = "blue" @@ -1192,7 +1192,7 @@ let Toast = { ## Next steps -If **HelloProjectOData** were a production add-in to be sold in AppSource or distributed in a SharePoint app catalog, it would be designed differently. For example, there would be no debug output in a text box, and probably no button to get the **ProjectData** endpoint. You would also have to rewrite the `retrieveOData` function to handle Project Web App instances that have more than 100 projects. +If **HelloProjectOData** were a production add-in to be sold in Microsoft Marketplace or distributed in a SharePoint app catalog, it would be designed differently. For example, there would be no debug output in a text box, and probably no button to get the **ProjectData** endpoint. You'd also have to rewrite the `retrieveOData` function to handle Project Web App instances that have more than 100 projects. The add-in should contain additional error checks, plus logic to catch and explain or show edge cases. For example, if a Project Web App instance has 1000 projects with an average duration of five days and average cost of $2400, and the active project is the only one that has a duration longer than 20 days, the cost and work comparison would be skewed. That could be shown with a frequency graph. You could add options to display duration, compare similar length projects, or compare projects from the same or different departments. Or, add a way for the user to select from a list of fields to display. @@ -1206,11 +1206,11 @@ If you modify the **HelloProjectOData** add-in for production use, do the follow <script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script> ``` -- Rewrite the `retrieveOData` function to enable queries of more than 100 projects. For example, you could get the number of projects with a `~/ProjectData/Projects()/$count` query, and use the _$skip_ operator and _$top_ operator in the REST query for project data. Run multiple queries in a loop, and then average the data from each query. Each query for project data would be of the form: +- Rewrite the `retrieveOData` function to enable queries of more than 100 projects. For example, you could get the number of projects with a `~/ProjectData/Projects()/$count` query and use the *$skip* operator and *$top* operator in the REST query for project data. Run multiple queries in a loop and then average the data from each query. Each query for project data would be of the form: `~/ProjectData/Projects()?skip= [numSkipped]&$top=100&$filter=[filter]&$select=[field1,field2, ???????]` - For more information, see [OData system query options using the REST endpoint](/previous-versions/dynamicscrm-2015/developers-guide/gg309461(v=crm.7)). You can also use the [Set-SPProjectOdataConfiguration](/powershell/module/sharepoint-server/Set-SPProjectOdataConfiguration?view=sharepoint-ps&preserve-view=true) command in Windows PowerShell to override the default page size for a query of the **Projects** entity set (or any of the 33 entity sets). See [ProjectData - Project OData service reference](/previous-versions/office/project-odata/jj163015(v=office.15)). + For more information, see [OData system query options using the REST endpoint](/previous-versions/dynamicscrm-2015/developers-guide/gg309461(v=crm.7)). You can also use the [Set-SPProjectOdataConfiguration](/powershell/module/microsoft.sharepoint.powershell/set-spprojectodataconfiguration) command in Windows PowerShell to override the default page size for a query of the **Projects** entity set (or any of the 33 entity sets). See [ProjectData - Project OData service reference](/previous-versions/office/project-odata/jj163015(v=office.15)). - To deploy the add-in, see [Publish your Office Add-in](../publish/publish.md). diff --git a/docs/project/index.yml b/docs/project/index.yml index 45267aca86..b372f6d122 100644 --- a/docs/project/index.yml +++ b/docs/project/index.yml @@ -8,7 +8,7 @@ metadata: description: Resources for learning about Project add-ins. # Required; article description that is displayed in search results. < 160 chars. ms.service: project #Required ms.topic: landing-page # Required - ms.date: 01/24/2024 #Required; mm/dd/yyyy format. + ms.date: 10/05/2024 #Required; mm/dd/yyyy format. ms.localizationpriority: medium # linkListType: architecture | concept | deploy | download | get-started | how-to-guide | learn | overview | quickstart | reference | sample | tutorial | video | whats-new @@ -58,8 +58,14 @@ landingContent: - text: Ask questions url: https://stackoverflow.com/questions/tagged/office-js - text: Request features - url: https://aka.ms/m365dev-suggestions + url: https://feedbackportal.microsoft.com/feedback/forum/40792262-301c-ec11-b6e7-0022481f8472 - text: Report issues url: https://github.com/officedev/office-js/issues + - text: Join Office Add-ins community call + url: https://learn.microsoft.com/office/dev/add-ins/overview/office-add-ins-community-call - text: Office Add-ins additional resources url: ../resources/resources-links-help.md + - text: Download samples + url: https://developer.microsoft.com/microsoft-365/gallery/?filterBy=Project,Samples + + diff --git a/docs/project/project-add-ins.md b/docs/project/project-add-ins.md index d233a5e19e..704f339b72 100644 --- a/docs/project/project-add-ins.md +++ b/docs/project/project-add-ins.md @@ -1,7 +1,7 @@ ---- +--- title: Task pane add-ins for Project description: Learn about task pane add-ins for Project. -ms.date: 02/21/2024 +ms.date: 09/16/2025 ms.topic: overview ms.custom: scenarios:getting-started ms.localizationpriority: medium @@ -9,48 +9,86 @@ ms.localizationpriority: medium # Task pane add-ins for Project -Project on Windows supports custom task pane add-ins. Use these to handle selection events in Project and integrate task, resource, view, and other cell-level data in a project with SharePoint lists, SharePoint Add-ins, Web Parts, web services, and enterprise applications. +Build custom task pane add-ins to extend Project with web integrations and streamlined workflows. Project add-ins help project managers consolidate critical information, manage resources, and collaborate with teams, all without leaving Project. For an introduction to Office Add-ins, see [Office Add-ins platform overview](../overview/office-add-ins.md). -## Add-in scenarios for Project +> [!NOTE] +> Project Professional supports task pane add-ins that can access Project on the web, on-premises Project Server installations, and SharePoint (both on-premises and online). Project Standard doesn't support direct integration with Project Server data or SharePoint task lists synchronized with Project Server. -Project managers can use Project task pane add-ins to help with project management activities. Instead of leaving Project and opening another application to search for frequently used information, project managers can directly access the information within Project. The content in a task pane add-in can be context-sensitive, based on the selected task, resource, view, or other data in a cell in a Gantt chart, task usage view, or resource usage view. +## Project add-in scenarios -> [!NOTE] -> With Project Professional, you can develop task pane add-ins that access Project on the web, on-premises installations of Project Server, and on-premises or online SharePoint. Project Standard doesn't support direct integration with Project Server data or SharePoint task lists that are synchronized with Project Server. +Project task pane add-ins are context-sensitive, meaning they can respond to your currently selected task, resource, view, or Gantt chart data. This creates opportunities for targeted, relevant functionality that enhances your project management workflow. + +Here are the primary ways project managers use Project add-ins: + +### External system integration + +**Enterprise data connections**: Connect Project with external systems like ERP applications, timesheet systems, or accounting software. Pull relevant data into Project or push project updates to other business systems. + +**Custom workflows**: Build approval processes and status update workflows that span multiple systems while keeping Project as the central planning tool. + +### Project Server and SharePoint integration + +**Project Server data access**: Use Project Server's REST APIs and OData services to access portfolio data, resource information, and reporting data. Integrate selected task or resource information with broader organizational project data. + +**SharePoint connectivity**: Connect with SharePoint libraries, lists, and workflows. Access project templates, document libraries, and team collaboration spaces directly from Project. + +### Data visualization and reporting + +**Custom dashboards**: Create specialized views of project data by combining Project information with external data sources. Build reports and visualizations tailored to your organization's needs. + +**Real-time data display**: Show live data from other systems alongside your project plan, helping you make informed decisions without switching applications. + +> [!TIP] +> For a detailed example of Project Server integration, see [Create a Project add-in that uses REST with an on-premises Project Server OData service](../project/create-a-project-add-in-that-uses-rest-with-an-on-premises-odata-service.md). + +## Build your Project add-in + +Project add-ins use the Office JavaScript API to interact with Project data and integrate with external services. While there's no Project-specific JavaScript API, you can use the [Common API](/javascript/api/office) to create add-ins. + +### Development approach -Add-in scenarios for Project include the following: +You have flexibility in how you build your Project add-in: -- **Project scheduling**: View data from related projects that can affect scheduling. A task pane add-in can integrate relevant data from other projects in Project Server. For example, you can view the departmental collection of projects and milestone dates, or view specified data from other projects that are based on a selected custom field. +- **Simple approach**: Create an HTML webpage with JavaScript, CSS, and REST queries using any text editor. +- **Framework-based**: Use modern web frameworks like React, Angular, or Vue.js for more complex user interfaces. +- **Server-side**: Build with ASP.NET, Node.js, PHP, or other server technologies for backend integration. -- **Resource management**: View the complete resource pool in Project Server or a subset based on specified skills, including cost data and resource availability, to help select appropriate resources. +### Required components -- **Statusing and approvals**: Use a web application in a task pane add-in to update or view data from an external enterprise resource planning (ERP) application, timesheet system, or accounting application. Or, create a custom status approval Web Part that can be used within both Project Web App and Project Professional. +Every Project add-in needs two key components: -- **Team communication**: Communicate with team members and resources directly from a task pane add-in, within the context of a project. Or, easily maintain a set of context-sensitive notes for yourself as you work in a project. +1. **Web application**: Your HTML, CSS, and JavaScript files that provide the user interface and functionality. +2. **Manifest file**: An XML configuration file that tells Project how to integrate your add-in. -- **Work packages**: Search for specified kinds of project templates within SharePoint libraries and online template collections. For example, find templates for construction projects and add them to your Project template collection. +The manifest file specifies the `TaskPaneExtension` type and can be shared across multiple Office applications or created specifically for Project. Learn more about manifests in the [Office Add-ins platform overview](../overview/office-add-ins.md). -- **Related items**: View metadata, documents, and messages that are related to specific tasks in a project plan. For example, you can use Project Professional to manage a project that was imported from a SharePoint task list, and still synchronize the task list with changes in the project. A task pane add-in can show additional fields or metadata that Project didn't import for tasks in the SharePoint list. +### Development best practices -- **Use the Project Server object models**: Use the GUID of a selected task with methods in the Project Server Interface (PSI) or the client-side object model (CSOM) of Project Server. For example, the web application for an add-in can read and update the statusing data of a selected task and resource, or integrate with an external timesheet application. +- **Test continuously**: Sideload and test your add-in frequently during development to catch issues early +- **Start simple**: Begin with basic functionality and gradually add complexity +- **Use familiar web technologies**: Leverage your existing HTML, CSS, and JavaScript skills -- **Get reporting data**: Use Representational State Transfer (REST), JavaScript, or LINQ queries to find related information for a selected task or resource in the OData service for reporting tables in Project Web App. Queries that use the OData service can be done with an online or an on-premises installation of Project Server. +> [!TIP] +> Learn about testing and sideloading techniques in [Test Office Add-ins](../testing/test-debug-office-add-ins.md). - For example, see [Create a Project add-in that uses REST with an on-premises Project Server OData service](../project/create-a-project-add-in-that-uses-rest-with-an-on-premises-odata-service.md). +## Share your Project add-in -## Develop Project add-ins +Once you've built your Project add-in, you have several options for distribution: -Project supports add-ins made with the JavaScript API, but there's currently no JavaScript API designed specifically for interacting with Project. You can use the [Common API](/javascript/api/office) to create Project add-ins. For information about the Common API, see [Office JavaScript API object model](../develop/office-javascript-api-object-model.md). +- **File share**: Share manifest files through network file shares for small team or departmental deployments +- **SharePoint app catalog**: Deploy through your organization's SharePoint app catalog for enterprise distribution +- **Microsoft Marketplace**: Publish to Microsoft Marketplace to reach Project users worldwide -To create an add-in, you can use a simple text editor to create an HTML webpage and related JavaScript files, CSS files, and REST queries. In addition to an HTML page or a web application, an add-in requires an add-in only manifest file for configuration. Project can use a manifest file that includes a **type** attribute that's specified as **TaskPaneExtension**. The manifest file can be used by multiple Office client applications, or you can create a manifest file that's specific for Project. For more information, see the _Development basics_ section in [Office Add-ins platform overview](../overview/office-add-ins.md). +Each distribution method has different benefits depending on your target audience and organizational requirements. Learn more about your options in [Publish your Office Add-in](../publish/publish.md). -Be sure to test your add-in as you develop it. Learn about testing and sideloading add-in in the article [Test Office Add-ins](../testing/test-debug-office-add-ins.md). +## Get started -## Distribute Project add-ins +Ready to being building your first Project add-in? Build an add-in in minutes by following with this quick start. -You can distribute add-ins through a file share, an app catalog in a SharePoint library, or AppSource. For more information, see [Publish your Office Add-in](../publish/publish.md). +> [!div class="nextstepaction"] +> [Get started with your first Project add-in](../quickstarts/project-quickstart.md) ## See also diff --git a/docs/publish/autolaunch-store-options.md b/docs/publish/autolaunch-store-options.md new file mode 100644 index 0000000000..d8af5f9bcd --- /dev/null +++ b/docs/publish/autolaunch-store-options.md @@ -0,0 +1,100 @@ +--- +title: Microsoft Marketplace listing options for your event-based add-in +description: Learn about the Microsoft Marketplace listing options available for your Office Add-ins that implement event-based activation. +ms.date: 10/28/2025 +ms.localizationpriority: medium +--- + +# Microsoft Marketplace listing options for your event-based add-in + +When you're ready to publish your [event-based activation](../develop/event-based-activation.md) add-in to [Microsoft Marketplace](https://marketplace.microsoft.com), you can choose to list your add-in as restricted or unrestricted. This article will help you understand these listing options and choose the right approach for your add-in. + +[!INCLUDE [outlook-smart-alerts-deployment](../includes/outlook-smart-alerts-deployment.md)] + +## Add-in listing options + +An event-based add-in can have either a restricted or unrestricted listing in Microsoft Marketplace. The following table compares these listing options based on their prerequisites, supported Office applications, and event-based activation support. + +| Listing features | Restricted | Unrestricted | +| --- | --- | --- | +| **Event-based activation support** | Add-in must be deployed by an organization's admin for the event-based activation feature to work. | Event-based activation works immediately upon installation by either the user or admin, without requiring admin deployment. | +| **Store searchability** | The add-in isn't searchable by name or ID in Microsoft Marketplace. Users and admins must use a specific flight code URL to install the add-in. | The add-in is searchable by name or ID and it appears in the Microsoft Marketplace search results. Users and admins can install the add-in directly from the store. | +| **Prerequisites** | You must specify a flight code for your add-in when you publish it to Microsoft Marketplace. | Your add-in must be [Microsoft 365 Certified](/microsoft-365-app-certification/docs/certification) and must comply with certain usage requirements. | +| **Supported Office apps** | <ul><li>Excel</li><li>Outlook</li><li>PowerPoint</li><li>Word</li></ul> | <ul><li>Outlook</li></ul> | + +For more information on how to list your event-based add-in as restricted or unrestricted in Microsoft Marketplace, select the tab for the applicable listing option. + +# [Restricted listing](#tab/restricted) + +Add-ins with restricted listing in Microsoft Marketplace must be deployed by an organization's admins for users to access the event-based activation features. Event-based activation is restricted if the user acquired the add-in directly from Microsoft Marketplace. For example, if the Contoso add-in includes an event-based function, the automatic invocation of the add-in only happens if the add-in was installed for the user by their organization's admin. Otherwise, the automatic invocation of the add-in is blocked. + +To enable that restriction, we can provide flight code URLs for add-ins in Microsoft Marketplace. Thanks to the flight codes, only users with these special URLs can access the listing. The following is an example URL. + +`https://marketplace.microsoft.com/product/office/WA200002862?flightCodes=EventBasedTest1` + +When a flight code is enabled for an add-in, the add-in isn't searchable by name or ID in Microsoft Marketplace or the in-app Microsoft 365 and Copilot store. As the add-in creator, you can privately share these flight codes with organization admins for add-in deployment. + +> [!NOTE] +> While users can install an event-based add-in using a flight code, the add-in won't include event-based activation. However, users can use other components of the add-in, such as a task pane or function command. + +### Specify a flight code + +To specify the flight code for your add-in, share the code in the **Notes for certification** when you publish your add-in. **Important**: Flight codes are case-sensitive. + +![A sample request for flight code in Notes for certification screen during publishing process.](../images/outlook-publish-notes-for-certification.png) + +### Deploy add-in with flight code + +After the flight codes are set, you'll receive the URL from the app certification team. You can then share the URL with admins privately. + +> [!NOTE] +> Once your add-in is certified, it may take up to 24 hours for the flight codes to take effect and for Microsoft Marketplace to hide your existing listing from the search results. + +To deploy the add-in, the admin can use the following steps. + +1. Sign in to [https://admin.microsoft.com](https://admin.microsoft.com) or [https://marketplace.microsoft.com](https://marketplace.microsoft.com) with your Microsoft 365 admin account. If the add-in has single sign-on (SSO) enabled, global admin credentials are needed. +1. Open the flight code URL in a web browser. +1. On the add-in listing page, select **Get it now**. You should be redirected to the [integrated apps portal](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps). + +# [Unrestricted listing](#tab/unrestricted) + +If an event-based add-in for Outlook has an unrestricted listing in Microsoft Marketplace, users and admins can use the event-based activation feature immediately after installing the add-in. An unrestricted add-in listing doesn't require admin deployment. + +To qualify for unrestricted listing: + +1. Your add-in must be Microsoft 365 Certified. For guidance on the certification process, see [Microsoft 365 Certification framework overview](/microsoft-365-app-certification/docs/certification). +1. Once Microsoft 365 Certification is awarded to your add-in, complete the [form](https://aka.ms/AutoLaunchForEndUser) to request for unrestricted listing. You must provide the following information. + - The certification status of your add-in. + - A link to your add-in's listing in Microsoft Marketplace. + - Your contact information. + +After submitting the form, your add-in will undergo further review for usage and market trend considerations. Upon approval, your add-in will have unrestricted listing in Microsoft Marketplace and users can immediately access event-based activation features upon installation. + +--- + +## Update existing add-ins to include event-based activation + +You can update your existing add-in to include event-based activation then resubmit it for validation and decide if you want a restricted or unrestricted Microsoft Marketplace listing. + +After the updated add-in is approved, organization admins who previously deployed the add-in will receive an update message in the **Integrated apps** section of the admin center. The message advises the admin about the event-based activation changes. After the admin accepts the changes, the update will be deployed to users. To learn more about the admin consent process, see [Admin consent for installing event-based add-ins](#admin-consent-for-installing-event-based-add-ins). + +![App update notifications on the "Integrated apps" screen.](../images/outlook-deploy-update-notification.png) + +> [!NOTE] +> For users who installed an add-in listed as restricted, the event-based activation feature won't work even after the add-in has been updated. + +## Admin consent for installing event-based add-ins + +Whenever an event-based add-in is deployed from the **Integrated apps** screen, the admin gets details about the add-in's event-based activation capabilities in the deployment wizard. The details appear in the **App Permissions and Capabilities** section. The admin should see all the events where the add-in can automatically activate. + +![The "Accept permissions requests" screen when deploying a new app.](../images/outlook-deploy-accept-permissions-requests.png) + +Similarly, when an existing add-in is updated to event-based functionality, the admin sees an "Update Pending" status on the add-in. The updated add-in is deployed only if the admin consents to the changes noted in the **App Permissions and Capabilities** section, including the set of events where the add-in can automatically activate. + +Each time you add any new event-based activation function to your add-in, admins will see the update flow in the admin portal and need to provide consent for additional events. To learn more about the update and consent process, see [Manage apps in the Integrated apps portal](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps#manage-apps-in-the-integrated-apps-portal). + +![The "Updates" flow when deploying an updated app.](../images/outlook-deploy-update-flow.png) + +## See also + +- [Activate add-ins with events](../develop/event-based-activation.md) diff --git a/docs/publish/custom-protocol-handler.md b/docs/publish/custom-protocol-handler.md deleted file mode 100644 index 137ce64cfc..0000000000 --- a/docs/publish/custom-protocol-handler.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: Trust custom protocol handlers that launch add-ins -description: How to use group policies for protocol handler trust in the registry to launch add-ins. -ms.topic: how-to -ms.date: 08/05/2024 -ms.localizationpriority: medium ---- - -# Trust custom protocol handlers to launch add-ins - -Protocol handlers are registered with the operating system to allow an app to be launched from a URI (for example, how `mailto:` launches an email client). Add-ins can also be launched from protocol handlers. This article explains how to automatically trust these custom protocol handlers by using admin group policies. - -Every add-in and protocol pair needs to be trusted. This either comes in the form end-user consent or admin group policies. Similarly, admins can block certain add-in and protocol pairs. - -> [!IMPORTANT] -> This information about trusting custom protocol handlers that launch add-ins through the registry only pertains to Windows. - -## Registry key format - -To automatically trust a custom protocol handler that launches an add-in, create a registry key at one of the following locations. Note that `<add-in id>` refers to the [Id element](/javascript/api/manifest/id) specified in the add-in only manifest or to the "id" property of the unified manifest. - -- Current user (64-bit Office): `HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\office\16.0\WEF\ProtocolHandlers\<add-in ID>` -- Local machine (64-bit Office): `HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\office\16.0\WEF\ProtocolHandlers\<add-in ID>` - -Give the key the following values. - -- **Name**: The protocol name based on the URI. For example, `mailto`. -- **Type**: REG_SZ -- **Data**: ["Allow", "Block"] - -## Set group policies - -The following sample files show how admins define and trust these custom protocol handlers across their organization. - -### Sample ADMX file - -```xml -<?xml version="1.0" encoding="utf-16"?> - -<policyDefinitions xmlns="http://www.microsoft.com/GroupPolicy/PolicyDefinitions" revision="1.0" schemaVersion="1.0"> -  <policyNamespaces> -    <target prefix="osf16" namespace="osf16.Office.Microsoft.Policies.Windows" /> -    <using prefix="windows" namespace="Microsoft.Policies.Windows" /> -  </policyNamespaces> -  <supersededAdm fileName="osf16" /> -  <resources minRequiredRevision="1.0" /> -  <categories> -    <category name="L_MicrosoftOfficeAddins" displayName="$(string.L_MicrosoftOfficeAddins)" /> -    <category name="L_ProtocolHandlers" displayName="$(string.L_ProtocolHandlers)"> -      <parentCategory ref="L_MicrosoftOfficeAddins" /> -    </category> -  </categories> -  <policies> -    <!-- Protocol ListBox --> -    <policy -      name="L_Protocols" -     class="Machine" -      displayName="$(string.L_Protocols)" -      explainText="$(string.L_ProtocolsExplain)" -      key="Software\Policies\Microsoft\Office\16.0\WEF\ProtocolHandlers\[add-in id]" -      presentation="$(presentation.L_CustomProtocolTaskpaneProtocols)"> -      <parentCategory ref="L_ProtocolHandlers" /> -      <supportedOn ref="windows:SUPPORTED_Windows7" /> -      <elements> -        <list id="L_ProtocolsListBox" explicitValue="true" additive="true"></list> -      </elements> -    </policy> -  </policies> -</policyDefinitions> -``` - -### Sample ADML file - -```xml -<?xml version="1.0" encoding="utf-16"?> -<policyDefinitionResources xmlns="http://www.microsoft.com/GroupPolicy/PolicyDefinitions" revision="1.0" schemaVersion="1.0"> -  <displayName>Microsoft Office Add-Ins</displayName> -  <description>Microsoft Office Add-Ins</description> -  <resources> -    <stringTable> -      <string id="L_MicrosoftOfficeAddins">Microsoft Office Add-ins</string> -      <string id="L_ProtocolHandlers">Protocol Handlers</string> -      <string id="L_Protocols">[add-in name]</string> -      <string id="L_ProtocolsExplain">Defines URL protocol behavior. </string> -    </stringTable> -    <presentationTable> -      <presentation id="L_Protocols"> -        <listBox refId="L_ProtocolsListBox">Protocols</listBox> -      </presentation> -    </presentationTable> -  </resources> -</policyDefinitionResources> -``` - -### Sample .REG file - -```text -Windows Registry Editor Version 5.00 - -[HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Office\16.0\WEF\ProtocolHandlers] - -[HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Office\16.0\WEF\ProtocolHandlers\[add-in id]] -"protocol1"="Allow" -"protocol2"="Block" -``` - -## Support - -Support for this feature was introduced with Office Version 2408 (Build 17928.20018). diff --git a/docs/publish/deploy-office-add-in-sso-to-azure.md b/docs/publish/deploy-office-add-in-sso-to-azure.md index 81518776f5..27a31a533f 100644 --- a/docs/publish/deploy-office-add-in-sso-to-azure.md +++ b/docs/publish/deploy-office-add-in-sso-to-azure.md @@ -1,7 +1,7 @@ --- title: Deploy a single sign-on (SSO) Office Add-in to Microsoft Azure App Service | Microsoft Docs description: Learn how to deploy an Office Add-in that uses single sign-on (SSO) to Microsoft Azure App Service from Visual Studio Code. -ms.date: 04/12/2024 +ms.date: 05/19/2025 ms.localizationpriority: medium --- @@ -14,11 +14,11 @@ Office Add-ins that use SSO require server-side code. To support server-side cod The steps in this article work for an Office Add-in created by the [Yeoman Generator for Office Add-ins](https://github.com/OfficeDev/generator-office) using the `Office Add-in Task Pane project supporting single sign-on (localhost)` project type. Be sure you have configured the add-in project so that it runs on localhost successfully. For more information, see the [Single sign-on (SSO) quick start](../quickstarts/sso-quickstart.md). > [!NOTE] -> For information about deploying an Office Add-in that you created using Teams Toolkit, see [Deploy Teams app to the cloud](/microsoftteams/platform/toolkit/deploy?pivots=visual-studio-code) and [Deploy your first Teams app](/microsoftteams/platform/sbs-gs-javascript?tabs=vscode%2Cvsc%2Cviscode). Add-ins created with the Teams Toolkit use the unified manifest for Microsoft 365. For more information about publication of add-ins and sideloading, see [Deploy and publish Office Add-ins](publish.md). +> For information about deploying an Office Add-in that you created using Agents Toolkit, see [Deploy Teams app to the cloud](/microsoftteams/platform/toolkit/deploy?pivots=visual-studio-code) and [Deploy your first Teams app](/microsoftteams/platform/sbs-gs-javascript?tabs=vscode%2Cvsc%2Cviscode). Add-ins created with Agents Toolkit use the unified manifest for Microsoft 365. For more information about publication of add-ins and sideloading, see [Deploy and publish Office Add-ins](publish.md). The steps in this article also require: -- An Azure account. Get a trial subscription at [Microsoft Azure](https://azure.microsoft.com/free/). +- An Azure account. Get a trial subscription at [Microsoft Azure](https://azure.microsoft.com/pricing/purchase-options/azure-account?cid=msft_learn) - [Azure Account extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account) for VS Code. - [Azure App Service extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azureappservice) for VS Code. @@ -41,14 +41,14 @@ App Service supports various versions of Node.js on both Linux and Windows. Sele # [Deploy to Linux](#tab/linux) 1. Right-click (or select and hold) on App Services and select **Create new Web App**. A Linux container is used by default. -1. Type a globally unique name for your web app and press **Enter**. The name must be unique across all of Azure and use only alphanumeric characters ('A-Z', 'a-z', and '0-9') and hyphens ('-'). +1. Type a globally unique name for your web app and press <kbd>Enter</kbd>. The name must be unique across all of Azure and use only alphanumeric characters ('A-Z', 'a-z', and '0-9') and hyphens ('-'). 1. In Select a runtime stack, select the **Node 16 LTS** runtime stack. 1. In Select a pricing tier, select **Free (F1)** and wait for the resources to be provisioned in Azure. When prompted to deploy, don't deploy the add-in yet. You'll do that in a later step. # [Deploy to Windows](#tab/windows) 1. Right-click (or select and hold) on App Services and select **Create new Web App... Advanced**. -1. Type a globally unique name for your web app and press **Enter**. The name must be unique across all of Azure and use only alphanumeric characters ('A-Z', 'a-z', and '0-9') and hyphens ('-'). +1. Type a globally unique name for your web app and press <kbd>Enter</kbd>. The name must be unique across all of Azure and use only alphanumeric characters ('A-Z', 'a-z', and '0-9') and hyphens ('-'). 1. Select the resource group you want to use. If you don't have a resource group, select **Create a new resource group**, then enter a name for the resource group, such as *AppServiceQS-rg*. 1. Select the **Node 16 LTS** runtime stack. 1. Select **Windows** for the operating system. @@ -71,13 +71,13 @@ App Service supports various versions of Node.js on both Linux and Windows. Sele ## Update package.json -1. Open the package.json file. Then replace the `start` command in the `"scripts"` section with the following entry. +1. Open the package.json file. Then replace the `start` command in the ``"scripts"`` section with the following entry. ```json "start": "node middletier.js", ``` -1. Find the `"prestart"` entry in the '"scripts"' section and delete it. This section is not needed for this deployment. +1. Find the `"prestart"` entry in the `"scripts"` section and delete it. This section is not needed for this deployment. 1. Save the file. ## Update webpack.config.js @@ -278,7 +278,7 @@ Sideload the **./dist/manifest.xml** file and test the functionality of the add- > [!NOTE] > If your app registration is on a different tenant than where you sideload the add-in, the add-in will not have admin consent for Microsoft Graph. To test in this scenario you need an admin to centrally deploy the add-in on the Microsoft 365 tenant. For more information, see [Deploy add-ins in the Microsoft 365 admin center](/microsoft-365/admin/manage/manage-deployment-of-add-ins) -If you encounter any deployment issues, see the [Azure App Service troubleshooting documentation](/troubleshoot/azure/app-service/welcome-app-service). If you use central deployment, or plan to deploy to AppSource, we recommend you [validate the Office Add-in's manifest](../testing/troubleshoot-manifest.md#microsoft-365-and-copilot-store-validation) using the '-p' option for production. +If you encounter any deployment issues, see the [Azure App Service troubleshooting documentation](/troubleshoot/azure/app-service/welcome-app-service). If you use central deployment, or plan to deploy to Microsoft Marketplace, we recommend you [validate the Office Add-in's manifest](../testing/troubleshoot-manifest.md#microsoft-365-and-copilot-store-validation) using the '-p' option for production. ## Next steps diff --git a/docs/publish/government-cloud-guidance.md b/docs/publish/government-cloud-guidance.md index 5452503fda..d8c5ef7989 100644 --- a/docs/publish/government-cloud-guidance.md +++ b/docs/publish/government-cloud-guidance.md @@ -2,7 +2,7 @@ title: Guidance for deploying Office Add-ins on government clouds description: Learn how to deploy your Office Add-in to secure, government cloud environments ms.topic: best-practice -ms.date: 10/10/2023 +ms.date: 1/28/2025 ms.localizationpriority: medium --- @@ -24,22 +24,25 @@ For all government cloud (i.e. Sovereign Cloud) environments, the public Microso [Centralized deployment](/microsoft-365/admin/manage/centralized-deployment-of-add-ins) of add-ins outside of the store is still supported. -## US Government Community Cloud (GCC) +In addition to requirements applicable to all Sovereign Clouds, each Sovereign Cloud environment has its own considerations that may affect Office Add-ins targeting the environment. These requirements and recommendations are described in the following sections. -In addition to requirements applicable to all Sovereign Clouds, each Sovereign Cloud environment has its own considerations that may affect Office Add-ins targeting the environment. GCC is the least restrictive of the government cloud environments and some of the resources required by the add-in are available from their usual production endpoints in this environment. One such resource is the Office JavaScript API library. Solution partners can continue to reference the public Office.js resource as they do with their public production solution. +### US Government Community Cloud (GCC) -## GCC High (GCCH), US Department of Defense (DOD), or other sovereign managed clouds +GCC is the least restrictive of the government cloud environments. Solution partners are permitted to reference the public Office JavaScript API library (office.js) resource as they do with their public production solution. However, we recommend that partners reference the library from the following URL. -These government clouds remain internet-connected, but the set of public endpoints made available is severely restricted. One such restricted endpoint is the public endpoint for loading the Office JavaScript API library. The public CDN location for Office.js will not be accessible from within these environments. However, there will be an internal, per-cloud Microsoft Office CDN provisioned with the same resource. This means the endpoint URL to access Office.js will be different and your Office Add-in may need some level of customization to run. Given the additional restrictions, it's likely that any solution provided to customers will require hosting provider services within the environment as well, necessitating additional customizations. You'll need to determine the best way to provide your solution to customers, such that it conforms to the additional restrictions imposed on services running within the boundaries of these environments. The Office JavaScript Library CDN URLs are as follows: +- **GCC**: `https://appsforoffice.gcc.cdn.office.net/appsforoffice/lib/1/hosted/office.js` -- **GCC High**: https://appsforoffice.gcch.cdn.office.net/appsforoffice/lib/1/hosted/office.js -- **DOD**: https://appsforoffice.dod.cdn.office.net/appsforoffice/lib/1/hosted/office.js +### GCC High (GCCH), US Department of Defense (DOD), or other sovereign managed clouds +These government clouds remain internet-connected, but the set of public endpoints made available is severely restricted. One such restricted endpoint is the public endpoint for loading the Office JavaScript API library. The public CDN location for Office.js won't be accessible from within these environments. However, there'll an internal, per-cloud Microsoft Office CDN provisioned with the same resource. This means the endpoint URL to access Office.js will be different and your Office Add-in may need some level of customization to run. Given the additional restrictions, it's likely that any solution provided to customers will require hosting provider services within the environment as well, necessitating additional customizations. You'll need to determine the best way to provide your solution to customers, such that it conforms to the additional restrictions imposed on services running within the boundaries of these environments. The Office JavaScript Library CDN URLs are as follows: -## Airgapped Sovereign Clouds +- **GCC High**: `https://appsforoffice.gcch.cdn.office.net/appsforoffice/lib/1/hosted/office.js` +- **DOD**: `https://appsforoffice.dod.cdn.office.net/appsforoffice/lib/1/hosted/office.js` + +### Airgapped Sovereign Clouds These government clouds are essentially disconnected from the public internet entirely. Any resource that would normally be accessed from public resources must instead be custom-provisioned inside these cloud environments. In the GCCH and DOD clouds mentioned previously, most (if not all) solution providers will need to provision their services and resources inside the cloud. There is an option to make firewall exceptions that allows access to public services and resources. However, this bypass is not possible in airgapped clouds. As with the GCCH and DOD clouds, there will be a Microsoft Office CDN provisioned inside each cloud environment that hosts required resources such as the Office.js library. You'll need to work closely with customer tenant administrators to determine the best way to provide your services and resources in a way that conforms to the strict access requirements for airgapped Sovereign Clouds. -## Office 365 operated by 21Vianet +### Office 365 operated by 21Vianet [!INCLUDE [Information about the China-specific CDN](../includes/21Vianet-CDN.md)] diff --git a/docs/publish/host-an-office-add-in-on-microsoft-azure.md b/docs/publish/host-an-office-add-in-on-microsoft-azure.md index aacad46b6b..8365efe345 100644 --- a/docs/publish/host-an-office-add-in-on-microsoft-azure.md +++ b/docs/publish/host-an-office-add-in-on-microsoft-azure.md @@ -1,18 +1,21 @@ ---- -title: Stage an Office Add-in on Microsoft Azure -description: Learn how to deploy an add-in web app to Azure and sideload the add-in for testing in an Office client application. -ms.date: 08/09/2024 +--- +title: Stage an Office Add-in on Microsoft Azure with Visual Studio +description: Learn how to deploy an add-in web app to Azure and sideload the add-in for testing in an Office client application using Visual Studio. +ms.date: 05/19/2025 ms.localizationpriority: medium --- -# Stage an Office Add-in on Microsoft Azure +# Stage an Office Add-in on Microsoft Azure with Visual Studio The simplest Office Add-in is made up of an manifest file and an HTML page. The manifest file describes the add-in's characteristics, such as its name, what Office desktop clients it can run in, and the URL for the add-in's HTML page. The HTML page is contained in a web app that users interact with when they install and run your add-in within an Office client application. You can host the web app of an Office Add-in on any web hosting platform, including Azure. -This article describes how to deploy an add-in web app to Azure and [sideload the add-in](../testing/test-debug-non-local-server.md) for testing in an Office client application. +This article describes how to deploy an add-in web app to Azure and [sideload the add-in](../testing/test-debug-non-local-server.md) for testing in an Office client application using Visual Studio. For information about publishing an Office Add-in that you created using Visual Studio Code to Azure, see [Publish an add-in using Visual Studio Code and Azure](publish-add-in-vs-code.md). > [!IMPORTANT] -> The process described in this article doesn't apply to Outlook Add-ins. +> The process described in this article doesn't apply to Outlook Add-ins or to add-ins that use the [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md). +> +> - For instructions about staging add-ins for Outlook on Azure with Visual Studio, see [Stage an Outlook Add-in on Microsoft Azure with Visual Studio](stage-outlook-add-in-azure.md). +> - Add-ins created using Microsoft 365 Agents Toolkit use the unified manifest. For information about publishing an add-in that you created using Agents Toolkit, see [Deploy Teams app to the cloud](/microsoftteams/platform/toolkit/deploy?pivots=visual-studio-code) and [Deploy your first Teams app](/microsoftteams/platform/sbs-gs-javascript?tabs=vscode%2Cvsc%2Cviscode). The latter article is about Teams tab apps, but it is applicable to Office Add-ins created with Agents Toolkit. ## Prerequisites @@ -44,14 +47,14 @@ This article describes how to deploy an add-in web app to Azure and [sideload th 1. In **File Sharing**, choose the drop-down arrow and then choose **Everyone** > **Add** > **Share**. > [!NOTE] -> In this walkthrough, you're using a local file share as a trusted catalog where you'll store the add-in manifest file. In a real-world scenario, you might instead choose to [deploy the manifest file to a SharePoint catalog](../publish/publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md) or [publish the add-in to AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center). +> In this walkthrough, you're using a local file share as a trusted catalog where you'll store the add-in manifest file. In a real-world scenario, you might instead choose to [deploy the manifest file to a SharePoint catalog](../publish/publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md) or [publish the add-in to Microsoft Marketplace](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center). ## Step 2: Add the file share to the Trusted Add-ins catalog 1. Start Word and create a document. > [!NOTE] - > Although this example uses Word, you can use any Office application that supports Office Add-ins such as Excel, Outlook, PowerPoint, or Project. + > Although this example uses Word, you can use any Office application that supports Office Add-ins such as Excel, PowerPoint, or Project. 1. Choose **File** > **Options**. diff --git a/docs/publish/maintain-breaking-changes.md b/docs/publish/maintain-breaking-changes.md index 63e4ac616b..bd5df578ac 100644 --- a/docs/publish/maintain-breaking-changes.md +++ b/docs/publish/maintain-breaking-changes.md @@ -1,8 +1,8 @@ ---- +--- title: Maintain your Office Add-in description: Understand our commitments to compatibility and how to keep your add-in up to date. ms.topic: best-practice -ms.date: 08/09/2024 +ms.date: 09/13/2024 ms.localizationpriority: medium --- @@ -15,8 +15,8 @@ After you publish your add-in, you should keep it up to date with any important The Microsoft 365 Developer Platform is committed to ensuring the compatibility of your add-in. We strive to avoid making breaking changes to the API surface and behavior. However, there are cases where we need to make breaking updates for the sake of security or reliability. In those rare cases, the following steps are taken to ensure users of your add-in are unaffected. - Announcements that describe the impacted features and recommended changes are made on the [Microsoft 365 Developer Blog](https://devblogs.microsoft.com/microsoft365dev/). -- If your add-in is published in [AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center), you'll be contacted through the information you provided. -- Where possible, admins of impacted Microsoft 365 tenants (including [Microsoft 365 Developer Program tenants](https://aka.ms/m365devprogram)) will be contacted through [Message Center](/microsoft-365/admin/manage/message-center). It's the responsibility of the admin to contact providers of add-in solutions published outside of AppSource. +- If your add-in is published in [Microsoft Marketplace](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center), you'll be contacted through the information you provided. +- Where possible, admins of impacted Microsoft 365 tenants (including [Microsoft 365 Developer Program tenants](https://aka.ms/m365devprogram)) will be contacted through [Message Center](/microsoft-365/admin/manage/message-center). It's the responsibility of the admin to contact providers of add-in solutions published outside of Microsoft Marketplace. ### Deprecation policy @@ -51,28 +51,24 @@ The [Yeoman Generator for Office Add-ins](../develop/yeoman-generator-overview.m This guidance also applies to copies of samples taken from the [Office Add-in code samples](https://github.com/OfficeDev/Office-Add-in-samples) and other sources. -### office.js NPM package - -The [office-js NPM package](https://www.npmjs.com/package/@microsoft/office-js) is a copy of what is hosted on the [Office.js content delivery network (CDN)](../develop/understanding-the-javascript-api-for-office.md#accessing-the-office-javascript-api-library). It's intended for scenarios where direct access to the CDN isn't possible. The NPM package isn't intended to provide versioned references to office.js. We strongly recommend always using the CDN to ensure you're using the latest version of the Office JavaScript APIs. - ## Current best practices While we strive to maintain backwards compatibility, the patterns and practices we recommend continually evolve. Our documentation strives to present the current best practices. To stay informed of new features that may improve your existing functionality, join our monthly [Office Add-ins Community Call](../overview/office-add-ins-community-call.md). ## Update your add-in -When you update your add-in, there are two pieces to consider: the web application and the manifest. Updates to your web application don't require any action from your users. Those users only have the manifest in their Office application. Changes to the manifest do require users to update. If you have published your add-in to AppSource, you will need to update your submission. More information about that process is found in the article [Update an existing offer](/partner-center/marketplace-offers/update-existing-offer). +When you update your add-in, there are two pieces to consider: the web application and the manifest. Updates to your web application don't require any action from your users. Those users only have the manifest in their Office application. Changes to the manifest do require users to update. If you have published your add-in to Microsoft Marketplace, you will need to update your submission. More information about that process is found in the article [Update an existing offer](/partner-center/marketplace-offers/update-existing-offer). Whenever you make a change to the manifest, you must raise the version number of the manifest. - If the add-in uses the add-in only manifest, see [Version element](/javascript/api/manifest/version). -- If the add-in uses the unified manifest, see [version property](/microsoftteams/platform/resources/schema/manifest-schema#version). +- If the add-in uses the unified manifest, see [version property](/microsoft-365/extensibility/schema/root#version). If your add-in is deployed by one or more admins to their organizations, some manifest changes require the admin to consent to the updates. Users are blocked from the add-in until consent is granted. The following manifest changes require the admin to consent again. - Changes to requested permissions. See [Requesting permissions for API use in add-ins](../develop/requesting-permissions-for-api-use-in-content-and-task-pane-add-ins.md) and [Understanding Outlook add-in permissions](../outlook/understanding-outlook-add-in-permissions.md). - Additional or changed [Scopes](/javascript/api/manifest/scopes). (Not applicable if the add-in uses the unified manifest for Microsoft 365.) -- Additional or changed [Outlook events](../outlook/autolaunch.md). +- Additional or changed [Events](../develop/event-based-activation.md). ## Community engagement diff --git a/docs/publish/manage-trust-options.md b/docs/publish/manage-trust-options.md new file mode 100644 index 0000000000..16d69703bd --- /dev/null +++ b/docs/publish/manage-trust-options.md @@ -0,0 +1,139 @@ +--- +title: Managing trust options for Office Add-ins +description: How to disable trust prompts for users without installed add-ins and how to use group policies for protocol handler trust in the registry when launching add-ins. +ms.topic: how-to +ms.date: 09/24/2025 +ms.localizationpriority: medium +--- + +# Managing trust options for Office Add-ins + +Office trust prompts help protect users by asking for consent before add-ins access their documents or launch from external protocols. While these security measures are important, there are scenarios where you don't want to prompt users to improve their experiences. This article covers how to disable trust prompts when the related add-in is not installed and how to configure protocol handler trust policies. + +## Disable trust prompts for add-ins that aren't installed + +When you share documents that contain add-in metadata, users without the required add-in installed may see trust prompts. These prompts appear when a document includes settings that instruct Office to automatically launch an add-in. + +The following scenarios trigger trust prompts when the required add-in isn't installed. + +- Documents with custom functions that use a [shared runtime](../develop/configure-your-add-in-to-use-a-shared-runtime.md). +- Documents configured to [automatically open a task pane](../develop/automatically-open-a-task-pane-with-a-document.md). +- Documents configured to [load add-ins when opened](../develop/run-code-on-document-open.md). + +You can prevent these prompts from appearing for users who don't have your add-in installed. Disable trust prompts in your document by setting the [Settings.set](/javascript/api/office/office.settings#office-office-settings-set-member(1)) method to set the `"Office.DisableTrustUX"` setting to `true`. + +```javascript +Office.context.document.settings.set("Office.DisableTrustUX", true); +Office.context.document.settings.saveAsync(); +``` + +This setting is saved in the document's OOXML metadata. When enabled, it prevents trust prompts in all the scenarios listed earlier in this section. This provides a better experience for users who don't need the add-in. + +> [!IMPORTANT] +> This setting only applies to Office on Windows and Mac. + +## Trust custom protocol handlers to launch add-ins + +Let your Office Add-in launch from a custom protocol handler (like `mailto:` or your own scheme) without prompting users for consent. This is useful when you want a seamless experience for users, or when your organization needs to centrally manage which add-ins launch from which protocols. + +> [!IMPORTANT] +> This section applies to Windows only. Support for this feature starts with Office Version 2408 (Build 17928.20018). + +### How protocol handler trust works + +A protocol handler lets an app or add-in launch from a URI (for example, clicking a `mailto:` link opens your email client). Office add-ins also launch this way. By default, users are prompted to trust each add-in and protocol pair. As an admin, pre-approve or block these pairs using group policy and the Windows registry. + +### Registry key format + +To automatically trust a custom protocol handler for an add-in, create a registry key at one of the following locations (replace `<add-in ID>` with your add-in's [manifest ID](/javascript/api/manifest/id) or unified manifest [`id`](/microsoft-365/extensibility/schema/root#id). + +- **Current user (64-bit Office)**: `HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\office\16.0\WEF\ProtocolHandlers\<add-in ID>` +- **Local machine (64-bit Office)**: `HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\office\16.0\WEF\ProtocolHandlers\<add-in ID>` + +Add the following values to the key. + +- **Name:** Protocol name (for example, `mailto`) +- **Type:** REG_SZ +- **Data:** `Allow` or `Block` + +### Set group policies + +Admins use group policy to manage protocol handler trust across the organization. The following sample files show how to set up these policies. + +#### Sample ADMX file + +```xml +<?xml version="1.0" encoding="utf-16"?> + +<policyDefinitions xmlns="http://www.microsoft.com/GroupPolicy/PolicyDefinitions" revision="1.0" schemaVersion="1.0"> +  <policyNamespaces> +    <target prefix="osf16" namespace="osf16.Office.Microsoft.Policies.Windows" /> +    <using prefix="windows" namespace="Microsoft.Policies.Windows" /> +  </policyNamespaces> +  <supersededAdm fileName="osf16" /> +  <resources minRequiredRevision="1.0" /> +  <categories> +    <category name="L_MicrosoftOfficeAddins" displayName="$(string.L_MicrosoftOfficeAddins)" /> +    <category name="L_ProtocolHandlers" displayName="$(string.L_ProtocolHandlers)"> +      <parentCategory ref="L_MicrosoftOfficeAddins" /> +    </category> +  </categories> +  <policies> +    <!-- Protocol ListBox --> +    <policy +      name="L_Protocols" +     class="Machine" +      displayName="$(string.L_Protocols)" +      explainText="$(string.L_ProtocolsExplain)" +      key="Software\Policies\Microsoft\Office\16.0\WEF\ProtocolHandlers\[add-in id]" +      presentation="$(presentation.L_CustomProtocolTaskpaneProtocols)"> +      <parentCategory ref="L_ProtocolHandlers" /> +      <supportedOn ref="windows:SUPPORTED_Windows7" /> +      <elements> +        <list id="L_ProtocolsListBox" explicitValue="true" additive="true"></list> +      </elements> +    </policy> +  </policies> +</policyDefinitions> +``` + +#### Sample ADML file + +```xml +<?xml version="1.0" encoding="utf-16"?> +<policyDefinitionResources xmlns="http://www.microsoft.com/GroupPolicy/PolicyDefinitions" revision="1.0" schemaVersion="1.0"> +  <displayName>Microsoft Office Add-Ins</displayName> +  <description>Microsoft Office Add-Ins</description> +  <resources> +    <stringTable> +      <string id="L_MicrosoftOfficeAddins">Microsoft Office Add-ins</string> +      <string id="L_ProtocolHandlers">Protocol Handlers</string> +      <string id="L_Protocols">[add-in name]</string> +      <string id="L_ProtocolsExplain">Defines URL protocol behavior. </string> +    </stringTable> +    <presentationTable> +      <presentation id="L_Protocols"> +        <listBox refId="L_ProtocolsListBox">Protocols</listBox> +      </presentation> +    </presentationTable> +  </resources> +</policyDefinitionResources> +``` + +#### Sample .REG file + +The following example shows how to configure the registry directly using a .REG file. + +```text +Windows Registry Editor Version 5.00 +[HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Office\16.0\WEF\ProtocolHandlers] + +[HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Office\16.0\WEF\ProtocolHandlers\[add-in id]] +"protocol1"="Allow" +"protocol2"="Block" +``` + +## See also + +- [Office Add-ins manifest](../develop/add-in-manifests.md) +- [Use policy settings to manage privacy controls for Microsoft 365 Apps for enterprise](/microsoft-365-apps/privacy/manage-privacy-controls) diff --git a/docs/publish/package-your-add-in-using-visual-studio.md b/docs/publish/package-your-add-in-using-visual-studio.md index 73705f712e..6aa7f13beb 100644 --- a/docs/publish/package-your-add-in-using-visual-studio.md +++ b/docs/publish/package-your-add-in-using-visual-studio.md @@ -1,4 +1,4 @@ ---- +--- title: Publish your add-in using Visual Studio description: How to deploy your web project and package your add-in by using Visual Studio 2019. ms.date: 01/23/2023 @@ -32,7 +32,7 @@ Complete the following steps to package your add-in using Visual Studio 2019. 1. From the **Build** tab, choose **Publish [Name of your add-in]**. 2. In the **Pick a publish target** window, choose **IIS, FTP, etc**, and select **Configure**. Next, select **Publish**. 3. A wizard appears that will help guide you through the process. Ensure the publish method is your preferred method, such as Web Deploy. -4. In the **Destination URL** box, enter the URL of the website that will host the content files of your add-in, and then select **Next**. If you plan to submit your add-in to AppSource, you can choose the **Validate Connection** button to identify any issues that will prevent your add-in from being accepted. You should address all issues before you submit your add-in to the store. +4. In the **Destination URL** box, enter the URL of the website that will host the content files of your add-in, and then select **Next**. If you plan to submit your add-in to Microsoft Marketplace, you can choose the **Validate Connection** button to identify any issues that will prevent your add-in from being accepted. You should address all issues before you submit your add-in to the store. 5. Confirm any settings desired including **File Publish Options** and select **Save**. > [!IMPORTANT] @@ -49,4 +49,4 @@ You can now upload your manifest to the appropriate location to [publish your ad ## See also - [Publish your Office Add-in](../publish/publish.md) -- [Make your solutions available in AppSource and within Office](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center) +- [Make your solutions available in Microsoft Marketplace and within Office](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center) diff --git a/docs/publish/publish-add-in-vs-code.md b/docs/publish/publish-add-in-vs-code.md index 92149b1bba..1f1031ebb3 100644 --- a/docs/publish/publish-add-in-vs-code.md +++ b/docs/publish/publish-add-in-vs-code.md @@ -1,7 +1,7 @@ --- title: Publish an add-in using Visual Studio Code and Azure -description: How to publish an add-in using Visual Studio Code and Azure Active Directory -ms.date: 03/27/2023 +description: How to publish an add-in using Visual Studio Code and Microsoft Entra ID +ms.date: 05/19/2025 ms.custom: vscode-azure-extension-update-completed ms.localizationpriority: medium --- @@ -13,11 +13,11 @@ This article describes how to publish an Office Add-in that you created using th > [!NOTE] > > - For information about publishing an Office Add-in that you created using Visual Studio, see [Publish your add-in using Visual Studio](package-your-add-in-using-visual-studio.md). -> - For information about publishing an Office Add-in that you created using Teams Toolkit, see [Deploy Teams app to the cloud](/microsoftteams/platform/toolkit/deploy?pivots=visual-studio-code) and [Deploy your first Teams app](/microsoftteams/platform/sbs-gs-javascript?tabs=vscode%2Cvsc%2Cviscode). This article is about Teams tab apps, but it is applicable to Office Add-ins created with Teams Toolkit. +> - The process described in this article doesn't apply to add-ins that use the [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md). Add-ins created using Microsoft 365 Agents Toolkit use the unified manifest. For information about publishing an add-in that you created using Agents Toolkit, see [Deploy Teams app to the cloud](/microsoftteams/platform/toolkit/deploy?pivots=visual-studio-code) and [Deploy your first Teams app](/microsoftteams/platform/sbs-gs-javascript?tabs=vscode%2Cvsc%2Cviscode). The latter article is about Teams tab apps, but it is applicable to Office Add-ins created with Agents Toolkit. ## Publishing an add-in for other users to access -An Office Add-in consists of a web application and a manifest file. The web application defines the add-in's user interface and functionality, while the manifest specifies the location of the web application and defines settings and capabilities of the add-in. +The simplest Office Add-in is made up of a manifest file and an HTML page. The manifest file describes the add-in's characteristics, such as its name, what Office applications it can run in, and the URL for the add-in's HTML page. The HTML page is contained in a web app that users interact with when they install and run your add-in within an Office application. You can host the web app of an Office Add-in on any web hosting platform, including Azure. While you're developing, you can run the add-in on your local web server (`localhost`). When you're ready to publish it for other users to access, you'll need to deploy the web application and update the manifest to specify the URL of the deployed application. @@ -26,10 +26,10 @@ When your add-in is working as desired, you can publish it directly through Visu ## Using Visual Studio Code to publish >[!NOTE] -> These steps only work for projects created with the Yeoman generator, and that use the add-in only manifest. They do not apply if you created the add-in using the Teams Toolkit or created it with the Yeoman generator and it uses the unified manifest for Microsoft 365. +> These steps only work for projects created with the Yeoman generator, and that use the add-in only manifest. They don't apply if you created the add-in using Agents Toolkit or created it with the Yeoman generator and it uses the unified manifest for Microsoft 365. 1. Open your project from its root folder in Visual Studio Code (VS Code). -1. Select **View** > **Extensions** (Ctrl+Shift+X) to open the Extensions view. +1. Select **View** > **Extensions** (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd>) to open the Extensions view. 1. Search for the **Azure Storage** extension and install it. 1. Once installed, an Azure icon is added to the **Activity Bar**. Select it to access the extension. If the **Activity Bar** is hidden, open it by selecting **View** > **Appearance** > **Activity Bar**. 1. Select **Sign in to Azure** to sign in to your Azure account. If you don't already have an Azure account, create one by selecting **Create an Azure Account**. Follow the provided steps to set up your account. @@ -40,9 +40,9 @@ When your add-in is working as desired, you can publish it directly through Visu :::image type="content" source="../images/azure-extension-create-storage-account.png" alt-text="Selecting Storage accounts > Create Storage Account in the Azure extension."::: -1. Right-click (or select and hold) your storage account and select **Configure Static Website**. You'll be asked to enter the index document name and the 404 document name. Change the index document name from the default `index.html` to **`taskpane.html`**. You may also change the 404 document name but are not required to. +1. Right-click (or select and hold) your storage account and select **Configure Static Website**. You'll be asked to enter the index document name and the 404 document name. Change the index document name from the default `index.html` to **`taskpane.html`**. You may also change the 404 document name but aren't required to. 1. Right-click (or select and hold) your storage account again and this time select **Browse Static Website**. From the browser window that opens, copy the website URL. -1. Open your project's manifest file (`manifest.xml`) and change all references to your localhost URL (such as `https://localhost:3000`) to the URL you've copied. This endpoint is the static website URL for your newly created storage account. Save the changes to your manifest file. +1. Open your project's manifest file and change all references to your localhost URL (such as `https://localhost:3000`) to the URL you've copied. This endpoint is the static website URL for your newly created storage account. Save the changes to your manifest file. 1. Open a command line prompt or terminal window and go to the root directory of your add-in project. Run the following command to prepare all files for production deployment. ```command line @@ -65,7 +65,7 @@ If your add-in has custom functions, there are a few more steps to enable them o 1. Right-click (or select and hold) the Azure storage account and select **Open in Portal**. 1. In the Settings group, select **Resource sharing (CORS)**. You can also use the search box to find this. -1. Create a new CORS rule with the following settings. +1. Create a new CORS rule for the **Blob service** with the following settings. |Property |Value | |----------------|-----------------------------| diff --git a/docs/publish/publish-nested-app-auth-add-in.md b/docs/publish/publish-nested-app-auth-add-in.md new file mode 100644 index 0000000000..78440773cf --- /dev/null +++ b/docs/publish/publish-nested-app-auth-add-in.md @@ -0,0 +1,115 @@ +--- +title: Publish an add-in that requires admin consent for Microsoft Graph scopes +description: Learn how to publish updates to an Office Add-in to use Microsoft Graph scopes and require admin consent. +ms.service: microsoft-365 +ms.subservice: add-ins +ms.topic: how-to +ms.date: 12/18/2024 +--- + +# Publish an add-in that requires admin consent for Microsoft Graph scopes + +In this article you'll learn how to publish updates to an Office Add-in to use Microsoft Graph scopes and require admin consent. This is a common scenario if you have moved your Outlook add-in from legacy Exchange Online tokens to using the Microsoft authentication library (MSAL) with nested app authentication (NAA) and Entra ID tokens with Microsoft Graph APIs. + +To publish updates there are three things to consider. + +1. How to deploy changes made in the add-in code to your web server. +1. How to obtain admin consent to the Microsoft Graph scopes. +1. How to deploy updates in your manifest. + +## Deploy updates to your add-in code + +Once you've updated and tested your add-in code, you'll need to deploy them to your web server. Follow your own update process (such as staging and production). Once deployed, all users of your add-in will see the changes and start using the updated add-in code. There is no need for admins or users to take any actions to see the updates. + +Any Microsoft Graph scopes used by your add-in require consent from either the user or the admin of a tenant. If the admin doesn't consent, the user will be prompted to provide consent when your add-in requests an access token through MSAL. For the best user experience, avoid prompting users for consent at all. Instead, ask your admin to provide consent for the entire tenant. + +There are two ways to get admin consent: use an admin consent URI or use the unified manifest. + +## Get admin consent via admin consent URI + +You can get admin consent by providing an admin consent URI. It provides a link that an admin can select. A dialog box prompts them to sign in with admin credentials, and consent to the Microsoft Graph scopes your add-in requires. + +To construct the admin URI, use the following pattern. + +```html +https://login.microsoftonline.com/organizations/v2.0/adminconsent?client_id={client_id}&scope={scopes}&redirect_uri={redirect_uri} +``` + +where: + +- `client_id`: The ID of your app registration. +- `scope`: Each scope (such as Microsoft Graph scopes) requires admin consent using the space as delimiter. Because the Microsoft authentication library (MSAL) always requests an ID and refresh token, you should always include the `openid`, `profile`, and `offline_access` scopes. These are requested by default by MSAL even if your add-in does not request them. +- `redirect_uri`: A redirect page for when consent is completed. The Microsoft identity platform will redirect to this page after an admin consents. The redirect page is sent a success or fail JSON message as specified in [Admin consent on the Microsoft identity platform](/entra/identity-platform/v2-admin-consent). On the page you can indicate the consent status to the admin as well as provide more information or next steps about your add-in. + +> [!IMPORTANT] +> The redirect page must be added to the list of single-page application (SPA) redirects in your app registration along with the `brk-multihub` redirect or the admin consent URI will fail. + +The following admin URI example shows how to specify the `openid`, `profile`, `offline_access`, `user.read` and `files.read` scopes and redirect to a page on your web server named `consentRedirect.html`. + +```html +https://login.microsoftonline.com/organizations/v2.0/adminconsent?client_id=63e62b68-c5c7-48f9-82bf-8c41d5637b49&scope=offline_access openid profile user.read files.read&redirect_uri=https://localhost:3000/consentRedirect.html +``` + +> [!NOTE] +> If the resource identifier is omitted in the scope parameter, the resource is assumed to be Microsoft Graph. For example, `User.Read` is equivalent to `https://graph.microsoft.com/User.Read`. + +## Get admin consent via the unified manifest + +You can also get admin consent as an automatic part of the deployment workflow when your add-in is deployed. To do this, add the `webApplicationInfo` property to your unified manifest. Then the admin deploys the updated manifest, either through central deployment, or from an update through Microsoft Marketplace. When the admin deploys the updated manifest, they are automatically prompted to consent to the scopes required by the add-in. If they don't consent, the updated add-in will not deploy. + +### Add Graph scopes to app registration + +When the admin deploys the updated manifest of your add-in, the consent process will read your app registration for which scopes to require the admin for consent. Be sure to add all permissions your add-in requires using the following steps. + +1. Sign in to the [Azure Portal](https://portal.azure.com/) and open your app registration. + +1. From the left pane, select **API permissions**. + + :::image type="content" source="../images/azure-portal-api-permissions.png" alt-text="The API permissions pane."::: + + The **API permissions** pane opens. + +1. Select **Add a permission**. + + :::image type="content" source="../images/azure-portal-add-a-permission.png" alt-text="Adding a permission on the API permissions pane."::: + + The **Request API permissions** pane opens. + +1. Select **Microsoft Graph**. + + :::image type="content" source="../images/azure-portal-request-api-permissions-graph.png" alt-text="The Request API permissions pane with Microsoft Graph button."::: + +1. Select **Delegated permissions**. + + :::image type="content" source="../images/azure-portal-request-api-permissions-delegated.png" alt-text="The Request API permissions pane with delegated permissions button."::: + +1. In the **Select permissions** search box, search for the permissions your add-in needs. For example, for an Outlook add-in, you might use `profile`, `openid`, `Files.ReadWrite`, and `Mail.Read`. + +1. Select the checkbox for each permission as it appears. Note that the permissions will not remain visible in the list as you select each one. After selecting the permissions that your add-in needs, select **Add permissions**. + + :::image type="content" source="../images/azure-portal-request-api-permissions-add-permissions.png" alt-text="The Request API permissions pane with some permissions selected."::: + +### Add the webApplicationInfo property + +To get admin consent as part of the deployment workflow, add the `webApplicationInfo` property to your unified manifest. Set the `id` property to your app registration ID. Set the `resource` property to the value of your domain. The following example shows the `webApplicationInfo` property for an app registration for contoso.com. + +```json + "webApplicationInfo": { + "id": "a92ace55-9daf-47bc-84e9-065e9a6e70e3", + "resource": "https://contoso.com/" + }, +``` + +### Deploy the updated manifest + +If you deployed your add-in through Microsoft Marketplace, you'll need to submit your updated unified manifest for approval. For more information, see [Microsoft Marketplace submission FAQ](/partner-center/marketplace-offers/appsource-submission-faq). + +If you deployed your add-in by providing the manifest to admins for central deployment, you'll need to provide admins with an updated [app package](/microsoftteams/platform/concepts/build-and-test/apps-package) that contains the updated manifest. + +## Related content + +- [Microsoft Marketplace submission FAQ](/partner-center/marketplace-offers/appsource-submission-faq) +- [Admin consent on the Microsoft identity platform](/entra/identity-platform/v2-admin-consent) +- [Requesting permissions through consent](/entra/identity-platform/consent-types-developer) +- [webApplicationInfo property](/microsoft-365/extensibility/schema/root#webapplicationinfo) +- [Nested app authentication and Outlook legacy tokens deprecation FAQ](../outlook/faq-nested-app-auth-outlook-legacy-tokens.md) diff --git a/docs/publish/publish-office-add-ins-to-appsource.md b/docs/publish/publish-office-add-ins-to-appsource.md index 503af7b386..26126ab7bc 100644 --- a/docs/publish/publish-office-add-ins-to-appsource.md +++ b/docs/publish/publish-office-add-ins-to-appsource.md @@ -1,32 +1,52 @@ ---- -title: Publish your Office Add-in to Microsoft AppSource -description: Learn how to publish your Office Add-in to Microsoft AppSource +--- +title: Publish your Office Add-in to Microsoft Marketplace +description: Learn how to publish your Office Add-in to Microsoft Marketplace and install the add-in with a Windows app or COM/VSTO add-in. ms.topic: concept-article -ms.date: 07/15/2024 -CustomerIntent: As a developer, I want to publish my Office Add-in to Microsoft AppSource so that customers can deploy and use my new add-in. +ms.date: 06/06/2025 +CustomerIntent: As a developer, I want to publish my Office Add-in to Microsoft Marketplace so that customers can deploy and use my new add-in. --- -# Publish your Office Add-in to Microsoft AppSource +# Publish your Office Add-in to Microsoft Marketplace -Publish your Office Add-in to Microsoft AppSource to make it widely available to customers and businesses. Microsoft AppSource is an online store that contains thousands of business applications and services built by industry-leading software providers. When you publish your add-in to Microsoft AppSource, you also make it available in the in-product experience within Office. +Publish your Office Add-in to [Microsoft Marketplace](https://marketplace.microsoft.com/) to make it widely available to customers and businesses. Microsoft Marketplace is an online store that contains thousands of business applications and services built by industry-leading software providers. When you publish your add-in to Microsoft Marketplace, you also make it available in the in-product experience within Office. ## The publishing process -Before you proceed, ensure that your add-in adheres to the applicable [AppSource validation policies](/legal/marketplace/certification-policies) and that you're [ready to publish](/partner-center/marketplace-offers/checklist). +Before you proceed: + +- Have a [Partner Center account](/partner-center/marketplace-offers/open-a-developer-account). +- Ensure that your add-in adheres to the applicable [Microsoft Marketplace validation policies](/legal/marketplace/certification-policies). +- Confirm that you're [ready to publish](/partner-center/marketplace-offers/checklist). + +When you're ready to include your solution in Microsoft Marketplace and within Office, submit it to Partner Center. Then, it goes through an approval and certification process. For complete details, see [Make your solutions available in Microsoft Marketplace and within Office](/partner-center/marketplace/submit-to-appsource-via-partner-center). + +When your add-in is available in Microsoft Marketplace, there are two further steps you can take to make it more widely installed. + +- [Provide an installation link](#provide-an-installation-link) +- [Include the add-in in the installation of a Windows app or a COM or VSTO add-in](#include-the-add-in-in-the-installation-of-a-windows-app-or-comvsto-add-in) + +### Provide an installation link -When you're ready to include your solution in Microsoft AppSource and within Office, submit it to Partner Center. Then, it goes through an approval and certification process. For complete details, see [Make your solutions available in Microsoft AppSource and within Office](/partner-center/marketplace/submit-to-appsource-via-partner-center). +After you publish to Microsoft Marketplace, you can create an installation link to help customers discover and install your add-in. The installation link provides a "click and run" experience. Put the link on your website, social media, or anywhere you think helps your customers discover your add-in. When users select the link, the Office application opens with a new document and your add-in is installed without the need for users to search for it in Microsoft Marketplace and install it manually. -## Provide an installation link +> [!NOTE] +> Installation links can only be created for Excel, PowerPoint, and Word add-ins. -After you publish to Microsoft AppSource, you can create an installation link to help customers discover and install your add-in. The installation link provides a "click and run" experience. Put the link on your website, social media, or anywhere you think helps your customers discover your add-in. +There are two styles of links depending on whether you want the Office application to open in Office on the web or on desktop Office. -The link opens a new Word, Excel, or PowerPoint document in the browser for the signed-in user. Your add-in is automatically loaded in the new document so you can guide users to try your add-in without the need to search for it in Microsoft AppSource and install it manually. +- [Open in Office on the web](#open-in-office-on-the-web) +- [Open in Office on Windows or Mac](#open-in-office-on-windows-or-mac) + +> [!NOTE] +> The style of link determines only the platform that opens, not the platforms where the add-in is installed. The add-in is installed on every platform that supports all of the requirement sets that are specified in its manifest. See [Office versions and requirement sets](../develop/office-versions-and-requirement-sets.md). + +#### Open in Office on the web To create the link, use the following URL template as a reference. `https://go.microsoft.com/fwlink/?linkid={{linkId}}&templateid={{addInId}}&templatetitle={{addInName}}` -Change the three parameters in the previous URL to support your add-in as follows. +Change the placeholders in the URL as follows. - **linkId**: Specifies which web endpoint to use when opening the new document. @@ -34,22 +54,422 @@ Change the three parameters in the previous URL to support your add-in as follow - For Excel on the web: `2261819` - For PowerPoint on the web: `2261820` - **Note:** Outlook is not supported at this time. - -- **templateid**: The ID of your add-in as listed in Microsoft AppSource. -- **templatetitle**: The full title of your add-in. This must be HTML encoded. +- **addInId**: The ID of your add-in as listed in Microsoft Marketplace. +- **addInName**: The full title of your add-in. This must be URL-encoded. -For example, if you want to provide an installation link for [Script Lab](https://appsource.microsoft.com/product/office/wa104380862), use the following link. +For example, the following is an installation link for [Script Lab](https://marketplace.microsoft.com/product/office/wa104380862). [https://go.microsoft.com/fwlink/?linkid=2261819&templateid=WA104380862&templatetitle=Script%20Lab,%20a%20Microsoft%20Garage%20project](https://go.microsoft.com/fwlink/?linkid=2261819&templateid=WA104380862&templatetitle=Script%20Lab,%20a%20Microsoft%20Garage%20project) The following parameter values are used for the Script Lab installation link. -- **linkid:** The value `2261819` specifies the Excel endpoint. Script Lab supports Word, Excel, and PowerPoint, so this value can be changed to support different endpoints. -- **templateid:** The value `WA104380862` is the Microsoft AppSource ID for Script Lab. -- **templatetitle:** The value `Script%20Lab,%20a%20Microsoft%20Garage%20project` which is the HTML encoded value of the title. +- **linkid:** The value `2261819` specifies the Excel endpoint. Script Lab supports Word, Excel, and PowerPoint, so this value can be changed to support different endpoints. +- **templateid:** The value `WA104380862` is the Microsoft Marketplace ID for Script Lab. +- **templatetitle:** The value `Script%20Lab,%20a%20Microsoft%20Garage%20project` is the URL-encoded value of the title. + +#### Open in Office on Windows or Mac + +To create the link, use the following URL template as a reference. + +`{{appName}}:https://api.addins.store.office.com/addinstemplate/{{language}}/{{correlationID}}/{{addinId}}/none/{{addinName}}.{{fileFormat}}?omexsrctype=1&isexternallink=1` + +Change the placeholders in the URL as follows. + +- **appName:** This parameter specifies which Office application is opened when users click the link. + + - For Word: `ms-word` + - For Excel: `ms-excel` + - For PowerPoint: `ms-powerpoint` + +- **language:** This is the language of the add-in. For example: `de-DE`, `ja-JP`, or `zh-CN`. +- **correlationID:** A GUID for diagnostic purposes. For example, "7bf846ec-905a-5edd-b162-83498f9a8674". Use a GUID generation tool. The diagnostic purpose is defeated if multiple users have the same GUID, so we recommend you to generate it at runtime and make it different per click. +- **addInId:** The ID of your add-in as listed in Microsoft Marketplace. *This parameter is case-sensitive. Use uppercase letters.* +- **addInName:** The full name of your add-in. This must be URL-encoded. +- **fileFormat:** Specifies the format of the file that is created. + + - For Word: `docx` + - For Excel: `xlsx` + - For PowerPoint: `pptx` + +For example, the following is an installation link for Script Lab in Word on Windows with en-US as the language. + +`ms-word:https://api.addins.store.office.com/addinstemplate/en-US/228a829b-69d7-45f4-a338-c6aba330ec7e/WA104380862/none/Script%20Lab,%20a%20Microsoft%20Garage%20project.docx?omexsrctype=1&isexternallink=1` + +### Include the add-in in the installation of a Windows app or COM/VSTO add-in + +When you have a Windows app or a COM or VSTO add-in whose functions overlap with your Office Web Add-in, consider including the web add-in in the installation (or an upgrade) of the Windows app or COM/VSTO add-in. (This installation option is supported only for Excel, PowerPoint, and Word add-ins.) The process for doing this depends on whether you are a [certified Microsoft 365 developer](/microsoft-365-app-certification/docs/certification). For more information, see [Microsoft 365 App Compliance Program](https://developer.microsoft.com/microsoft-365/app-compliance-program) and [Microsoft 365 App Compliance Program overview](/microsoft-365-app-certification/overview). + +The following are the basic steps: + +1. [Join the certification program (recommended)](#join-the-certification-program-recommended) +1. [Update your installation executable (required)](#update-your-installation-executable-required) + +#### Join the certification program (recommended) + +We recommend that you join the [developer certification program](/microsoft-365-app-certification/docs/certification). Among other things, this enables your installation program to run smoother. For more information, see the following articles: + +- [Get Started in Partner Center for Microsoft 365, Teams, SaaS, and SharePoint apps](/microsoft-365-app-certification/docs/userguide) +- [Microsoft 365 App Compliance Program](https://developer.microsoft.com/microsoft-365/app-compliance-program) +- [Microsoft 365 App Compliance Program overview](/microsoft-365-app-certification/overview) +- [Microsoft 365 Certification sample evidence guide overview](/microsoft-365-app-certification/docs/seg2_overview) + +#### Update your installation executable (required) + +The following are the steps for updating your installation executable. + +1. [Check that user's Office version supports the add-ins (recommended)](#check-that-users-office-version-supports-web-add-ins-recommended) +1. [Check for Microsoft Marketplace disablement (recommended)](#check-for-Microsoft Marketplace-disablement-recommended) +1. [Create a registry key for the add-in (required)](#create-a-registry-key-for-the-add-in-required) +1. [Include privacy terms in your terms & conditions (required for certified developers)](#include-privacy-terms-in-your-terms--conditions-required-for-certified-developers) + +##### Check that user's Office version supports web add-ins (recommended) + +We recommend that your installation check whether the user has the Office application (Excel, PowerPoint, or Word) installed and whether the Office application is a build that supports including a web add-in in a Windows application installation. If it is an old version that doesn't support web add-ins, the installation program should skip all the remaining steps. Consider displaying a message to the user that recommends that they install or update to the latest version of Microsoft 365 so they can take advantage of your web add-in. They would need to rerun the installation after installing or upgrading. + +The exact code needed depends on the installation framework and the programming language that you are using. The following is an example of how to check using C#. + +> [!NOTE] +> The installation can be designed to install the add-in for all users of the computer, if an administrator of the computer is running the installation program. To implement that design, update the code to do the following. +> +> - Check if the user is an administrator of the computer. +> - If the user is an administrator, the code should do one of the following. +> +> - If you want to force the add-in to be installed for all users, the code should set the `supportLocalComputer` variable to `true`. +> - If you want to give the administrator a choice between installing the add-in only for themself or for all users on the computer, the code should present a dialog to the administrator, return the administrator's choice, and set the `supportLocalComputer` variable accordingly. + +```csharp +using Microsoft.Win32; +using System; + +namespace SampleProject +{ + internal class IsBuildSupportedSample + { + /// <summary> + /// This function checks if the build of the Office application supports web add-ins. + /// </summary> + /// <returns> Returns true if the supported build is installed, and false if an old, unsupported build is installed or if the app is not installed at all.</returns> + private bool IsBuildSupported() + { + RegistryKey hklm = Registry.CurrentUser; + string basePath = @"Software\Microsoft\Office"; + RegistryKey baseKey = Registry.CurrentUser.OpenSubKey(basePath); + string wxpName = "Word"; // Can be one of "Word", "Powerpoint", or "Excel". + bool supportLocalComputer = false; // True means LOCAL_MACHINE support, false means CURRENT_USER support. + + + const string buildNumberStr = "BuildNumber"; + const int smallBuildNumber = 18227; // This is the minimum build that supports installation of a web add-in in the installation of a Windows app. + if (supportLocalComputer) + { + smallBuildNumber = 18730; // This is the minimum build that supports installation of a web add-in, for all users of the computer, in the installation of a Windows app. + } + const int supportedBuildMajorNumber = 16; // 16 is the lowest major build of Office applications that supports web add-ins. + + if (baseKey != null) + { + Version maxVersion = new Version(supportedBuildMajorNumber, 0); // Initial value for the max supported build version + foreach (string subKeyName in baseKey.GetSubKeyNames()) + { + if (Version.TryParse(subKeyName, out Version version)) + { + if (version > maxVersion) + { + maxVersion = version; + } + } + } + + string maxVersionString = maxVersion.ToString(); + // The Office application's build number is under this path. + RegistryKey buildNumberKey = hklm.OpenSubKey(String.Format(@"Software\Microsoft\\Office\{0}\\Common\Experiment\{1}", maxVersionString, wxpName)); + + if (maxVersion.Major >= supportedBuildMajorNumber && buildNumberKey != null) + { + object buildNumberValue = buildNumberKey.GetValue(buildNumberStr); + if (buildNumberValue != null && Version.TryParse(buildNumberValue.ToString(), out Version version)) + { + if (version.Major > supportedBuildMajorNumber || (version.Major == supportedBuildMajorNumber && version.Build >= smallBuildNumber)) + { + // Build is supported + return true; + } + else + { + // Office is installed, but the build is not supported. + return false; + } + } + else + { + // There is no build number, which is an abnormal case. + return false; + } + } + else + { + // An old version is installed. + return false; + } + } + else + { + // Office is not installed. + return false; + } + } + } +} +``` + +##### Check for Microsoft Marketplace disablement (recommended) + +We recommend that your installation check whether the [Microsoft Marketplace](https://marketplace.microsoft.com/) store is disabled in the user's Office application. Microsoft 365 Administrators sometimes disable the store. If the store is disabled, the installation program should skip all the remaining steps. Consider displaying a message to the user that recommends that they contact their administrator about your web add-in. They would need to rerun the installation after the store is enabled. + +The following is an example of how to check for disablement of the store. + +```csharp +using Microsoft.Win32; +using System; + +namespace SampleProject +{ + internal class IsStoreEnabledSample + { + /// <summary> + /// This function checks if the store is enabled. + /// </summary> + /// <returns> Returns true if it store is enabled, false if store is disabled.</returns> + private bool IsStoreEnabled() + { + RegistryKey hklm = Registry.CurrentUser; + string basePath = @"Software\Microsoft\Office"; + RegistryKey baseKey = Registry.CurrentUser.OpenSubKey(basePath); + const int supportedBuildMajorNumber = 16; + + if (baseKey != null) + { + Version maxVersion = new Version(supportedBuildMajorNumber, 0); // Initial value for the maximum supported build version. + foreach (string subKeyName in baseKey.GetSubKeyNames()) + { + if (Version.TryParse(subKeyName, out Version version)) + { + if (version > maxVersion) + { + maxVersion = version; + } + } + } + + string maxVersionString = maxVersion.ToString(); + + // The StoreDisabled value is under this registry path. + string antoInstallPath = String.Format(@"Software\Microsoft\Office\{0}\Wef\AutoInstallAddins", maxVersionString); + RegistryKey autoInstallPathKey = Registry.CurrentUser.OpenSubKey(autoInstallPath); + + if (autoInstallPathKey != null) + { + object storedisableValue = autoInstallPathKey.GetValue("StoreDisabled"); + + if (storedisableValue != null) + { + int value = (int)storedisableValue; + if (value == 1) + { + // Store is disabled + return false; + } + else + { + // Store is enabled + return true; + } + } + else + { + // No such key exists since the build does not have the value, so the store is enabled. + return true; + } + } + else + { + // The registry path does not exist, so the store is enabled. + return true; + } + } + else + { + // Office is not installed at all. + return false; + } + } + } +} +``` + +##### Create a registry key for the add-in (required) + +Include in the installation program a function to add *one* of the following keys and values to the Windows Registry, depending on whether the add-in is being installed for all users of the computer or only for the user that is running the installation program. + +``` +// Only the current user. +[HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Wef\AutoInstallAddins\{{OfficeApplication}}\{{add-inName}}] +"AssetIds"="{{assetId}}" + +// All users of the computer. +[HKEY_LOCAL_MACHINE\Software\Microsoft\Office\16.0\AutoInstallAddins\{{OfficeApplication}}\{{add-inName}}] +"AssetIds"="{{assetId}}" +``` + +Replace the placeholders as follows: + +- `{{OfficeApplication}}` with the name of the Office application that the add-in should be installed in. Only `Word`, `Excel`, and `PowerPoint` are supported. + + > [!NOTE] + > If the add-in's manifest is configured to support more than one Office application, replace `{{OfficeApplication}}` with any *one* of the supported applications. Don't create separate registry entries for each supported application. The add-in will be installed for all the Office applications that it supports. + +- `{{add-inName}}` with the name of the add-in; for example `ContosoAdd-in`. +- `{{assetId}}` with the Microsoft Marketplace asset ID of your add-in, such as `WA999999999`. + +The following is an example. + +``` +// Only the current user. +[HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Wef\AutoInstallAddins\Word\ContosoAdd-in] +"AssetIds"="WA999999999" + +// All users of the computer. +[HKEY_LOCAL_MACHINE\Software\Microsoft\Office\16.0\AutoInstallAddins\Word\ContosoAdd-in] +"AssetIds"="WA999999999" +``` + +The exact code depends on your installation framework and programming language. The following is an example in C#. + +> [!NOTE] +> To install the add-in for all users, change this code so that `WriteRegisterKeys` takes a `bool` parameter. The method should set the `supportLocalMachine` variable to the value that is passed: `true` to install for all users, `false` to install for only the current user. + +```csharp +using Microsoft.Win32; +using System; + +namespace SampleProject +{ + internal class WriteRegisterKeysSample + { + /// <summary> + /// This function writes information to the registry that will tell Office applications to install the web add-in. + /// </summary> + + private void WriteRegisterKeys() + { + bool supportLocalMachine = false; // false = CurrentUser, true = LocalMachine + RegistryKey targetRootKey = supportLocalMachine ? Registry.LocalMachine : Registry.CurrentUser; + + string basePath = @"Software\Microsoft\Office"; + using (RegistryKey baseKey = targetRootKey.OpenSubKey(basePath)) + { + if (baseKey == null) + { + Console.WriteLine("Base registry path not found."); + return; + } + + string wxpName = "Word"; // Can be "Word", "Powerpoint", or "Excel". + string assetID = "WA999999999"; // Microsoft Marketplace asset ID of your web add-in. + string appName = "ContosoAddin"; // Your web add-in name. + const int supportedBuildMajorNumber = 16; + const string assetIdStr = "AssetIDs"; + + Version maxVersion = new Version(supportedBuildMajorNumber, 0); + foreach (string subKeyName in baseKey.GetSubKeyNames()) + { + if (Version.TryParse(subKeyName, out Version version)) + { + if (version > maxVersion) + { + maxVersion = version; + } + } + } + + string maxVersionString = maxVersion.ToString(); + string subKeyPath = supportLocalMachine + ? $@"Software\Microsoft\Office\{maxVersionString}\AutoInstallAddins\{wxpName}\{appName}" + : $@"Software\Microsoft\Office\{maxVersionString}\Wef\AutoInstallAddins\{wxpName}\{appName}"; + + using (RegistryKey addInKey = targetRootKey.CreateSubKey(subKeyPath)) + { + if (addInKey != null) + { + addInKey.SetValue(assetIdStr, assetID); + } + else + { + Console.WriteLine("Failed to create or open the registry subkey."); + } + } + } + } + + } +} +``` + +##### Include privacy terms in your terms & conditions (required for certified developers) + +Skip this section if you aren't a member of the certification program, but *it is required if you are*. + +Include in the installation program code to add *one* of the following keys and values to the Windows Registry, depending on whether the add-in is being installed for all users of the computer or only for the user that is running the installation program. + +``` +// Only the current user. +[HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Wef\AutoInstallAddins\{{OfficeApplication}}\{{add-inName}}] +"HasPrivacyLink"="1" + +// All users of the computer. +[HKEY_LOCAL_MACHINE\Software\Microsoft\Office\16.0\AutoInstallAddins\{{OfficeApplication}}\{{add-inName}}] +"HasPrivacyLink"="1" +``` + +Replace the `{{OfficeApplication}}` and `{{add-inName}}` placeholders exactly as in the preceding section. The following is an example. + +``` +// Only the current user. +[HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Wef\AutoInstallAddins\Word\ContosoAdd-in] +"HasPrivacyLink"="1" + +// All users of the computer. +[HKEY_LOCAL_MACHINE\Software\Microsoft\Office\16.0\AutoInstallAddins\Word\ContosoAdd-in] +"HasPrivacyLink"="1" +``` + +To implement this, just make two small changes in the code sample in the previous section. + +1. To the list of `const`s at the top of the `WriteRegistryKeys` method, add the following line: + + ```csharp + const string hasPrivacyLinkStr = "HasPrivacyLink"; // Indicates that your installer has a privacy link. + ``` + +1. Just below the line `AddInNameKey.SetValue(assetIdStr, assetID);`, add the following lines: + + ```csharp + // Set this value if the Privacy Consent has been shown on the main app installation program, this is required for a silent installation of the web add-in. + AddInNameKey.SetValue(hasPrivacyLinkStr, 1); + ``` + +#### The user's installation experience + +When an end user runs your installation executable, their experience with the web add-in installation depends on two factors. + +- Whether you're a [certified Microsoft 365 developer](/microsoft-365-app-certification/docs/certification). +- The security settings made by the user's Microsoft 365 administrator. + +If you're certified and the administrator has enabled automatic approval for all apps from certified developers, then the web add-in is installed without the need for any special action by the user after the installation executable is started. If you're not certified or the administrator hasn't granted automatic approval for all apps from certified developers, then the user is prompted to approve inclusion of the web add-in as part of the overall installation. After installation, the web add-in is available to the user in Office on the web as well as Office on Windows. + +If you're combining the installation of a web add-in with a COM/VSTO add-in, you need to think about the relationship between the two. For more information, see [Make your Office Add-in compatible with an existing COM or VSTO add-in](../develop/make-office-add-in-compatible-with-existing-com-add-in.md). ## Related content -- [Make your solutions available in Microsoft AppSource and within Office](/partner-center/marketplace/submit-to-appsource-via-partner-center) -- [What is Microsoft AppSource?](/marketplace/appsource-overview) +- [Make your solutions available in Microsoft Marketplace and within Office](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center) +- [What is Microsoft Marketplace?](/marketplace/marketplace-overview) diff --git a/docs/publish/publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md b/docs/publish/publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md index b9da4b7dfe..16ff950cb2 100644 --- a/docs/publish/publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md +++ b/docs/publish/publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md @@ -1,7 +1,7 @@ ---- +--- title: Publish task pane and content add-ins to a SharePoint app catalog description: To make Office Add-ins accessible to users within their organization, administrators can upload Office Add-ins manifest files to the app catalog for their organization. -ms.date: 04/12/2024 +ms.date: 08/13/2025 ms.localizationpriority: medium --- @@ -14,8 +14,8 @@ An app catalog is a dedicated site collection in a SharePoint web application or > > - Outlook add-ins are **not** supported by app catalogs. > - App catalogs on SharePoint don't support add-in features that are implemented in the `VersionOverrides` node of the [Office add-in only manifest](../develop/xml-manifest-overview.md), such as add-in commands. -> - If you're targeting a cloud or hybrid environment, we recommend that you [use Integrated Apps via the Microsoft 365 admin center](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps) to publish your add-ins. -> - App catalogs on SharePoint aren't supported in Office on Mac. To deploy Office Add-ins to Mac clients, you must submit them to [AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center). +> - If you're targeting a cloud or hybrid environment, we recommend that you [use the integrated apps portal via the Microsoft 365 admin center](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps) to publish your add-ins. +> - App catalogs on SharePoint aren't supported in Office on Mac. To deploy Office Add-ins to Mac clients, you must submit them to [Microsoft Marketplace](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center). > - App catalogs don't support add-ins that use the [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md). @@ -76,7 +76,7 @@ Find Office Add-ins from the app catalog using the following steps. 1. Open the application. 1. Create or open a document. -1. Select **Home** > **Add-ins**, then select **More Add-ins**. +1. Select **Home** > **Add-ins**, then select **More Settings**. _**Insert** > **Office Add-ins** in OneNote._ 1. In the Office Add-ins dialog, choose the **MY ORGANIZATION** tab. 1. Choose an Office Add-in and then choose **Add**. @@ -92,7 +92,7 @@ Find Office Add-ins from the app catalog using the following steps. Specify just the URL of the parent site collection: - `https://<domain>/sites/<AddinCatalogSiteCollection>` 1. Close and reopen the Office application. -1. Select **Home** > **Add-ins**, then select **Get Add-ins**. +1. Select **Home** > **Add-ins**, then select **More Settings**. 1. In the Office Add-ins dialog, choose the **MY ORGANIZATION** tab. 1. Choose an Office Add-in and then choose **Add**. diff --git a/docs/publish/publish.md b/docs/publish/publish.md index 5318dffa0a..11d5445293 100644 --- a/docs/publish/publish.md +++ b/docs/publish/publish.md @@ -1,7 +1,7 @@ ---- +--- title: Deploy and publish Office Add-ins description: Methods and options to deploy your Office Add-in for testing or distribution to users. -ms.date: 07/13/2024 +ms.date: 10/10/2025 ms.localizationpriority: high --- @@ -9,70 +9,74 @@ ms.localizationpriority: high You can use one of several methods to deploy your Office Add-in for testing or distribution to users. The deployment method can also affect which platforms surface your add-in. +> [!NOTE] +> For information about how end users acquire, insert, and run add-ins, see [Start using your Office Add-in](https://support.microsoft.com/office/82e665c4-6700-4b56-a3f3-ef5441996862). + +## Primary publication methods + +The following table summarizes the primary publication methods that can be used regardless of which type of manifest the add-in uses. If the add-in uses the add-in only manifest, see also [Additional publication methods for the add-in only manifest](#additional-publication-methods-for-the-add-in-only-manifest). + |Method|Use| |:---------|:------------| |[Sideloading](../testing/test-debug-office-add-ins.md#sideload-an-office-add-in-for-testing)|As part of your development process, to test your add-in running on Windows, iPad, Mac, or in a browser. (Not for production add-ins.) | -|[Network share](../testing/create-a-network-shared-folder-catalog-for-task-pane-and-content-add-ins.md)|As part of your development process, to test your add-in running on Windows after you have published the add-in to a server other than localhost. (Not for production add-ins, for testing on iPad, Mac, or the web, or for add-ins that use the [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md).)| -|[AppSource][AppSource]|To distribute your add-in publicly to users.| -|[Microsoft 365 admin center](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps)|In a cloud deployment, to distribute your add-in to users in your organization by using the Microsoft 365 admin center. This is done through [Integrated Apps](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps) or [Centralized Deployment](/microsoft-365/admin/manage/centralized-deployment-of-add-ins). | -|[SharePoint catalog](publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md)|In an on-premises environment, to distribute your add-in to users in your organization. Doesn't support add-ins that use the [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md).| -|[Exchange server](#outlook-add-in-exchange-server-deployment)|In an on-premises or online environment, to distribute Outlook add-ins to users.| +|[Microsoft Marketplace](#microsoft-marketplace)|To distribute your add-in publicly to users.| +|[Integrated apps portal](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps) in the Microsoft 365 admin center|To distribute your add-in to users in your organization.| -[!INCLUDE [publish policies note](../includes/note-publish-policies.md)] +### Production deployment methods -## Deployment options by Office application and add-in type +The following sections provide additional information about the deployment methods that are most commonly used to distribute production Office Add-ins to users. -The deployment options that are available depend on the Office application that you're targeting and the type of add-in you create. +#### Microsoft Marketplace -| Extension point | Sideloading | Network share | AppSource | Microsoft 365 admin center | SharePoint catalog\* | Exchange server | -|:----------------|:-----------:|:---------------------------------------------:|:---------:|:--------------------------:|:--------------------:|:---------------:| -| Content | Supported | Supported | Supported | Supported | Supported | Not supported | -| Task pane | Supported | Supported | Supported | Supported | Supported | Not supported | -| Command | Supported | Support for Excel, PowerPoint, and Word only | Supported | Supported | Not supported | Not supported | -| Mail app | Supported | Not supported | Supported | Supported | Not supported | Supported | +You can make your add-in available through [Microsoft Marketplace](https://marketplace.microsoft.com/marketplace/apps?product=office), Microsoft's online app store which is accessible through a browser and through the UI of Office applications. Distribution through Microsoft Marketplace gives you the option of including installation of your add-in with the installation of your Windows app or a COM or VSTO add-in. For more information, see [Publish to your Office Add-in to Microsoft Marketplace](publish-office-add-ins-to-appsource.md). -\* SharePoint catalogs don't support Office on Mac. +[!INCLUDE [publish policies note](../includes/note-publish-policies.md)] -## Production deployment methods +#### Integrated apps portal in the Microsoft 365 admin center -The following sections provide additional information about the deployment methods that are most commonly used to distribute production Office Add-ins to users within an organization. +The Microsoft 365 admin center makes it easy for an administrator to deploy Office Add-ins to users and groups in their organization. Add-ins deployed via the admin center are available to users in their Office applications right away, with no client configuration required. You can use integrated apps portal to deploy internal add-ins as well as add-ins provided by independent software vendors (ISVs). The integrated apps portal also shows admins add-ins and other apps bundled together by same ISV, giving them exposure to the entire experience across the Microsoft 365 platform. -### Deploy updates +When you link your Apps for Microsoft 365 (including Office Add-ins and Teams apps), SharePoint Framework (SPFx) apps, and [other apps](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps#what-apps-can-i-deploy-from-integrated-apps) together, you create a single software as a service (SaaS) offering for your customers. For general information about this process, see [How to plan a SaaS offer for the commercial marketplace](/azure/marketplace/plan-saas-offer). For specifics on how to create the offer, see [Create the offer](/azure/marketplace/create-new-saas-offer). -[!INCLUDE [deploy-updates-that-require-admin-consent](../includes/deploy-updates-that-require-admin-consent.md)] +For more information on the deployment process, see [Get started with the integrated apps portal](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps). -For information about how end users acquire, insert, and run add-ins, see [Start using your Office Add-in](https://support.microsoft.com/office/82e665c4-6700-4b56-a3f3-ef5441996862). +> [!NOTE] +> If your add-in uses the [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md) and is distributed as an internal add-in in the integrated apps portal (instead of being acquired by the administrator from Microsoft Marketplace), it won't be installable by users with certain versions of Office. For more information, see [Office Add-ins with the unified app manifest for Microsoft 365 - Client and platform support](../develop/unified-manifest-overview.md#client-and-platform-support). -### Integrated Apps via the Microsoft 365 admin center +> [!IMPORTANT] +> Customers in sovereign or government clouds don't have access to the integrated apps portal. They use Centralized Deployment instead. (See [Additional publication methods for the add-in only manifest](#additional-publication-methods-for-the-add-in-only-manifest) later in this article.) Centralized Deployment is a similar deployment method, but doesn't expose connected add-ins and apps to the admin. For more information, see [Determine if Centralized Deployment of add-ins works for your organization](/microsoft-365/admin/manage/centralized-deployment-of-add-ins). -The Microsoft 365 admin center makes it easy for an administrator to deploy Office Add-ins to users and groups in their organization. Add-ins deployed via the admin center are available to users in their Office applications right away, with no client configuration required. You can use Integrated Apps to deploy internal add-ins as well as add-ins provided by ISVs. Integrated Apps also shows admins add-ins and other apps bundled together by same ISV, giving them exposure to the entire experience across the Microsoft 365 platform. +#### Deploy updates -When you link your Office Add-ins, Teams apps, SPFx apps, and [other apps](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps#what-apps-can-i-deploy-from-integrated-apps) together, you create a single software as a service (SaaS) offering for your customers. For general information about this process, see [How to plan a SaaS offer for the commercial marketplace](/azure/marketplace/plan-saas-offer). For specifics on how to create Integrated Apps, see [Configure Microsoft 365 App integration](/azure/marketplace/create-new-saas-offer#configure-microsoft-365-app-integration). +[!INCLUDE [deploy-updates-that-require-admin-consent](../includes/deploy-updates-that-require-admin-consent.md)] -For more information on the Integrated Apps deployment process, see [Test and deploy Microsoft 365 Apps by partners in the Integrated apps portal](/microsoft-365/admin/manage/test-and-deploy-microsoft-365-apps). +## Additional publication methods for the add-in only manifest -> [!IMPORTANT] -> Customers in sovereign or government clouds don't have access to Integrated Apps. They will use Centralized Deployment instead. Centralized Deployment is a similar deployment method, but doesn't expose connected add-ins and apps to the admin. For more information, see [Determine if Centralized Deployment of add-ins works for your organization](/microsoft-365/admin/manage/centralized-deployment-of-add-ins). +The following table summarizes publication methods that are available *only when the add-in uses the add-in only manifest*. -### SharePoint app catalog deployment +|Method|Use|Support limitations| +|:---------|:------------|:------------| +|[Network share](../testing/create-a-network-shared-folder-catalog-for-task-pane-and-content-add-ins.md)|As part of your development process, to test your add-in running on Windows computers other than your development computer after you have published the add-in to a server other than localhost.|<ul><li>Not supported for production add-ins.</li><li>Not supported for Outlook add-ins.</li><li>Not supported for testing on iPad, Mac, or the web.</li></ul>| +|[SharePoint catalog](#sharepoint-app-catalog-deployment)|In an on-premises environment, to distribute your add-in to users in your organization.|<ul><li>Not supported for Outlook add-ins.</li><li>Not supported for Office on Mac.</li><li>Not supported for add-ins with any feature that requires a `<VersionOverrides>` element in the add-in only manifest.</li></ul>| +|[Exchange server](#outlook-add-in-exchange-server-deployment)|In an on-premises or online environment, to distribute Outlook add-ins to users.|Only supported for Outlook add-ins.| +|[Centralized Deployment](/microsoft-365/admin/manage/centralized-deployment-of-add-ins)| To distribute your add-in to users in your organization.|| -A SharePoint app catalog is a special site collection that you can create to host Word, Excel, and PowerPoint add-ins. Because SharePoint catalogs don't support new add-in features implemented in the `VersionOverrides` node of the manifest, including add-in commands, we recommend that you use Centralized Deployment via the admin center if possible. Add-in commands deployed via a SharePoint catalog open in a task pane by default. +### SharePoint app catalog deployment -If you are deploying add-ins in an on-premises environment, use a SharePoint catalog. For details, see [Publish task pane and content add-ins to a SharePoint catalog](publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md). +A SharePoint app catalog is a special SharePoint site collection that you can create to host the manifests (add-in only manifest type) of a Word, Excel, or PowerPoint add-in. If you're deploying add-ins in an on-premises environment and none of the add-in users use a Mac, consider using a SharePoint catalog. For details, see [Publish task pane and content add-ins to a SharePoint catalog](publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md). -> [!NOTE] -> SharePoint catalogs don't support Office on Mac. To deploy Office Add-ins to Mac clients, you must submit them to [AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center). +Because SharePoint catalogs don't support new add-in features implemented in the `VersionOverrides` node of the manifest, including add-in commands, for these add-ins, we recommend that you use Centralized Deployment via the admin center if possible. ### Outlook add-in Exchange server deployment -For on-premises and online environments that don't use the Azure AD identity service, you can deploy Outlook add-ins via the Exchange server. +For on-premises and online environments that don't use the [Microsoft Entra](/entra/fundamentals/what-is-entra) identity service, you can deploy Outlook add-ins via the Exchange server. Outlook add-in deployment requires: - Microsoft 365, Exchange Online, or Exchange Server 2016 or later - Outlook 2016 or later -To assign add-ins to tenants, use the Exchange admin center to upload a manifest directly, either from a file or a URL, or add an add-in from AppSource. To assign add-ins to individual users, you must use Exchange PowerShell. For details, see [Add-ins for Outlook in Exchange Server](/exchange/add-ins-for-outlook-2013-help). +To assign and manage add-ins for your tenants and users, use [Exchange PowerShell](/powershell/module/exchangepowershell). For more information, see [Add-ins for Outlook in Exchange Server](/exchange/add-ins-for-outlook-2013-help) and [Add-ins for Outlook in Exchange Online](/exchange/clients-and-mobile-in-exchange-online/add-ins-for-outlook/add-ins-for-outlook). It's important to note that some versions of Outlook clients and Exchange servers may only support certain Mailbox requirement sets. For details about supported requirement sets, see [Requirement sets supported by Exchange servers and Outlook clients](/javascript/api/requirement-sets/outlook/outlook-api-requirement-sets#requirement-sets-supported-by-exchange-servers-and-outlook-clients). @@ -80,19 +84,18 @@ It's important to note that some versions of Outlook clients and Exchange server [Microsoft 365 subscriptions provided by GoDaddy](https://www.godaddy.com/business/office-365) have limited support for add-ins. The following options are **not** supported. -- Deployment through the Microsoft Admin Center. +- Deployment through the Microsoft 365 admin center. - Deployment through Exchange servers. -- Acquiring add-ins from AppSource. +- Acquiring add-ins from Microsoft Marketplace. ## See also - [Sideload Outlook add-ins for testing](../outlook/sideload-outlook-add-ins-for-testing.md) -- [Submit to AppSource][AppSource] -- [AppSource](https://appsource.microsoft.com/marketplace/apps?product=office) +- [Publish to your Office Add-in to Microsoft Marketplace](publish-office-add-ins-to-appsource.md) +- [Microsoft Marketplace](https://marketplace.microsoft.com/marketplace/apps?product=office) - [Design guidelines for Office Add-ins](../design/add-in-design.md) -- [Create effective AppSource listings](/partner-center/marketplace-offers/create-effective-office-store-listings) +- [Create effective Microsoft Marketplace listings](/partner-center/marketplace-offers/create-effective-office-store-listings) - [Troubleshoot user errors with Office Add-ins](../testing/testing-and-troubleshooting.md) - [What is the Microsoft commercial marketplace?](/azure/marketplace/overview) - [Microsoft Dev Center app publishing page](https://developer.microsoft.com/microsoft-teams/app-publishing) -[AppSource]: /partner-center/marketplace-offers/submit-to-appsource-via-partner-center diff --git a/docs/publish/stage-outlook-add-in-azure.md b/docs/publish/stage-outlook-add-in-azure.md new file mode 100644 index 0000000000..bafba35083 --- /dev/null +++ b/docs/publish/stage-outlook-add-in-azure.md @@ -0,0 +1,69 @@ +--- +title: Stage an Outlook add-in on Microsoft Azure with Visual Studio +description: Learn how to deploy an Outlook add-in web app to Azure and sideload the add-in for testing in Outlook. +ms.date: 07/29/2025 +ms.localizationpriority: medium +--- + +# Stage an Outlook add-in on Microsoft Azure with Visual Studio + +This article describes how to deploy an Outlook add-in web app to Azure and [sideload the add-in](../testing/test-debug-non-local-server.md) for testing in an Outlook client application. + +> [!IMPORTANT] +> The process described in this article applies only to Outlook add-ins. For instructions about staging add-ins for other Office applications on Azure, see [Stage an Office Add-in on Microsoft Azure with Visual Studio](host-an-office-add-in-on-microsoft-azure.md). + +## Prerequisites + +1. Install [Visual Studio 2022](https://www.visualstudio.com/downloads) or later, and choose to include the **Azure development** workload. + + > [!NOTE] + > If you've previously installed Visual Studio, [use the Visual Studio Installer](/visualstudio/install/modify-visual-studio) to ensure that the **Azure development** workload is installed. + +1. Install Office. + + > [!NOTE] + > If you don't already have Office, you can [register for a free 1-month trial](https://www.microsoft.com/microsoft-365/try). + +1. Obtain an Azure subscription. + + > [!NOTE] + > If don't already have an Azure subscription, you can [get one as part of your Visual Studio subscription](https://azure.microsoft.com/pricing/member-offers/visual-studio-subscriptions/) or [register for a free trial](https://azure.microsoft.com/pricing/free-trial). + +## Step 1: Create an Outlook add-in in Visual Studio + +1. Start Visual Studio as an administrator. + +1. Choose **Create a new project**. + +1. Using the search box, enter **add-in**. + +1. Choose **Outlook Web Add-in** as the project type, and then choose **Next** to accept the default settings. + +Visual Studio creates a basic Outlook add-in that you'll be able to publish as-is, without making any changes to its web project. + +## Step 2: Publish your Outlook add-in web app to Azure + +1. With your add-in project open in Visual Studio, right-click (or select and hold) the web project and then choose **Publish**. + +1. Follow the instructions at [Publish your web app](/azure/app-service/quickstart-dotnetcore?tabs=netframework48&pivots=development-environment-vs#2-publish-your-web-app). Skip the article sections that precede **Publish your web app**, but be sure that the **Visual Studio** button is selected at the top of the page. + + Visual Studio publishes the web project for your Outlook add-in to your Azure web app. When Visual Studio finishes publishing the web project, your browser opens and shows a webpage with the text "Your web app is running and waiting for your content." This is the current default page for the web app. + +1. Copy the root URL (for example: `https://YourDomain.azurewebsites.net`); you'll need it when you edit the add-in manifest file later in this article. + +## Step 3: Edit and deploy the add-in manifest file + +1. In Visual Studio with the sample Outlook add-in open in **Solution Explorer**, expand the solution so that both projects show. + +1. Expand the Outlook add-in project (for example, OutlookWebAddIn), right-click (or select and hold) the manifest folder, and then choose **Open**. The add-in manifest file opens. + +1. In the manifest file, find and replace all instances of "~remoteAppUrl" with the root URL of the add-in web app on Azure. This is the URL that you copied earlier after you published the add-in web app to Azure; for example, `https://YourDomain.azurewebsites.net`. + +## Step 4: Sideload the manifest to Outlook + +Follow the guidance at [Sideload an Outlook add-in that uses an add-in only manifest](../outlook/sideload-outlook-add-ins-for-testing.md?tabs=xmlmanifest) to sideload the add-in. + +## See also + +- [Publish your Office Add-in](../publish/publish.md) +- [Publish your add-in using Visual Studio](../publish/package-your-add-in-using-visual-studio.md) diff --git a/docs/quickstarts/agent-and-add-in-quickstart.md b/docs/quickstarts/agent-and-add-in-quickstart.md new file mode 100644 index 0000000000..0b4000558b --- /dev/null +++ b/docs/quickstarts/agent-and-add-in-quickstart.md @@ -0,0 +1,349 @@ +--- +title: Build your first add-in as a Copilot skill +description: Learn how to build a simple Copilot agent that has an Excel add-in as a skill. +ms.date: 10/23/2025 +ms.topic: how-to +ms.service: microsoft-365 +ms.localizationpriority: high +--- + +# Build your first add-in as a Copilot skill + +In this article, you'll walk through the process of building a simple Excel Copilot agent that can perform actions on the content of an Excel workbook. The app also includes an Excel task pane add-in. + +## Knowledge prerequisites + +- A basic understanding of declarative agents in Microsoft 365 Copilot. If you aren't familiar with them already, we recommend the following actions. + - Read [Declarative agents for Microsoft 365 Copilot overview](/microsoft-365-copilot/extensibility/overview-declarative-agent). + - Complete the tutorial that begins at [Create declarative agents using Microsoft 365 Agent Toolkit](/microsoft-365-copilot/extensibility/build-declarative-agents). + +## Software prerequisites + +- All the prerequisites listed at [Create declarative agents using Microsoft 365 Agent Toolkit](/microsoft-365-copilot/extensibility/build-declarative-agents). +- The [Microsoft 365 Agent Toolkit](../develop/teams-toolkit-overview.md). + +## Start with an Office Add-in + +Create a basic Excel add-in with the following steps. + +1. Create an Office Add-in in Microsoft 365 Agent Toolkit by following the instructions in [Create Office Add-in projects with Microsoft 365 Agent Toolkit](../develop/teams-toolkit-overview.md#create-an-office-add-in-project). *Stop after the project is created. Don't carry out the steps in the sideloading section.* + + > [!NOTE] + > When prompted to name the add-in, use "Excel Add-in + Agent". + +1. The project opens in a new Visual Studio Code window. Close the original Visual Studio Code window. +1. In a command prompt or Visual Studio Code **TERMINAL** in the root of the project, run `npm install`. + +### Sideload and test the add-in + +1. Test that the add-in works by carrying out the following steps. + + 1. Select **View | Run** in Visual Studio Code. In the **RUN AND DEBUG** dropdown menu, select **Excel Desktop (Edge Chromium)**. + 1. Press <kbd>F5</kbd>. The project builds and a Node dev-server window opens. This process may take a couple of minutes. Eventually, Excel opens. + + > [!NOTE] + > If this is the first time that you have sideloaded an Office Add-in on your computer (or the first time in over a month), you may be prompted to delete an old certificate and/or to install a new one. Agree to both prompts. + + 1. Select the **Add-ins** button on the **Home** ribbon, and then in the flyout that opens, select your add-in. + 1. A **Contoso Add-in** group with a **Show Taskpane** button will appear on the **Home** ribbon. Use the button to open the add-in's task pane. + + > [!NOTE] + > If a **WebView Stop On Load** prompt appears, select **OK**. + + 1. When the task pane has opened, select **Run**. A cell in the worksheet changes to yellow. + 1. Stop debugging and uninstall the add-in by shutting down Excel and running `npm run stop` in a command prompt or Visual Studio Code **TERMINAL** in the root of the project. + + > [!IMPORTANT] + > Stopping debugging in the UI of Visual Studio Code doesn't work currently due to a bug. Also, neither closing Excel nor manually closing the dev server window reliably shut down the server or cause Excel to unacquire the add-in. You **must** run `npm run stop`. + +## Add a Copilot declarative agent + +Add the agent with the following steps. + +1. In the manifest file, make the following changes. + + 1. Add the following object to the root. By convention, it's put just below the "validDomains" property. You create the "declarativeAgent.json" file in a later step. + + ```json + "copilotAgents": { + "declarativeAgents": [ + { + "id": "ContosoCopilotAgent", + "file": "declarativeAgent.json" + } + ] + }, + ``` + + 1. There are multiple objects in the `"extensions.runtimes"` array. Find the one whose `"id"` is "CommandsRuntime" and copy it as an additional runtime object in the array. + 1. Make the following changes to this additional runtime object. + + 1. Change the `"id"` from "CommandsRuntime" to "CopilotAgentActionsRuntime". + 1. Change its `"actions.id"` property to "fillcolor". This is the ID of a function that you add in a later step. + 1. Change the `"actions.type"` property to "executeDataFunction". + +1. Create a file in the **appPackage** folder named **declarativeAgent.json**. +1. Paste the following content into the file. (You create the **Excel-API-local-plugin.json** file that is mentioned in this JSON in a later step.) + + ```json + { + "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.5/schema.json", + "version": "v1.5", + "name": "Excel Add-in + Agent", + "description": "Agent for working with Excel cells.", + "instructions": "You are an agent for working with an add-in. You can work with any cells, not just a well-formatted table.", + "conversation_starters": [ + { + "title": "Change cell color", + "text": "I want to change the color of cell B2 to orange" + } + ], + "actions": [ + { + "id": "localExcelPlugin", + "file": "Excel-API-local-plugin.json" + } + ] + } + ``` + +1. Create a file in the **appPackage** folder named **Excel-API-local-plugin.json**. +1. Paste the following content into the file. + + ```json + { + "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.3/schema.json", + "schema_version": "v2.3", + "name_for_human": "Excel Add-in + Agent", + "description_for_human": "Add-in Actions in Agents", + "namespace": "addinfunction", + "functions": [ + { + "name": "fillcolor", + "description": "fillcolor changes a single cell location to a specific color.", + "parameters": { + "type": "object", + "properties": { + "cell": { + "type": "string", + "description": "A cell location in the format of A1, B2, etc.", + "default" : "B2" + }, + "color": { + "type": "string", + "description": "A color in hex format, e.g., #30d5c8", + "default" : "#30d5c8" + } + }, + "required": ["cell", "color"] + }, + "returns": { + "type": "string", + "description": "A string indicating the result of the action." + }, + "states": { + "reasoning": { + "description": "`fillcolor` changes the color of a single cell based on the grid location and a color value.", + "instructions": "The user will pass ask for a color that isn't in the hex format needed in most cases, make sure to convert to the closest approximation in the right format." + }, + "responding": { + "description": "`fillcolor` changes the color of a single cell based on the grid location and a color value.", + "instructions": "If there is no error present, tell the user the cell location and color that was set." + } + } + } + ], + "runtimes": [ + { + "type": "LocalPlugin", + "spec": { + "local_endpoint": "Microsoft.Office.Addin", + "allowed_host": ["workbook"] + }, + "run_for_functions": ["fillcolor"] + } + ] + } + ``` + + [!INCLUDE [Validation warning about missing 'auth' property](../includes/auth-property-warning-note.md)] + +1. Open the **\src\commands\commands.ts** file and add the following code the end of it. + + ```javascript + async function fillcolor(cell, color) { + await Excel.run(async (context) => { + context.workbook.worksheets + .getActiveWorksheet() + .getRange(cell).format.fill.color = color; + await context.sync(); + }) + } + + Office.onReady((info) => { + Office.actions.associate("fillcolor", async (message) => { + const {cell, color} = JSON.parse(message); + await fillcolor(cell, color); + return "Cell color changed."; + }); + }); + ``` + +## Update project configuration files for a combined add-in and Copilot agent + +1. There is a file called either **teamsapp.yaml** or **m365agents.yaml** in the root of project. Replace its contents with the following: + + ```yaml + # yaml-language-server: $schema=https://aka.ms/teams-toolkit/v1.7/yaml.schema.json + # Visit https://aka.ms/teamsfx-v5.0-guide for details on this file + # Visit https://aka.ms/teamsfx-actions for details on actions + version: v1.7 + + environmentFolderPath: ./env + + # Triggered when 'teamsapp provision' is executed + provision: + # Creates a Teams app + - uses: teamsApp/create + with: + # Teams app name + name: Contoso Agent ${{APP_NAME_SUFFIX}} + # Write the information of created resources into environment file for + # the specified environment variable(s). + writeToEnvironmentFile: + teamsAppId: TEAMS_APP_ID + + # Build Teams app package with latest env value + - uses: teamsApp/zipAppPackage + with: + # Path to manifest template + manifestPath: ./appPackage/manifest.json + outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip + outputFolder: ./appPackage/build + # Validate app package using validation rules + - uses: teamsApp/validateAppPackage + with: + # Relative path to this file. This is the path for built zip file. + appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip + # Extend your Teams app to Outlook and the Microsoft 365 app + - uses: teamsApp/extendToM365 + with: + # Relative path to the build app package. + appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip + # Write the information of created resources into environment file for + # the specified environment variable(s). + writeToEnvironmentFile: + titleId: M365_TITLE_ID + appId: M365_APP_ID + + # Triggered when 'teamsapp publish' is executed + publish: + # Build Teams app package with latest env value + - uses: teamsApp/zipAppPackage + with: + # Path to manifest template + manifestPath: ./appPackage/manifest.json + outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip + outputFolder: ./appPackage/build + # Validate app package using validation rules + - uses: teamsApp/validateAppPackage + with: + # Relative path to this file. This is the path for built zip file. + appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip + # Apply the Teams app manifest to an existing Teams app in + # Teams Developer Portal. + # Will use the app id in manifest file to determine which Teams app to update. + - uses: teamsApp/update + with: + # Relative path to this file. This is the path for built zip file. + appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip + # Publish the app to + # Teams Admin Center (https://admin.teams.microsoft.com/policies/manage-apps) + # for review and approval + - uses: teamsApp/publishAppPackage + with: + appPackagePath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip + # Write the information of created resources into environment file for + # the specified environment variable(s). + writeToEnvironmentFile: + publishedAppId: TEAMS_APP_PUBLISHED_APP_ID + projectId: da53b0a2-1561-415e-919a-5b870bcd2f49 + ``` + +1. Replace the value of `projectId` in the last line of content you pasted in the preceding step with a new randomly generated GUID. +1. Open the **\env\.env.dev** file and add the following lines to the end of the file, right after the line "ADDIN_ENDPOINT=". + + ``` + TEAMS_APP_ID= + TEAMS_APP_TENANT_ID= + M365_TITLE_ID= + M365_APP_ID= + ``` + +## Test the add-in and agent + +1. Close all Office applications. +1. Open Microsoft 365 Agent Toolkit. +1. In the **Lifecycle** pane, select **Provision**. Among other things, provisioning does the following: + + - Set values for the four lines you added to the .env.dev file. + - Create a **/build** folder inside the **/appPackage** folder with the package zip file. The file contains the manifest and JSON files for the agent and plug-in. + +1. In a command prompt or Visual Studio Code **TERMINAL** in the root of the project, run `npm run dev-server` to start the server on localhost. Wait until you see a line in the server window that the app compiled successfully. This means the server is running and serving the files. + + > [!NOTE] + > If this is the first time in over a month you have run a local server for an Office Add-in on your computer, you may be prompted to delete an old certificate and to install a new one. Agree to both prompts. + +1. The first step in testing depends on the platform. + + - To test in Office on Windows, open Excel. In a few moments, the **Show Task pane** button appears on the **Home** ribbon in the Contoso Add-in group. (If it doesn't appear on the ribbon, select the **Add-ins** button on the ribbon, and then select the **Excel Add-in + Agent** app in the flyout that opens.) + - To test in Office on the web, in a browser, navigate to `https://excel.cloud.microsoft.com/`, and then create a new workbook. + +1. The process of opening your agent depends on the UI for Copilot in Office applications which is in transition. + + - If there is a **Copilot** *button* on the ribbon (not a dro down menu), select the **Copilot** button to open the **Copilot** pane. + - If there is a **Copilot** dropdown menu, open the menu and select **App Skills** to open the **Copilot** pane. + +1. In the **Copilot** pane, select the hamburger control. +1. In the pane, **Excel Add-in + Agent** should be in the list of agents. (You may need to select **See more** to ensure that all agents are listed.) If the agent isn't, try one or both of the following actions. + + - Wait a few minutes and reload Copilot. + - With Copilot open to the list of agents, click the cursor on the **Copilot** pane and press <kbd>Ctrl</kbd>+<kbd>R</kbd>. + +1. When the agent is listed, select it. The **Excel Add-in + Agent** pane opens. +1. Select the **Change cell color** conversation starter, and then press the **Send** control in the conversation box at the bottom of the pane. Select **Confirm** in response to the confirmation prompt. The cell's color should change. + + > [!TIP] + > If Copilot reports an error, repeat your prompt but add the following sentence to the prompt: "If you get an error, report the complete text of the error to me." + +1. Try entering other combinations of cell and color in the conversation box, such as "Set cell G5 to the color of the sky". + +## Make changes in the add-in or agent + +Live reloading and hot reloading for a combined add-in and agent aren't supported in the preview period. To make changes, first shut down the server and uninstall the extension with these steps. + +1. Shutting down the server depends on what window it's running in. + + - If the web server is running in the same command prompt or Visual Studio Code **TERMINAL** where you ran `npm run dev-server`, give the window focus and press <kbd>Ctrl</kbd>+<kbd>C</kbd>. Choose "Y" in response to the prompt to end the process. + - If the web server is running in a separate window, then in a command prompt or Visual Studio Code **TERMINAL** in the root of the project, run `npm run stop`. + +1. Clear the Office cache following the instructions at [Manually clear the cache](../testing/clear-cache.md#manually-clear-the-cache). +1. Open Teams and select **Apps** from the app bar, then select **Manage your apps** at the bottom of the **Apps** pane. +1. Find **Excel Add-in + Agent** in the list of apps, and select the arrow head to the left of the name to expand its row. +1. Select the trash can icon near the right end of the row, and then select **Remove** in the prompt. + +Make your changes and then repeat the steps in [Test the add-in and agent](#test-the-add-in-and-agent). + +## Troubleshooting + +See [Troubleshooting combined add-ins and agents](../design/agent-and-add-in-overview.md#troubleshooting-combined-agents-and-add-ins). + +## Next steps + +- [Add a Copilot agent to an existing add-in](../develop/agent-and-add-in.md) + +## See also + +- [Combine Copilot Agents with Office Add-ins](../design/agent-and-add-in-overview.md) +- [Declarative agent manifest object](/microsoft-365-copilot/extensibility/declarative-agent-manifest-1.2#declarative-agent-manifest-object) +- [API plugin manifest schema 2.3 for Microsoft 365 Copilot](/microsoft-365-copilot/extensibility/api-plugin-manifest-2.3) \ No newline at end of file diff --git a/docs/quickstarts/excel-custom-functions-quickstart.md b/docs/quickstarts/excel-custom-functions-quickstart.md index 78fe1f43cf..be1f9f0925 100644 --- a/docs/quickstarts/excel-custom-functions-quickstart.md +++ b/docs/quickstarts/excel-custom-functions-quickstart.md @@ -46,17 +46,13 @@ To start, you'll use the Yeoman generator to create the custom functions project To test your add-in in Excel on the web, run the following command. When you run this command, the local web server will start. Replace "{url}" with the URL of an Excel document on your OneDrive or a SharePoint library to which you have permissions. -[!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] +[!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] [!INCLUDE [alert use https](../includes/alert-use-https.md)] # [Excel on Windows or Mac](#tab/excel-windows) -To test your add-in in Excel on Windows or Mac, run the following command. When you run this command, the local web server will start and Excel will open with your add-in loaded. - -```command line -npm run start:desktop -``` +The command to test your add-in in Excel on Windows or Mac depends on when the project was created. If there's a "start:desktop" script in the "scripts" section of the package.json file, then run `npm run start:desktop`; otherwise, run `npm run start`. The local web server will start and Excel will open with your add-in loaded. [!INCLUDE [alert use https](../includes/alert-use-https.md)] @@ -70,9 +66,9 @@ In your Excel workbook, try out the `ADD` custom function by completing the foll 1. Select a cell and type `=CONTOSO`. Notice that the autocomplete menu shows the list of all functions in the `CONTOSO` namespace. -1. Run the `CONTOSO.ADD` function, using numbers `10` and `200` as input parameters, by typing the value `=CONTOSO.ADD(10,200)` in the cell and pressing enter. +1. Run the `CONTOSO.ADD` function, using numbers `10` and `200` as input parameters, by typing the value `=CONTOSO.ADD(10,200)` in the cell and pressing <kbd>Enter</kbd>. -The `ADD` custom function computes the sum of the two numbers that you specify as input parameters. Typing `=CONTOSO.ADD(10,200)` should produce the result **210** in the cell after you press enter. +The `ADD` custom function computes the sum of the two numbers that you specify as input parameters. Typing `=CONTOSO.ADD(10,200)` should produce the result **210** in the cell after you press <kbd>Enter</kbd>. [!include[Manually register an add-in](../includes/excel-custom-functions-manually-register.md)] diff --git a/docs/quickstarts/excel-quickstart-content.md b/docs/quickstarts/excel-quickstart-content.md index 9359c864f8..7fa4fc4fee 100644 --- a/docs/quickstarts/excel-quickstart-content.md +++ b/docs/quickstarts/excel-quickstart-content.md @@ -56,7 +56,7 @@ In this article, you'll walk through the process of building an Excel [content a ## Try it out -1. Using Visual Studio, test the newly created Excel add-in by pressing **F5** or choosing the **Start** button to launch Excel with the content add-in displayed in the spreadsheet. +1. Using Visual Studio, test the newly created Excel add-in by pressing <kbd>F5</kbd> or choosing the **Start** button to launch Excel with the content add-in displayed in the spreadsheet. 1. Ensure that there's text in the worksheet, then select any range of cells containing text in the worksheet. @@ -86,7 +86,7 @@ Congratulations, you've successfully created an Excel content add-in! Next, lear ## Code samples -- [Excel Content Add-in Humongous Insurance](https://github.com/OfficeDev/Excel-Content-Add-in-Humongous-Insurance) +- [Excel content add-in: Humongous Insurance](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/excel-content-add-in) ## See also diff --git a/docs/quickstarts/excel-quickstart-jquery.md b/docs/quickstarts/excel-quickstart-jquery.md index 53622d84a6..b901e726f2 100644 --- a/docs/quickstarts/excel-quickstart-jquery.md +++ b/docs/quickstarts/excel-quickstart-jquery.md @@ -1,14 +1,45 @@ --- title: Build your first Excel task pane add-in description: Learn how to build a simple Excel task pane add-in by using the Office JS API and the Yo Office tool. -ms.date: 08/20/2024 +ms.date: 12/12/2024 ms.service: excel ms.localizationpriority: high --- # Build an Excel task pane add-in -In this article, you'll walk through the process of building an Excel task pane add-in with Yo Office. +In this article, you'll walk through the process of building an Excel task pane add-in. You'll use either the Office Add-ins Development Kit or the Yeoman generator to create your Office Add-in. Select the tab for the one you'd like to use and then follow the instructions to create your add-in and test it locally. If you'd like to create the add-in project within Visual Studio Code, we recommend the Office Add-ins Development Kit. + +# [Office Add-ins Development Kit](#tab/devkit) + +[!include[Dev_kit prerequisites](../includes/dev-kit-prerequisites.md)] + +## Create the add-in project + +Click the following button to create an add-in project using the Office Add-ins Development Kit for Visual Studio Code. You'll be prompted to install the extension if don't already have it. A page that contains the project description will open in Visual Studio Code. + +> [!div class="nextstepaction"] +> [Create an add-in in Visual Studio Code](vscode://msoffice.microsoft-office-add-in-debugger/open-specific-sample?sample-id=excel-get-started-with-dev-kit) + +In the prompted page, select **Create** to create the add-in project. In the **Workspace folder** dialog that opens, select the folder where you want to create the project. + +:::image type="content" source="../images/office-add-ins-development-kit-samplepage-excelquickstart.png" alt-text="The Development Kit sample gallery in Visual Studio Code"::: + +The Office Add-ins Development Kit will create the project. It will then open the project in a *second* Visual Studio Code window. Close the original Visual Studio Code window. + +> [!NOTE] +> If you use VSCode Insiders, or you have problems opening the project page in VSCode, install the extension manually by following [these steps](../develop/development-kit-overview.md?tabs=vscode), and find the sample in the sample gallery. +[!include[Devkit_project_components_taskpane](../includes/devkit-project-components-taskpane.md)] + +## Try it out + +[!include[Dev_kit_start_debugging](../includes/dev-kit-start-debugging.md)] + +[!include[Dev_kit_stop_debugging](../includes/dev-kit-stop-debugging.md)] + +[!include[Dev_kit_troubleshooting](../includes/dev-kit-troubleshooting.md)] + +# [Yeoman generator](#tab/yeoman) ## Prerequisites @@ -27,8 +58,6 @@ In this article, you'll walk through the process of building an Excel task pane After you complete the wizard, the generator creates the project and installs supporting Node components. -[!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - ## Explore the project [!include[Yeoman generator add-in project components](../includes/yo-task-pane-project-components-js.md)] @@ -55,12 +84,14 @@ After you complete the wizard, the generator creates the project and installs su 1. [!include[Instructions to stop web server and uninstall dev add-in](../includes/stop-uninstall-dev-add-in.md)] +[!include[The common troubleshooting section for all Yo Office quick starts](../includes/quickstart-troubleshooting-yo.md)] + +--- + ## Next steps Congratulations, you've successfully created an Excel task pane add-in! Next, learn more about the capabilities of an Excel add-in and build a more complex add-in by following along with the [Excel add-in tutorial](../tutorials/excel-tutorial.md). -[!include[The common troubleshooting section for all Yo Office quick starts](../includes/quickstart-troubleshooting-yo.md)] - ## Code samples - [Excel "Hello world" add-in](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/hello-world/excel-hello-world): Learn how to build a simple Office Add-in with only a manifest, HTML web page, and a logo. diff --git a/docs/quickstarts/excel-quickstart-react.md b/docs/quickstarts/excel-quickstart-react.md index 4d5dc1baa9..b05224b125 100644 --- a/docs/quickstarts/excel-quickstart-react.md +++ b/docs/quickstarts/excel-quickstart-react.md @@ -1,7 +1,7 @@ --- title: Use React to build an Excel task pane add-in description: Learn how to build a simple Excel task pane add-in by using the Office JS API and React. -ms.date: 12/11/2023 +ms.date: 02/12/2025 ms.service: excel ms.localizationpriority: high --- @@ -27,13 +27,11 @@ In this article, you'll walk through the process of building an Excel task pane After you complete the wizard, the generator creates the project and installs supporting Node components. -[!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - ## Explore the project The add-in project that you've created with the Yeoman generator contains sample code for a basic task pane add-in. If you'd like to explore the key components of your add-in project, open the project in your code editor and review the files listed below. When you're ready to try out your add-in, proceed to the next section. -- The **manifest.xml** file in the root directory of the project defines the settings and capabilities of the add-in. To learn more about the **manifest.xml** file, see [Office Add-ins with the add-in only manifest](../develop/xml-manifest-overview.md). +- The **./manifest.xml** or **manifest.json** file in the root directory of the project defines the settings and capabilities of the add-in. - The **./src/taskpane/taskpane.html** file defines the HTML framework of the task pane, and the files within the **./src/taskpane/components** folder define the various parts of the task pane UI. - The **./src/taskpane/taskpane.css** file contains the CSS that's applied to content in the task pane. - The **./src/taskpane/components/App.tsx** file contains the Office JavaScript API code that facilitates interaction between the task pane and Excel. diff --git a/docs/quickstarts/excel-quickstart-vs.md b/docs/quickstarts/excel-quickstart-vs.md index cd60648622..96590264ae 100644 --- a/docs/quickstarts/excel-quickstart-vs.md +++ b/docs/quickstarts/excel-quickstart-vs.md @@ -136,7 +136,7 @@ In this article, you'll walk through the process of building an Excel task pane ## Try it out -1. Using Visual Studio, test the newly created Excel add-in by pressing **F5** or choosing the **Start** button to launch Excel with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. If you're asked to trust a certificate, do so to allow the add-in to connect to its Office application. +1. Using Visual Studio, test the newly created Excel add-in by pressing <kbd>F5</kbd> or choosing the **Start** button to launch Excel with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. If you're asked to trust a certificate, do so to allow the add-in to connect to its Office application. 1. In Excel, choose the **Home** tab, and then choose the **Show Taskpane** button on the ribbon to open the add-in task pane. diff --git a/docs/quickstarts/fluent-react-quickstart.md b/docs/quickstarts/fluent-react-quickstart.md index dbd3c89de5..bcb4222402 100644 --- a/docs/quickstarts/fluent-react-quickstart.md +++ b/docs/quickstarts/fluent-react-quickstart.md @@ -1,7 +1,7 @@ --- title: Fluent UI React in Office Add-ins description: Learn how to create an Office Add-in that uses Fluent UI React. -ms.date: 12/13/2023 +ms.date: 02/12/2025 ms.topic: how-to ms.service: microsoft-365 ms.localizationpriority: medium @@ -42,8 +42,6 @@ The following is an example. After you complete the wizard, the generator creates the project and installs supporting Node components. -[!INCLUDE [Yeoman generator next steps](../includes/yo-office-next-steps.md)] - > [!NOTE] > Fluent UI React v9 or later isn't supported with the Trident (IE) or EdgeHTML (Edge Legacy) webview controls. If your version of Office is using either of those, the task pane of the add-in generated by Yo Office simply contains a message to upgrade your version of Office. For more information, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). @@ -51,7 +49,10 @@ After you complete the wizard, the generator creates the project and installs su The add-in project that you've created with the Yeoman generator contains sample code for a basic task pane add-in. If you'd like to explore the components of your add-in project, open the project in your code editor and review the following files. The file name extensions depend on which language you choose. TypeScript extensions are in parentheses. When you're ready to try out your add-in, proceed to the next section. -- The **./manifest.xml** file in the root directory of the project defines the settings and capabilities of the add-in. To learn more about the **manifest.xml** file, see [Office Add-ins with the add-in only manifest](../develop/xml-manifest-overview.md). +- The **./manifest.xml** or **./manifest.json** file in the root directory of the project defines the settings and capabilities of the add-in. To learn more about the **manifest.xml** file, see [Office Add-ins with the add-in only manifest](../develop/xml-manifest-overview.md). To learn more about the **manifest.json** file, see [Office Add-ins with the unified app manifest for Microsoft 365](../develop/unified-manifest-overview.md). + + [!include[Unified manifest host application support note](../includes/unified-manifest-support-note.md)] + - The **./src/taskpane/taskpane.html** file contains the HTML markup for the task pane and loads the Office JavaScript Library. It also tests whether the webview control supports Fluent UI React v9 and displays a special message if it doesn't. - The **./src/taskpane/index.jsx (tsx)** file is the React root component. It loads React and Fluent UI React, ensures that the Office JavaScript library has been loaded, and applies the Fluent-defined theme. - The **./src/taskpane/office-document.js (ts)** file contains the Office JavaScript API code that facilitates interaction between the task pane and the Office client application. @@ -86,7 +87,7 @@ The add-in project that you've created with the Yeoman generator contains sample - To test your add-in in Excel, Word, or PowerPoint on the web, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of a Word document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] > [!NOTE] > If this is the first time that you have sideloaded an Office add-in on your computer (or the first time in over a month), you're prompted first to delete an old certificate and then to install a new one. Agree to both prompts. diff --git a/docs/quickstarts/onenote-quickstart.md b/docs/quickstarts/onenote-quickstart.md index 1adcafe5ac..56483f9097 100644 --- a/docs/quickstarts/onenote-quickstart.md +++ b/docs/quickstarts/onenote-quickstart.md @@ -27,8 +27,6 @@ In this article, you'll walk through the process of building a OneNote task pane After you complete the wizard, the generator creates the project and installs supporting Node components. -[!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - ## Explore the project The add-in project that you've created with the Yeoman generator contains sample code for a very basic task pane add-in. @@ -125,5 +123,5 @@ Congratulations, you've successfully created a OneNote task pane add-in! Next, l - [Develop Office Add-ins](../develop/develop-overview.md) - [OneNote JavaScript API programming overview](../onenote/onenote-add-ins-programming-overview.md) - [OneNote JavaScript API reference](../reference/overview/onenote-add-ins-javascript-reference.md) -- [Rubric Grader sample](https://github.com/OfficeDev/OneNote-Add-in-Rubric-Grader) +- [Sample: Rubric grader task pane add-in for OneNote on the web](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/onenote-add-in-rubric-grader) - [Using Visual Studio Code to publish](../publish/publish-add-in-vs-code.md#using-visual-studio-code-to-publish) diff --git a/docs/quickstarts/outlook-quickstart-vs.md b/docs/quickstarts/outlook-quickstart-vs.md index c26e9fc5b8..2814d925ef 100644 --- a/docs/quickstarts/outlook-quickstart-vs.md +++ b/docs/quickstarts/outlook-quickstart-vs.md @@ -1,4 +1,4 @@ ---- +--- title: Build your first Outlook add-in with Visual Studio description: Learn how to build a simple Outlook task pane add-in by using the Office JS API and a Visual Studio template. ms.date: 08/24/2024 @@ -40,7 +40,7 @@ When you've completed the wizard, Visual Studio creates a solution that contains ## Update the code -1. **MessageRead.html** specifies the HTML that will be rendered in the add-in's task pane. In **MessageRead.html**, replace the **\<body\>** element with the following markup and save the file. +1. **MessageRead.html** specifies the HTML that will be rendered in the add-in's task pane. In **MessageRead.html**, replace the `<body>` element with the following markup and save the file. ```HTML <body class="ms-font-m ms-welcome"> @@ -125,11 +125,11 @@ When you've completed the wizard, Visual Studio creates a solution that contains 1. Open the manifest file in the Add-in project. This file defines the add-in's settings and capabilities. -1. The **\<ProviderName\>** element has a placeholder value. Replace it with your name. +1. The `<ProviderName>` element has a placeholder value. Replace it with your name. -1. The **DefaultValue** attribute of the **\<DisplayName\>** element has a placeholder. Replace it with `My Office Add-in`. +1. The **DefaultValue** attribute of the `<DisplayName>` element has a placeholder. Replace it with `My Office Add-in`. -1. The **DefaultValue** attribute of the **\<Description\>** element has a placeholder. Replace it with `My First Outlook add-in`. +1. The **DefaultValue** attribute of the `<Description>` element has a placeholder. Replace it with `My First Outlook add-in`. 1. Save the file. @@ -145,7 +145,7 @@ When you've completed the wizard, Visual Studio creates a solution that contains ## Try it out -1. Using Visual Studio, test the newly created Outlook add-in by pressing **F5** or choosing the **Start** button. The add-in will be hosted locally on IIS. +1. Using Visual Studio, test the newly created Outlook add-in by pressing <kbd>F5</kbd> or choosing the **Start** button. The add-in will be hosted locally on IIS. 1. In the **Connect to Exchange email account** dialog box, enter the email address and password for your [Microsoft account](https://account.microsoft.com/account), then choose **Connect**. When the Outlook.com login page opens in a browser, sign in to your email account with the same credentials as you entered previously. diff --git a/docs/quickstarts/outlook-quickstart-yo.md b/docs/quickstarts/outlook-quickstart-yo.md index a7a5514ee2..edea2fa523 100644 --- a/docs/quickstarts/outlook-quickstart-yo.md +++ b/docs/quickstarts/outlook-quickstart-yo.md @@ -1,9 +1,10 @@ --- title: Build your first Outlook add-in description: Learn how to build a simple Outlook task pane add-in by using the Office JS API. -ms.date: 08/24/2024 +ms.date: 02/18/2025 ms.service: outlook ms.localizationpriority: high +ms.custom: required-for-compliance # Indicates that this page is linked to in a legal document. --- # Build your first Outlook add-in @@ -36,8 +37,6 @@ In this article, you'll walk through the process of building an Outlook task pan After you complete the wizard, the generator will create the project and install supporting Node components. - [!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - 1. Navigate to the root folder of the web application project. ```command line @@ -91,7 +90,7 @@ The Yeoman generator creates a project in a folder with the project name that yo ## Next steps -Congratulations, you've successfully created your first Outlook task pane add-in! Next, learn more about the capabilities of an Outlook add-in and build a more complex add-in by following along with the [Outlook add-in tutorial](../tutorials/outlook-tutorial.md). +Congratulations, you've successfully created your first Outlook task pane add-in! Next, explore more capabilities of an Outlook add-in by following along with the [Outlook add-in tutorial](../tutorials/outlook-tutorial.md). In the tutorial, you'll build a more complex add-in that incorporates a task pane, which you've learned about in the quick start. Additionally, you'll create a button that invokes a UI-less function. [!include[The common troubleshooting section for all Yo Office quick starts](../includes/quickstart-troubleshooting-yo.md)] diff --git a/docs/quickstarts/powerpoint-quickstart-content.md b/docs/quickstarts/powerpoint-quickstart-content.md index f3b99dc6d5..af6e945490 100644 --- a/docs/quickstarts/powerpoint-quickstart-content.md +++ b/docs/quickstarts/powerpoint-quickstart-content.md @@ -89,7 +89,7 @@ In this article, you'll walk through the process of building a PowerPoint [conte ## Try it out -1. Using Visual Studio, test the newly created PowerPoint add-in by pressing **F5** or choosing the **Start** button to launch PowerPoint with the content add-in displayed over the slide. +1. Using Visual Studio, test the newly created PowerPoint add-in by pressing <kbd>F5</kbd> or choosing the **Start** button to launch PowerPoint with the content add-in displayed over the slide. 1. In PowerPoint, choose the **Get slide details** button in the content add-in to get details about the current slide. diff --git a/docs/quickstarts/powerpoint-quickstart-vs.md b/docs/quickstarts/powerpoint-quickstart-vs.md index e9a9ebf0ed..4a158b2994 100644 --- a/docs/quickstarts/powerpoint-quickstart-vs.md +++ b/docs/quickstarts/powerpoint-quickstart-vs.md @@ -1,7 +1,7 @@ --- title: Build your first PowerPoint task pane add-in with Visual Studio description: Learn how to build a simple PowerPoint task pane add-in by using the Office JS API and a Visual Studio template. -ms.date: 08/20/2024 +ms.date: 06/20/2025 ms.service: powerpoint ms.localizationpriority: high --- @@ -153,7 +153,7 @@ In this article, you'll walk through the process of building a PowerPoint task p ## Try it out -1. Using Visual Studio, test the newly created PowerPoint add-in by pressing **F5** or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. +1. Using Visual Studio, test the newly created PowerPoint add-in by pressing <kbd>F5</kbd> or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. 2. In PowerPoint, insert a new blank slide, choose the **Home** tab, and then choose the **Show Taskpane** button on the ribbon to open the add-in task pane. @@ -171,7 +171,7 @@ In this article, you'll walk through the process of building a PowerPoint task p ## Next steps -Congratulations, you've successfully created a PowerPoint task pane add-in! Next, learn more about [developing Office Add-ins with Visual Studio](../develop/develop-add-ins-visual-studio.md). +Congratulations, you've successfully created a PowerPoint task pane add-in! Next, learn more about the capabilities of a PowerPoint add-in and build a more complex add-in by following along with the [PowerPoint add-in tutorial](../tutorials/powerpoint-tutorial-vs.md). [!include[The common troubleshooting section for all Visual Studio quick starts](../includes/quickstart-troubleshooting-vs.md)] diff --git a/docs/quickstarts/powerpoint-quickstart-yo.md b/docs/quickstarts/powerpoint-quickstart-yo.md index b4560ef616..7d112d4f67 100644 --- a/docs/quickstarts/powerpoint-quickstart-yo.md +++ b/docs/quickstarts/powerpoint-quickstart-yo.md @@ -27,8 +27,6 @@ In this article, you'll walk through the process of building a PowerPoint task p After you complete the wizard, the generator creates the project and installs supporting Node components. -[!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - ## Explore the project [!include[Yeoman generator add-in project components](../includes/yo-task-pane-project-components-js.md)] @@ -60,7 +58,7 @@ After you complete the wizard, the generator creates the project and installs su - To test your add-in in PowerPoint on a browser, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of a PowerPoint document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] 1. In PowerPoint, insert a new blank slide, choose the **Home** tab, and then choose the **Show Taskpane** button on the ribbon to open the add-in task pane. @@ -74,8 +72,7 @@ After you complete the wizard, the generator creates the project and installs su ## Next steps -Congratulations, you've successfully created a PowerPoint task pane add-in! Next, learn more about the capabilities of a PowerPoint add-in and build a more complex add-in by following along with the [PowerPoint add-in tutorial](../tutorials/powerpoint-tutorial.md). - +Congratulations, you've successfully created a PowerPoint task pane add-in! Next, learn more about the capabilities of a PowerPoint add-in and build a more complex add-in by following along with the [PowerPoint add-in tutorial](../tutorials/powerpoint-tutorial-yo.md). [!include[The common troubleshooting section for all Yo Office quick starts](../includes/quickstart-troubleshooting-yo.md)] diff --git a/docs/quickstarts/project-quickstart.md b/docs/quickstarts/project-quickstart.md index 8cad900ef3..7e4b2e5dc7 100644 --- a/docs/quickstarts/project-quickstart.md +++ b/docs/quickstarts/project-quickstart.md @@ -1,9 +1,9 @@ --- title: Build your first Project task pane add-in -description: Learn how to build a simple Project task pane add-in by using the Office JS API. -ms.date: 12/11/2023 +description: Learn how to build a simple Project task pane add-in by using the Office JavaScript API. +ms.date: 09/22/2025 ms.service: project -ms.localizationpriority: high +ms.localizationpriority: medium --- # Build your first Project task pane add-in @@ -29,11 +29,9 @@ In this article, you'll walk through the process of building a Project task pane After you complete the wizard, the generator creates the project and installs supporting Node components. -[!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - ## Explore the project -The add-in project that you've created with the Yeoman generator contains sample code for a very basic task pane add-in. +The add-in project that you've created with the Yeoman generator contains sample code for a basic task pane add-in. - The **./manifest.xml** file in the root directory of the project defines the settings and capabilities of the add-in. - The **./src/taskpane/taskpane.html** file contains the HTML markup for the task pane. @@ -48,19 +46,19 @@ The add-in project that you've created with the Yeoman generator contains sample cd "My Office Add-in" ``` -1. Start the local web server. +1. Complete the following steps to start the local web server and sideload your add-in. [!INCLUDE [alert use https](../includes/alert-use-https.md)] - Run the following command in the root directory of your project. When you run this command, the local web server will start. + - To test your add-in in Project, run the following command in the root directory of your project. This starts the local web server and sideloads your add-in. - ```command line - npm run dev-server - ``` + ```command line + npm start + ``` -1. In Project, create a simple project plan. + If your add-in doesn't automatically sideload, follow the instructions in [Sideload Office Add-ins on Windows](../testing/create-a-network-shared-folder-catalog-for-task-pane-and-content-add-ins.md) to manually sideload the add-in in Project. -1. Load your add-in in Project by following the instructions in [Sideload Office Add-ins on Windows](../testing/create-a-network-shared-folder-catalog-for-task-pane-and-content-add-ins.md). +1. In Project, create a simple project plan. 1. Select a single task within the project. @@ -68,15 +66,9 @@ The add-in project that you've created with the Yeoman generator contains sample ![The Project application with the task pane add-in loaded.](../images/project-quickstart-addin-1.png) -1. When you want to stop the local web server and uninstall the add-in, follow these instructions: +1. [!include[Instructions to stop web server and uninstall dev add-in](../includes/stop-uninstall-dev-add-in.md)] - - To stop the server, run the following command. - - ```command line - npm stop - ``` - - - To uninstall the sideloaded add-in, see [Remove a sideloaded add-in](../testing/create-a-network-shared-folder-catalog-for-task-pane-and-content-add-ins.md#remove-a-sideloaded-add-in). +[!include[The common troubleshooting section for all Yo Office quick starts](../includes/quickstart-troubleshooting-yo.md)] ## Next steps @@ -85,10 +77,10 @@ Congratulations, you've successfully created a Project task pane add-in! Next, l > [!div class="nextstepaction"] > [Project add-ins](../project/project-add-ins.md) -[!include[The common troubleshooting section for all Yo Office quick starts](../includes/quickstart-troubleshooting-yo.md)] - ## See also +- [Office Add-ins platform overview](../overview/office-add-ins.md) - [Develop Office Add-ins](../develop/develop-overview.md) - [Core concepts for Office Add-ins](../overview/core-concepts-office-add-ins.md) +- [Project add-in code samples](https://developer.microsoft.com/microsoft-365/gallery/?filterBy=Project,Samples) - [Using Visual Studio Code to publish](../publish/publish-add-in-vs-code.md#using-visual-studio-code-to-publish) diff --git a/docs/quickstarts/sso-quickstart.md b/docs/quickstarts/sso-quickstart.md index b9f3020221..4c0c9c2ccf 100644 --- a/docs/quickstarts/sso-quickstart.md +++ b/docs/quickstarts/sso-quickstart.md @@ -1,7 +1,7 @@ --- title: Single sign-on (SSO) quick start description: Use the Yeoman generator to build a Node.js Office Add-in that uses single sign-on. -ms.date: 12/11/2023 +ms.date: 05/16/2025 ms.service: microsoft-365 ms.localizationpriority: high --- @@ -43,8 +43,6 @@ In this article, you'll use the Yeoman generator for Office Add-ins to create an After you complete the wizard, the generator creates the project and installs supporting Node components. -[!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - ## Explore the project The add-in project that you've created with the Yeoman generator contains code for an SSO-enabled task pane add-in. @@ -126,7 +124,7 @@ Complete the following steps to try out an Outlook add-in. npm start ``` -1. Follow the instructions in [Sideload Outlook add-ins for testing](../outlook/sideload-outlook-add-ins-for-testing.md) to sideload the add-in in Outlook. Make sure that you're signed in to Outlook with a user that's a member of the same Microsoft 365 organization as the Microsoft 365 administrator account that you used to connect to Azure while configuring SSO in step 3 of the [previous section](#configure-sso). Doing so establishes the appropriate conditions for SSO to succeed. +1. Outlook will start and sideload the add-in. Make sure that you're signed in to Outlook with a user that's a member of the same Microsoft 365 organization as the Microsoft 365 administrator account that you used to connect to Azure while configuring SSO in step 3 of the [previous section](#configure-sso). Doing so establishes the appropriate conditions for SSO to succeed. 1. In Outlook, compose a new message. diff --git a/docs/quickstarts/word-quickstart-vs.md b/docs/quickstarts/word-quickstart-vs.md index 76d45e1adf..f2bda98b9d 100644 --- a/docs/quickstarts/word-quickstart-vs.md +++ b/docs/quickstarts/word-quickstart-vs.md @@ -200,7 +200,7 @@ In this article, you'll walk through the process of building a Word task pane ad ## Try it out -1. Using Visual Studio, test the newly created Word add-in by pressing **F5** or choosing **Debug** > **Start Debugging** to launch Word with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. +1. Using Visual Studio, test the newly created Word add-in by pressing <kbd>F5</kbd> or choosing **Debug** > **Start Debugging** to launch Word with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. 1. In Word, if the add-in task pane isn't already open, choose the **Home** tab, and then choose the **Show Taskpane** button on the ribbon to open the add-in task pane. (If you're using a volume-licensed perpetual version of Office 2016 or older, then custom buttons aren't supported. Instead, the task pane will open immediately.) diff --git a/docs/quickstarts/word-quickstart-yo.md b/docs/quickstarts/word-quickstart-yo.md index 71ef16a8ad..7f35c16eb5 100644 --- a/docs/quickstarts/word-quickstart-yo.md +++ b/docs/quickstarts/word-quickstart-yo.md @@ -1,15 +1,45 @@ --- title: Build your first Word task pane add-in description: Learn how to build a simple Word task pane add-in by using the Office JavaScript API. -ms.date: 08/20/2024 +ms.date: 12/12/2024 ms.service: word ms.localizationpriority: high --- # Build your first Word task pane add-in -In this article, you'll walk through the process of building a Word task pane add-in. +In this article, you'll walk through the process of building a Word task pane add-in. You'll use either the Office Add-ins Development Kit or the Yeoman generator to create your Office Add-in. Select the tab for the one you'd like to use and then follow the instructions to create your add-in and test it locally. If you'd like to create the add-in project within Visual Studio Code, we recommend the Office Add-ins Development Kit. +# [Office Add-ins Development Kit](#tab/devkit) + +[!include[Dev_kit prerequisites](../includes/dev-kit-prerequisites.md)] + +## Create the add-in project + +Click the following button to create an add-in project using the Office Add-ins Development Kit for Visual Studio Code. You'll be prompted to install the extension if don't already have it. A page that contains the project description will open in Visual Studio Code. + +> [!div class="nextstepaction"] +> [Create an add-in in Visual Studio Code](vscode://msoffice.microsoft-office-add-in-debugger/open-specific-sample?sample-id=word-get-started-with-dev-kit) + +In the prompted page, select **Create** to create the add-in project. In the **Workspace folder** dialog that opens, select the folder where you want to create the project. + +:::image type="content" source="../images/office-add-ins-development-kit-samplepage-wordquickstart.png" alt-text="The Development Kit sample gallery in Visual Studio Code"::: + +The Office Add-ins Development Kit will create the project. It will then open the project in a *second* Visual Studio Code window. Close the original Visual Studio Code window. + +> [!NOTE] +> If you use VSCode Insiders, or you have problems opening the project page in VSCode, install the extension manually by following [these steps](../develop/development-kit-overview.md?tabs=vscode), and find the sample in the sample gallery. + +[!include[Devkit_project_components_taskpane](../includes/devkit-project-components-taskpane.md)] + +## Try it out + +[!include[Dev_kit_start_debugging](../includes/dev-kit-start-debugging.md)] + +[!include[Dev_kit_stop_debugging](../includes/dev-kit-stop-debugging.md)] + +[!include[Dev_kit_troubleshooting](../includes/dev-kit-troubleshooting.md)] +# [Yeoman generator](#tab/yeoman) ## Prerequisites [!include[Yeoman generator prerequisites](../includes/quickstart-yo-prerequisites.md)] @@ -27,8 +57,6 @@ In this article, you'll walk through the process of building a Word task pane ad After you complete the wizard, the generator creates the project and installs supporting Node components. -[!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - ## Explore the project [!include[Yeoman generator add-in project components](../includes/yo-task-pane-project-components-js.md)] @@ -60,7 +88,7 @@ After you complete the wizard, the generator creates the project and installs su - To test your add-in in Word on a browser, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of a Word document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] 1. In Word, if the "My Office Add-in" task pane isn't already open, open a new document, choose the **Home** tab, and then choose the **Show Taskpane** button on the ribbon to open the add-in task pane. diff --git a/docs/reference/images/visio-api-block-diagram.png b/docs/reference/images/visio-api-block-diagram.png deleted file mode 100644 index f5f824a1cc..0000000000 Binary files a/docs/reference/images/visio-api-block-diagram.png and /dev/null differ diff --git a/docs/reference/javascript-api-for-office.md b/docs/reference/javascript-api-for-office.md index de6020fbcd..e54348bd32 100644 --- a/docs/reference/javascript-api-for-office.md +++ b/docs/reference/javascript-api-for-office.md @@ -1,13 +1,13 @@ --- -layout: LandingPage -ms.topic: landing-page title: Office JavaScript API reference documentation description: Learn about the Office JavaScript APIs. -ms.date: 07/22/2024 +ms.author: lindalu +ms.topic: overview +ms.date: 06/11/2025 ms.localizationpriority: high --- -# API reference documentation +# Office JavaScript API reference documentation An add-in can use the Office JavaScript APIs to interact with objects in Office client applications. @@ -18,109 +18,33 @@ You should use application-specific APIs whenever feasible, and use Common APIs ## API reference -<ul class="panelContent cardsF cols cols3"> - <li> - <div class="cardSize"> - <div class="cardPadding"> - <div class="card"> - <div class="cardImageOuter"> - <div class="cardImage"> - <a href="http://github.com/javascript/api/excel"><img src="http://github.com/images/index/logo-excel.svg" alt="Excel API reference docs" /></a> - </div> - </div> - <div class="cardText"> - <h3>Excel API reference</h3> - <p><a href="http://github.com/javascript/api/excel">JavaScript APIs for building Excel add-ins.</a></p> - </div> - </div> - </div> - </div> - </li> - <li> - <div class="cardSize"> - <div class="cardPadding"> - <div class="card"> - <div class="cardImageOuter"> - <div class="cardImage"> - <a href="http://github.com/javascript/api/outlook"><img src="http://github.com/images/index/logo-outlook.svg" alt="Outlook API reference docs" /></a> - </div> - </div> - <div class="cardText"> - <h3>Outlook API reference</h3> - <p><a href="http://github.com/javascript/api/outlook">JavaScript APIs for building Outlook add-ins.</a></p> - </div> - </div> - </div> - </div> - </li> - <li> - <div class="cardSize"> - <div class="cardPadding"> - <div class="card"> - <div class="cardImageOuter"> - <div class="cardImage"> - <a href="http://github.com/javascript/api/word"><img src="http://github.com/images/index/logo-word.svg" alt="Word API reference docs" /></a> - </div> - </div> - <div class="cardText"> - <h3>Word API reference</h3> - <p><a href="http://github.com/javascript/api/word">JavaScript APIs for building Word add-ins.</a></p> - </div> - </div> - </div> - </div> - </li> - <li> - <div class="cardSize"> - <div class="cardPadding"> - <div class="card"> - <div class="cardImageOuter"> - <div class="cardImage"> - <a href="http://github.com/javascript/api/powerpoint"><img src="http://github.com/images/index/logo-powerpoint.svg" alt="PowerPoint API reference docs" /></a> - </div> - </div> - <div class="cardText"> - <h3>PowerPoint API reference</h3> - <p><a href="http://github.com/javascript/api/powerpoint">JavaScript APIs for building PowerPoint add-ins.</a></p> - </div> - </div> - </div> - </div> - </li> - <li> - <div class="cardSize"> - <div class="cardPadding"> - <div class="card"> - <div class="cardImageOuter"> - <div class="cardImage"> - <a href="http://github.com/javascript/api/onenote"><img src="http://github.com/images/index/logo-onenote.svg" alt="OneNote API reference docs" /></a> - </div> - </div> - <div class="cardText"> - <h3>OneNote API reference</h3> - <p><a href="http://github.com/javascript/api/onenote">JavaScript APIs for building OneNote add-ins.</a></p> - </div> - </div> - </div> - </div> - </li> - <li> - <div class="cardSize"> - <div class="cardPadding"> - <div class="card"> - <div class="cardImageOuter"> - <div class="cardImage"> - <a href="http://github.com/javascript/api/office"><img src="http://github.com/images/index-landing-page/i_code-blocks.svg" alt="reference docs" /></a> - </div> - </div> - <div class="cardText"> - <h3>Common API reference</h3> - <p><a href="http://github.com/javascript/api/office">JavaScript APIs that can be used by any Office Add-in.</a></p> - </div> - </div> - </div> - </div> - </li> -</ul> +:::row::: + :::column span=""::: + :::image type="content" source="../images/m365-app-excel.png" alt-text="Excel API reference" border="false"::: + <br>**Excel API reference**<br>[JavaScript APIs for building Excel add-ins](/javascript/api/excel) + :::column-end::: + :::column span=""::: + :::image type="content" source="../images/m365-app-outlook.png" alt-text="Outlook API reference"::: + <br>**Outlook API reference**<br>[JavaScript APIs for building Outlook add-ins](/javascript/api/outlook) + :::column-end::: + :::column span=""::: + :::image type="content" source="../images/m365-app-word.png" alt-text="Word API reference" border="false"::: + <br>**Word API reference**<br>[JavaScript APIs for building Word add-ins](/javascript/api/word) + :::column-end::: +:::row-end::: +:::row::: + :::column span=""::: + :::image type="content" source="../images/m365-app-powerpoint.png" alt-text="PowerPoint API reference" border="false"::: + <br>**PowerPoint API reference**<br>[JavaScript APIs for building PowerPoint add-ins](/javascript/api/powerpoint) + :::column-end::: + :::column span=""::: + :::image type="content" source="../images/m365-app-onenote.png" alt-text="OneNote API reference" border="false"::: + <br>**OneNote API reference**<br>[JavaScript APIs for building OneNote add-ins](/javascript/api/onenote) + :::column-end::: + :::column span=""::: + :::image type="content" source="../images/m365-app-office.png" alt-text="Common API reference" border="false"::: + <br>**Common API reference**<br>[JavaScript APIs that can be used by any Office Add-in](/javascript/api/office) + :::column-end::: +:::row-end::: -<b>Note</b>: There's currently no application-specific JavaScript API for Project; you'll use Common APIs to create Project add-ins. +**Note**: There's currently no application-specific JavaScript API for Project; you'll use Common APIs to create Project add-ins. diff --git a/docs/reference/overview/onenote-add-ins-javascript-reference.md b/docs/reference/overview/onenote-add-ins-javascript-reference.md index bdedaafb37..1284da8b25 100644 --- a/docs/reference/overview/onenote-add-ins-javascript-reference.md +++ b/docs/reference/overview/onenote-add-ins-javascript-reference.md @@ -1,24 +1,24 @@ --- title: OneNote JavaScript API overview description: Learn more about the OneNote JavaScript API. -ms.date: 07/28/2020 +ms.date: 06/17/2025 ms.service: onenote ms.localizationpriority: high --- # OneNote JavaScript API overview -A OneNote add-in interacts with objects in OneNote on the web by using the Office JavaScript API, which includes two JavaScript object models: +A OneNote add-in interacts with objects in OneNote on the web by using the [Office JavaScript API Library](../../develop/understanding-the-javascript-api-for-office.md), which includes two JavaScript object models: * **OneNote JavaScript API**: These are the [application-specific APIs](../../develop/application-specific-api-model.md) for OneNote. Introduced with Office 2016, the [OneNote JavaScript API](/javascript/api/onenote) provides strongly-typed objects that you can use to access objects in OneNote on the web. * **Common APIs**: Introduced with Office 2013, the [Common API](/javascript/api/office) can be used to access features such as UI, dialogs, and client settings that are common across multiple types of Office applications. -This section of the documentation focuses on the OneNote JavaScript API, which you'll use to develop the majority of functionality in add-ins that target OneNote on the web. For information about the Common API, see [Common JavaScript API object model](../../develop/office-javascript-api-object-model.md). +This section of the documentation focuses on the OneNote JavaScript API, which you'll use to develop most of the functionality in add-ins that target OneNote on the web. For information about the Common API, see [Common JavaScript API object model](../../develop/office-javascript-api-object-model.md). ## Learn programming concepts -See the following articles for information about important programming concepts. +See the following articles for information about important programming concepts related to OneNote extensibility. * [OneNote JavaScript API programming overview](../../onenote/onenote-add-ins-programming-overview.md) * [Work with OneNote page content](../../onenote/onenote-add-ins-page-content.md) diff --git a/docs/reference/overview/powerpoint-add-ins-reference-overview.md b/docs/reference/overview/powerpoint-add-ins-reference-overview.md index f124390ff8..f5fefcbcc0 100644 --- a/docs/reference/overview/powerpoint-add-ins-reference-overview.md +++ b/docs/reference/overview/powerpoint-add-ins-reference-overview.md @@ -1,7 +1,7 @@ --- title: JavaScript API for PowerPoint description: Overview of the PowerPoint JavaScript API. -ms.date: 07/05/2019 +ms.date: 05/29/2025 ms.service: powerpoint ms.localizationpriority: high --- @@ -10,9 +10,9 @@ ms.localizationpriority: high A PowerPoint add-in interacts with objects in PowerPoint by using the Office JavaScript API, which includes two JavaScript object models: -* **PowerPoint JavaScript API**: The [PowerPoint JavaScript API](/javascript/api/powerpoint) provides strongly-typed objects that you can use to access objects in PowerPoint. +- **PowerPoint JavaScript API**: The [PowerPoint JavaScript API](/javascript/api/powerpoint) provides strongly-typed objects that you can use to access objects in PowerPoint. To learn about the asynchronous nature of the PowerPoint JavaScript APIs and how they work with the presentation, see [Using the application-specific API model](../../develop/application-specific-api-model.md). -* **Common APIs**: Introduced with Office 2013, the [Common API](/javascript/api/office) can be used to access features such as UI, dialogs, and client settings that are common across multiple types of Office applications. +- **Common APIs**: The [Common API](/javascript/api/office) can be used to access features such as UI, dialogs, and client settings that are common across multiple Office applications. To learn more about using the Common API, see [Common JavaScript API object model](../../develop/office-javascript-api-object-model.md). ## Learn programming concepts @@ -20,10 +20,10 @@ See [PowerPoint add-ins overview](../../powerpoint/powerpoint-add-ins.md) for in ## Learn about API capabilities -For hands-on experience using the Common API to interact with content in PowerPoint, complete the [PowerPoint add-in tutorial](../../tutorials/powerpoint-tutorial.md). - For detailed information about the PowerPoint JavaScript API object model, see the [PowerPoint JavaScript API reference documentation](/javascript/api/powerpoint). +For hands-on experience interacting with content in PowerPoint, complete the [PowerPoint add-in tutorial](../../tutorials/powerpoint-tutorial-yo.md). + ## Try out code samples in Script Lab Use [Script Lab](../../overview/explore-with-script-lab.md) to get started quickly with a collection of built-in samples that show how to complete tasks with the API. You can run the samples in Script Lab to instantly see the result in the task pane or document, examine the samples to learn how the API works, and even use samples to prototype your own add-in. diff --git a/docs/reference/overview/word-add-ins-reference-overview.md b/docs/reference/overview/word-add-ins-reference-overview.md index eda9b3e624..c9fdbf7b2d 100644 --- a/docs/reference/overview/word-add-ins-reference-overview.md +++ b/docs/reference/overview/word-add-ins-reference-overview.md @@ -1,7 +1,7 @@ --- title: Word JavaScript API overview description: Overview of the Word JavaScript API. -ms.date: 02/24/2023 +ms.date: 05/29/2025 ms.topic: concept-article ms.service: word ms.localizationpriority: high @@ -13,7 +13,7 @@ A Word add-in interacts with objects in Word by using the Office JavaScript API, * **Word JavaScript API**: These are the [application-specific APIs](../../develop/application-specific-api-model.md) for Word. Introduced with Office 2016, the [Word JavaScript API](/javascript/api/word) provides strongly-typed objects that you can use to access objects and metadata in a Word document. -* **Common APIs**: Introduced with Office 2013, the [Common API](/javascript/api/office) can be used to access features such as UI, dialogs, and client settings that are common across multiple types of Office applications. +* **Common APIs**: The [Common API](/javascript/api/office), introduced with Office 2013, can be used to access features such as UI, dialogs, and client settings that are common across multiple Office applications. This section of the documentation focuses on the Word JavaScript API, which you'll use to develop the majority of functionality in add-ins that target Word on the web, or Word 2016 and later. For information about the Common API, see [Common JavaScript API object model](../../develop/office-javascript-api-object-model.md). @@ -23,7 +23,7 @@ See [Word JavaScript object model in Office Add-ins](../../word/word-add-ins-cor ## Learn about API capabilities -Use other articles in this section of the documentation to learn how to [get the whole document from an add-in](../../word/get-the-whole-document-from-an-add-in-for-word.md), [use search options in your Word add-in to find text](../../word/search-option-guidance.md), and more. See the table of contents for the complete list of available articles. +Use other articles in this section of the documentation to learn how to [get the whole document from an add-in](../../develop/get-the-whole-document-from-an-add-in-for-powerpoint-or-word.md), [use search options in your Word add-in to find text](../../word/search-option-guidance.md), and more. See the table of contents for the complete list of available articles. For hands-on experience using the Word JavaScript API to access objects in Word, complete the [Word add-in tutorial](../../tutorials/word-tutorial.md). diff --git a/docs/resources/resources-github-copilot-prompt-library.md b/docs/resources/resources-github-copilot-prompt-library.md index 7ee8c25281..38ac1e21c2 100644 --- a/docs/resources/resources-github-copilot-prompt-library.md +++ b/docs/resources/resources-github-copilot-prompt-library.md @@ -106,7 +106,7 @@ JavaScript API. ### Insert a copy of an existing workbook into the current one ```code -Insert a workbook template as base64 in the current workbook using +Insert a workbook template as Base64 in the current workbook using insertWorksheetsFromBase64 Excel JavaScript API. ``` diff --git a/docs/resources/resources-glossary.md b/docs/resources/resources-glossary.md index 2d7b8a7fa2..f604a7d7b1 100644 --- a/docs/resources/resources-glossary.md +++ b/docs/resources/resources-glossary.md @@ -1,7 +1,7 @@ ---- +--- title: Office Add-ins glossary of terms description: A glossary of terms commonly used throughout the Office Add-ins documentation. -ms.date: 11/30/2023 +ms.date: 02/12/2025 ms.topic: glossary ms.localizationpriority: medium --- @@ -82,18 +82,36 @@ An add-in that contains a custom function, but no UI such as a task pane. The cu See also: [custom function](#custom-function), [custom functions runtime](#custom-functions-runtime). +## function command + +Function commands are buttons or menu items that run JavaScript functions. Unlike task pane commands, function commands don't display any user interface other than the command button or menu item itself. + +See also: [add-in commands](#add-in-commands). + ## host -**\<Host\>** typically refers to an Office application. The Office applications, or hosts, that support Office Add-ins are Excel, OneNote, Outlook, PowerPoint, Project, and Word. +`<Host>` typically refers to an Office application. The Office applications, or hosts, that support Office Add-ins are Excel, OneNote, Outlook, PowerPoint, Project, and Word. See also: [application](#application), [client](#client), [Office application, Office client](#office-application-office-client). +## Long-Term Service Channel (LTSC) + +**LTSC** refers to the perpetual version of Office available through a volume-licensing agreement between Microsoft and your company. + +See also: [perpetual](#perpetual), [volume-licensed, volume-licensed perpetual, volume licensing](#volume-licensed-volume-licensed-perpetual-volume-licensing). + ## Office application, Office client **Office client** refers to an Office application. The Office applications, or clients, that support Office Add-ins are Excel, OneNote, Outlook, PowerPoint, Project, and Word. See also: [application](#application), [client](#client), [host](#host), [Office desktop application, Office desktop client, desktop client, desktop](#office-desktop-application-office-desktop-client-desktop-client-desktop). +## Office cache + +The **Office cache** stores resources and data used by Office Add-ins. This cache prevents an add-in from repeatedly downloding the resources it needs, thereby improving its performance. + +See also: [web cache](#web-cache), [Wef cache](#wef-cache). + ## Office desktop application, Office desktop client, desktop client, desktop **Office desktop client** refers to an Office application that runs natively on Windows or on Mac. The Office desktop clients that support Office Add-ins are Excel on Windows and on Mac, Outlook on Windows ([new](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) and classic) and on Mac, PowerPoint on Windows and on Mac, Project on Windows, and Word on Windows and on Mac. @@ -140,6 +158,12 @@ A **runtime** is the host environment (including a JavaScript engine and usually See also: [custom functions runtime](#custom-functions-runtime), [shared runtime](#shared-runtime), [webview](#webview). +## setless API + +An API in the Office JavaScript Library that is not included in any requirement set. + +See also [requirement set](#requirement-set). + ## shared runtime A **shared runtime**, enables code in your task pane, function commands, and custom functions, to run in the same runtime and continue running even when the task pane is closed. Code in dialogs generally runs in a separate runtime even when the add-in is configured to use a shared runtime. See [shared runtime](../testing/runtimes.md#shared-runtime) and [Tips for using the shared runtime in your Office Add-in](https://devblogs.microsoft.com/microsoft365dev/tips-for-using-the-shared-javascript-runtime-in-your-office-add-in%e2%80%af/) to learn more. @@ -168,7 +192,7 @@ See also: [quick start](#quick-start). Other Microsoft content may use the term **commercial** to represent this concept. -See also: [perpetual](#perpetual). +See also: [Long-Term Service Channel (LTSC)](#long-term-service-channel-ltsc), [perpetual](#perpetual). ## web add-in @@ -176,12 +200,24 @@ See also: [perpetual](#perpetual). See also: [add-in](#add-in). +## web cache + +The **web cache** temporarily stores web-based resources and data used by an individual Office Add-in. + +See also: [Office cache](#office-cache), [Wef cache](#wef-cache). + ## webview A **webview** is an element or view that displays web content inside an application. Content add-ins and task panes both contain embedded web browsers and are examples of webviews in Office Add-ins. See also: [content add-in](#content-add-in), [task pane](#task-pane). +## Wef cache + +The **Wef cache** locally stores resources and data for all installed Office Add-ins. + +See also: [Office cache](#office-cache), [web cache](#web-cache). + ## XLL An **XLL** add-in is an Excel add-in file that provides user-defined functions and has the file extension **.xll**. An XLL file is a type of dynamic link library (DLL) file that can only be opened by Excel. XLL add-in files must be written in C or C++. Custom functions are the modern equivalent of XLL user-defined functions. Custom functions offer support across platforms and are backwards compatible with XLL files. See [Extend custom functions with XLL user-defined functions](/office/dev/add-ins/excel/make-custom-functions-compatible-with-xll-udf) for more information. diff --git a/docs/resources/resources-links-help.md b/docs/resources/resources-links-help.md index 13de9bca5c..d7b4b764b0 100644 --- a/docs/resources/resources-links-help.md +++ b/docs/resources/resources-links-help.md @@ -1,7 +1,7 @@ --- title: Office Add-ins additional resources -description: Useful resources about Office Add-ins. -ms.date: 10/10/2023 +description: Useful resources about developing Office Add-ins. +ms.date: 10/16/2025 ms.localizationpriority: medium --- @@ -11,12 +11,12 @@ These resources provide additional information and support for developing Office ## Product support and service issues -Use **Microsoft 365 Admin Center** or **Azure Admin Center** for any **business-critical issues** that need SLA-based support. +Use **Microsoft 365 Admin Center** or **Azure portal** for any **business-critical issues** that need SLA-based support. | Product support | Contact | |:------------|:------------| | **Microsoft 365 product issues and failures** | If you have a Premier support contract for Microsoft 365, visit the Microsoft 365 Admin Center and use the Support menu to [open a service request](https://admin.microsoft.com/). | -| **Azure help and support** | If you have a paid Azure subscription, visit the Azure Admin Center to [open a ticket](https://ms.portal.azure.com/#blade/Microsoft_Azure_Support/HelpAndSupportBlade/newsupportreq). | +| **Azure help and support** | If you have a paid Azure subscription, visit the Azure portal to [open a ticket](https://ms.portal.azure.com/#blade/Microsoft_Azure_Support/HelpAndSupportBlade/newsupportreq). | | **General questions about Microsoft 365** | If you have general questions about Microsoft 365 or Office, submit your questions on [Microsoft 365 and Office Community](https://answers.microsoft.com).| ## Developer community help @@ -25,11 +25,11 @@ Our community of developers use Stack Overflow, GitHub, and Microsoft Q&A to con ### Developer community forums -Post your questions and help other community members by sharing and responding to Office Add-in Development questions. +Post your questions and help other community members by sharing and responding to Office Add-in development questions. | Developer need | Contact | |:---------------------|:---------------| -| **Office Add-in / Office JavaScript API questions** | <ul> <li> Post API questions to [Stack Overflow](https://stackoverflow.com/questions/tagged/office-js) using the `office-js` tag, and also include the `outlook-web-addins` tag if your question relates to Outlook add-ins. Please note that Stack Overflow has guidelines such as requiring a descriptive title, a complete and concise problem statement, and sufficient details to reproduce your issue. Feature requests or overly broad questions are off-topic; new users should visit the [Stack Overflow Help Center](https://stackoverflow.com/help/how-to-ask) for more details. </li> <li> You can also post questions using the `Office Development` tag on [Microsoft Q&A](https://aka.ms/office-addins-dev-questions).</li></ul> | +| **Office Add-in / Office JavaScript API questions** | <ul> <li> Post API questions to [Stack Overflow](https://stackoverflow.com/questions/tagged/office-js) using the `office-js` tag, and also include the `outlook-web-addins` tag if your question relates to Outlook add-ins. Please note that Stack Overflow has guidelines such as requiring a descriptive title, a complete and concise problem statement, and sufficient details to reproduce your issue. Feature requests or overly broad questions are off-topic; new users should visit the [Stack Overflow Help Center](https://stackoverflow.com/help/how-to-ask) for more details. </li> <li> You can also post questions on [Microsoft Q&A](/answers/) using one of the following tags.<ul> <li>[Microsoft 365 and Office | Development | Office JavaScript API](/answers/tags/255/m365-office-development-routing-javascript-api)</li> <li>[Microsoft 365 and Office | Development | Microsoft 365 Publishing](/answers/tags/367/m365-office-development-routing-m365-publishing)</li> <li>[Microsoft 365 and Office | Development | Microsoft 365 App Publishing](/answers/tags/665/m365-office-development-routing-m365-app-publishing)</li> <li>[Microsoft 365 and Office | Development | Microsoft 365 Developer Program](/answers/tags/666/m365-office-development-routing-m365-developer-program)</li> <li>[Microsoft 365 and Office | Development | Other](/answers/tags/321/m365-office-development-routing-development-other)</li> </ul> </li></ul> | | **Documentation gaps** | If the documentation is missing something that would help you understand how to create add-ins, please submit an issue to the [Office Add-ins documentation GitHub repository](https://github.com/officedev/office-js-docs-pr/issues)| ### Report issues @@ -66,7 +66,7 @@ The following books and classes provide add-ins information from a different per |Resource|More information| |-----------------|------------| -|**Pluralsight course about Office Add-ins**| [John Brown's course "Fundamentals of Building Office Add-ins with Office JavaScript APIs"](https://www.pluralsight.com/courses/build-office-addins-js-api) teaches you how to develop a PowerPoint add-in from scratch, including information about how to communicate with Trello and publish the add-in to AppSource.| +|**Pluralsight course about Office Add-ins**| [John Brown's course "Fundamentals of Building Office Add-ins with Office JavaScript APIs"](https://www.pluralsight.com/courses/build-office-addins-js-api) teaches you how to develop a PowerPoint add-in from scratch, including information about how to communicate with Trello and publish the add-in to Microsoft Marketplace.| |**LinkedIn course about Office Add-ins**| [Bill Ayer's course "Microsoft Office Add-Ins for Developers"](https://www.linkedin.com/learning/microsoft-office-add-ins-for-developers/microsoft-office-add-ins?u=3322) gives an overview of the platform and explains many of the major concepts of Office Add-ins.| |***Building Office Add-ins using Office.js* book**| [Michael Zlatkovsky's book *Building Office Add-ins using Office.js*](https://leanpub.com/buildingofficeaddins) describes the principles and design patterns shared by the 2016 APIs for Excel, Word, and OneNote. At the time of writing, Michael was a member of the Office Extensibility team at Microsoft, but this book is independently authored without input from Microsoft. Neither Microsoft nor Michael collect any profit on this book, as proceeds are donated to disaster-relief and humanitarian charitable causes.| diff --git a/docs/resources/resources-office-add-in-known-issues.md b/docs/resources/resources-office-add-in-known-issues.md new file mode 100644 index 0000000000..893d661dab --- /dev/null +++ b/docs/resources/resources-office-add-in-known-issues.md @@ -0,0 +1,114 @@ +--- +title: Office Add-ins known issues +description: This article documents active and resolved issues with Office Add-ins. +ms.date: 10/01/2025 +ms.localizationpriority: medium +--- + +# Office Add-ins known issues + +_Last updated October 1st, 2025_ + +This article provides information about current known issues with Office Add-ins. For more information about common error messages you might encounter, see [Troubleshoot user errors with Office Add-ins](/office/dev/add-ins/testing/testing-and-troubleshooting) or contact the add-in developer on the **Details + support** tab on the add-in's detail page in [Microsoft Marketplace](https://marketplace.microsoft.com). + +## Active issues in Office Add-ins + +### Outlook: Delays loading inline images in email signatures in the new Outlook for Windows and Outlook for the web + +We're currently investigating reports from Outlook users who are experiencing loading delays of inline images in email signatures when using the new Outlook for Windows and Outlook for the web. Our findings indicate that this is a server-side performance issue that affects rendering of all inline images. Attempting to send messages while the images are not yet loaded results in the following dialog box. + +![Outlook images still loading error message.](../images/outlook-images-still-loading-error.png) + +Tracking ID: 678890927 + +Client version: 20250822005.18 + +#### STATUS + +We're still receiving isolated reports from some users regarding this previously resolved issue. While the issue has been largely mitigated, certain users in specific regions are still experiencing inline signature images loading slowly and the blocking dialog during email send. Because this stems from a server-side performance delay, the impact varies by customer and region. Those affected may see delays when loading inline images—particularly in scenarios involving signature add-ins. We're actively investigating this issue with highest priority. + +#### WORKAROUND + +Options: + +1. Remove inline images from signature. +1. Wait for images to load before sending the file. +1. Switch to classic Outlook for Windows or Outlook for Mac. + +### Centrally deployed add-in error "You don't have permission to use this add-in" + +Numerous customers report that after updating Office from 2505 to 2507 their add-in will not load and an error is displayed "You don't have permission to use this add-in. Contact your system administrator." Any add-in may reproduce this issue; it is not specific to a single add-in. + + ![Excel web add-in permissions error message.](../images/excel-web-add-in-permission-error.png) + +Tracking ID: 667052546 + +Version affected: Office Monthly Enterprise 2507 + +#### STATUS + +A fix is being deployed. + +| Channel | Release timeline | +| --- | --- | +| Insiders | Available as of September 30th, 2025 | +| Current Channel | Available to install on October 7th, 2025 | +| Monthly Enterprise Channel | Available to install on October Patch Tuesday, October 14th, 2025 | + +#### WORKAROUND + +**Option 1: Refresh admin-managed add-ins** + +1. Select **Home** > **Add-ins** in the ribbon. +1. Select **More add-ins**. +1. Go to the **Admin Managed** tab. +1. Select the **Refresh** button in top right. +1. The add-in should reappear. Open it to reload the add-in. + +**Option 2: Forced admin refresh** + +IT admins can force the add-ins to refresh by creating the following registry key. + +Key: `HKCU\Software\Microsoft\Office\16.0\WEF\TrustedCatalogs\ClearInstalledExtensions` +Value: `DWORD = 1` + +### Excel: Increased frequency of RichApi.Error: Error code: 0xF5320001 + +Date reported: 09/04/2025 + +Since late August, customers are seeing an increase in `RichApi.Error 0xF532001` in their error telemetry. This error happens only when the `Office.ribbon.requestUpdate` API is called immediately after the `Office.ribbon.requestCreateControls` API is called. + +Tracking ID: 10529994 + +GitHub issue: [Increased frequency of RichApi.Error code 0xF5320001](https://github.com/OfficeDev/office-js/issues/6072) + +#### STATUS + +We're currently working on a fix. + +#### WORKAROUND + +Options: + +1. When you make the initial `requestCreateControls` call, include the enabled/disabled state, if known. Instead of making two calls one right after the other, do it in one call. +1. Roll back Office from version 2508 to 2507. + +## Recently resolved issues in Office Add-ins + +### Excel: RichApi.Error code 0x8002802B known as hrNotFound is occurring more frequently when not expected + +Date reported: 09/17/2025 + +Users might experience failures when executing Excel grid operations initiated through add-in commands on the ribbon or context menu. This issue occurs primarily when users have Custom Functions. + +Platform affected: Windows Desktop + +#### STATUS + +Date fixed: 09/26/2025 + +Users should upgrade Excel to 2508 (19127.20264) or later for the fix. + +### See also + +- For more information about resolved issues in Office Add-ins, see the [Office-js closed issues in GitHub](https://github.com/OfficeDev/office-js/issues?q=is%3Aissue%20state%3Aclosed). diff --git a/docs/testing/application-specific-api-error-handling.md b/docs/testing/application-specific-api-error-handling.md index e67d371336..1fa3b6fe72 100644 --- a/docs/testing/application-specific-api-error-handling.md +++ b/docs/testing/application-specific-api-error-handling.md @@ -2,7 +2,7 @@ title: Error handling with the application-specific JavaScript APIs description: Learn about Excel, Word, PowerPoint, and other application-specific JavaScript API error handling logic to account for runtime errors. ms.topic: error-reference -ms.date: 03/01/2024 +ms.date: 06/23/2025 ms.localizationpriority: medium --- @@ -62,7 +62,7 @@ The following tables list the errors that application-specific APIs may return. |Error code | Error message | Notes | |:----------|:--------------|:------| -|`AccessDenied` |You cannot perform the requested operation.|*None* | +|`AccessDenied` |You cannot perform the requested operation.| This may be caused by a user's antivirus software blocking parts of Office. See the [Common errors and troubleshooting steps](../testing/testing-and-troubleshooting.md#common-errors-and-troubleshooting-steps) for "Error: Access denied" for more guidance. | |`ActivityLimitReached`|Activity limit has been reached.|*None* | |`ApiNotAvailable`|The requested API is not available.|*None* | |`ApiNotFound`|The API you are trying to use could not be found. It may be available in a newer version of the Office application. See [Office client application and platform availability for Office Add-ins](/javascript/api/requirement-sets) for more information.|*None* | @@ -100,13 +100,14 @@ The following tables list the errors that application-specific APIs may return. |`FormulaLengthExceedsLimit`|The bytecode of the applied formula exceeds the maximum length limit. For Office on 32-bit machines, the bytecode length limit is 16384 characters. On 64-bit machines, the bytecode length limit is 32768 characters.| This error occurs in both Excel on the web and on desktop.| |`GeneralException`|*Various.*|The data types APIs return `GeneralException` errors with dynamic error messages. These messages reference the cell that is the source of the error, and the problem that is causing the error, such as: "Cell A1 is missing the required property `type`."| |`InactiveWorkbook`|The operation failed because multiple workbooks are open and the workbook being called by this API has lost focus.|*None* | -|`InvalidOperationInCellEditMode`|The operation isn't available while Excel is in Edit cell mode. Exit Edit mode by using the **Enter** or **Tab** keys, or by selecting another cell, and then try again.|*None* | +|`InvalidOperationInCellEditMode`|The operation isn't available while Excel is in Edit cell mode. Exit Edit mode by using the <kbd>Enter</kbd> or <kbd>Tab</kbd> keys, or by selecting another cell, and then try again.|*None* | |`MergedRangeConflict`|Cannot complete the operation. A table can't overlap with another table, a PivotTable report, query results, merged cells, or an XML Map.|*None* | |`NonBlankCellOffSheet`|Microsoft Excel can't insert new cells because it would push non-empty cells off the end of the worksheet. These non-empty cells might appear empty but have blank values, some formatting, or a formula. Delete enough rows or columns to make room for what you want to insert and then try again.|*None* | |`OperationCellsExceedLimit`|The attempted operation affects more than the limit of 33554000 cells.| If the `TableColumnCollection.add API` triggers this error, confirm that there is no unintentional data within the worksheet but outside of the table. In particular, check for data in the right-most columns of the worksheet. Remove the unintended data to resolve this error. One way to verify how many cells that an operation processes is to run the following calculation: `(number of table rows) x (16383 - (number of table columns))`. The number 16383 is the maximum number of columns that Excel supports. <br><br>This error only occurs in Excel on the web. | |`PivotTableRangeConflict`|The attempted operation causes a conflict with a PivotTable range.|*None* | |`RangeExceedsLimit`|The cell count in the range has exceeded the maximum supported number. See the [Resource limits and performance optimization for Office Add-ins](../concepts/resource-limits-and-performance-optimization.md#excel-add-ins) article for more information.|*None* | |`RefreshWorkbookLinksBlocked`|The operation failed because the user hasn't granted permission to refresh external workbook links.|*None* | +|`UndoNotSupported`|The JavaScript API request failed due to lack of support for the undo operation.|*None* | |`UnsupportedSheet`|This sheet type does not support this operation, since it is a Macro or Chart sheet.|*None* | ### Word-specific error codes and messages diff --git a/docs/testing/clear-cache.md b/docs/testing/clear-cache.md index f71c43f548..0dcec4317d 100644 --- a/docs/testing/clear-cache.md +++ b/docs/testing/clear-cache.md @@ -1,36 +1,65 @@ --- title: Clear the Office cache description: Learn how to clear the Office cache on your computer. -ms.date: 09/09/2024 +ms.date: 06/25/2025 ms.localizationpriority: high --- # Clear the Office cache -To remove an add-in that you've previously sideloaded on Windows, Mac, or iOS, you need to clear the Office cache on your computer. +The Office cache stores resources and data used by Office Add-ins. By accessing stored resources, an add-in's performance is improved as it avoids redownloading these resources when needed. -Additionally, if you make changes to your add-in's manifest (for example, update file names of icons or text of add-in commands), you should clear the Office cache and then re-sideload the add-in using an updated manifest. Doing so allows Office to render the add-in as it's described by the updated manifest. +You should clear the Office cache in the following scenarios. + +- When you want to remove an add-in that you've previously sideloaded on Windows, Mac, or iOS. +- When you've updated the manifest (for example, to update the file names of icons or text of add-in commands). This ensures that you're using the latest version of the add-in. + > [!TIP] + > For add-ins that implement a task pane, if you only want the sideloaded add-in to reflect recent changes to its HTML or JavaScript source files, you shouldn't need to clear the cache. Instead, put focus in the add-in's task pane (by selecting anywhere within the task pane). Then, select <kbd>Ctrl</kbd>+<kbd>F5</kbd> to reload the add-in. +- When you want to resolve issues or errors when running the add-in. > [!NOTE] > To remove a sideloaded add-in from Excel, OneNote, PowerPoint, or Word on the web, see [Sideload Office Add-ins in Office on the web for testing: Remove a sideloaded add-in](sideload-office-add-ins-for-testing.md#remove-a-sideloaded-add-in). +> +> To remove a sideloaded add-in from Outlook on the web, see [Sideload Outlook add-ins for testing](../outlook/sideload-outlook-add-ins-for-testing.md#remove-a-sideloaded-add-in). + +> [!CAUTION] +> When you clear the Office cache, clear it completely. Don't delete individual manifest files. This can cause all add-ins to stop loading. + +## Types of caches + +The Office cache can refer to either the web cache or the Wef cache. + +- The **web cache** temporarily stores web-based resources and data used by an individual Office Add-in. +- The **Wef cache** locally stores resources and data for all installed Office Add-ins. + +The following table outlines which Office cache types can be cleared on different platforms. It also provides links to instructions on how to clear a specific cache. + +| Platform | Types of caches to clear | Options to clear the cache | +| ----- | ----- | ----- | +| Windows | Both the web and Wef caches. There's currently no option to clear one cache without clearing the other. | <ul><li>[Automatically clear the cache](#automatically-clear-the-cache)</li><li>[Manually clear the cache](#manually-clear-the-cache)</li><li>[Use the Microsoft Edge developer tools on Windows 10](#use-the-microsoft-edge-developer-tools-on-windows-10)</li></ul> | +| Mac | <ul><li>Web</li><li>Both web and Wef caches</li></ul> | <ul><li>**Web**: [Use the personality menu to clear the web cache](#clear-the-web-cache)</li><li>**Web and Wef**: [Clear the web and Wef caches on Mac](#clear-the-web-and-wef-caches)</li></ul> | +| iOS | <ul><li>Web</li></ul> | <ul><li>[Use JavaScript to clear the cache on iOS](#clear-the-office-cache-on-ios)</li></ul> | ## Clear the Office cache on Windows -There are three ways to clear the Office cache on a Windows computer: automatically, manually, and using the Microsoft Edge developer tools. The methods are described in the following subsections. +Depending on your Office host and operating system, you can automatically or manually clear both the web and Wef caches on a Windows computer. -### Automatically +> [!IMPORTANT] +> On Windows, the automatic and manual options clear both the web and Wef caches. There's currently no option to clear one cache without clearing the other. -This method is recommended for add-in development computers. If your Office on Windows version is 2108 or later, the following steps configure the Office cache to be cleared the next time Office is reopened. +### Automatically clear the cache > [!NOTE] -> The automatic method is not supported for Outlook. +> The automatic option is only supported for Excel, PowerPoint, and Word. Outlook only supports the [manual option](#manually-clear-the-cache-in-outlook). -1. From the ribbon of any Office host except Outlook, navigate to **File** > **Options** > **Trust Center** > **Trust Center Settings** > **Trusted Add-in Catalogs**. -1. Select the checkbox **Next time Office starts, clear all previously-started web add-ins cache**. +This method is recommended for add-in development computers. If your Office on Windows version is 2108 or later, the following steps configure the Office cache to be cleared the next time Office is reopened. -### Manually +1. From the ribbon of Excel, PowerPoint, or Word, navigate to **File** > **Options** > **Trust Center** > **Trust Center Settings** > **Trusted Add-in Catalogs**. +1. Select the **Next time Office starts, clear all previously-started web add-ins cache** checkbox. +1. Select **OK**. +1. Restart Excel, PowerPoint, or Word. -The manual method for Excel, Word, and PowerPoint is different from Outlook. +### Manually clear the cache #### Manually clear the cache in Excel, Word, and PowerPoint @@ -40,7 +69,7 @@ To remove all sideloaded add-ins from Excel, Word, and PowerPoint, delete the co %LOCALAPPDATA%\Microsoft\Office\16.0\Wef\ ``` -If the following folder exists, delete its contents too. +If the following folder exists, delete its contents, too. ``` %userprofile%\AppData\Local\Packages\Microsoft.Win32WebViewHost_cw5n1h2txyewy\AC\#!123\INetCache\ @@ -48,7 +77,7 @@ If the following folder exists, delete its contents too. #### Manually clear the cache in Outlook -To remove a sideloaded add-in from Outlook, use the steps outlined in [Sideload Outlook add-ins for testing](../outlook/sideload-outlook-add-ins-for-testing.md) to find the add-in in the **Custom add-ins** section of the dialog box that lists your installed add-ins. Choose the ellipsis (`...`) for the add-in and then choose **Remove** to remove that specific add-in. +Before attempting to clear the cache in Outlook, first try to remove the sideloaded add-in using the steps outlined in [Sideload Outlook add-ins for testing](../outlook/sideload-outlook-add-ins-for-testing.md#remove-a-sideloaded-add-in). If this add-in removal doesn't work, then delete the contents of the `Wef` folder as noted for Excel, Word, and PowerPoint in [Manually clear the cache in Excel, Word, and PowerPoint](#manually-clear-the-cache-in-excel-word-and-powerpoint). @@ -71,17 +100,14 @@ To clear the cache in [new Outlook on Windows](https://support.microsoft.com/off 1. In the Microsoft Edge DevTools window, select the **Network** tab. 1. Select and hold (or right-click) anywhere in the **Requests** table. Then, select **Clear browser cache**. -### Using the Microsoft Edge developer tools - -To clear the Office cache on Windows 10 when the add-in is running in Microsoft Edge, you can use the Microsoft Edge DevTools. +### Use the Microsoft Edge developer tools on Windows 10 -> [!TIP] -> If you only want the sideloaded add-in to reflect recent changes to its HTML or JavaScript source files, you shouldn't need to clear the cache. Instead, just put focus in the add-in's task pane (by clicking anywhere within the task pane) and then press **Ctrl+F5** to reload the add-in. +To clear the Office cache on Windows 10 when the add-in is running in Microsoft Edge, use the Microsoft Edge DevTools. > [!NOTE] > To clear the Office cache using the following steps, your add-in must have a task pane. If your add-in is a UI-less add-in -- for example, one that uses the [on-send](../outlook/outlook-on-send-addins.md) feature -- you'll need to add a task pane to your add-in that uses the same domain for [SourceLocation](/javascript/api/manifest/sourcelocation), before you can use the following steps to clear the cache. -1. Install the [Microsoft Edge DevTools](https://www.microsoft.com/p/microsoft-edge-devtools-preview/9mzbfrmz0mnj). +1. Install the [Microsoft Edge DevTools](https://apps.microsoft.com/detail/9mzbfrmz0mnj). 2. Open your add-in in the Office client. @@ -101,11 +127,43 @@ To clear the Office cache on Windows 10 when the add-in is running in Microsoft ## Clear the Office cache on Mac -[!include[additional cache folders on Mac](../includes/mac-cache-folders.md)] +You can choose to clear the web or both the web and Wef caches on Mac. + +### Clear the web cache + +Normally, the web cache is cleared by reloading the add-in. If more than one add-in exists in the same document, the process of automatically clearing the cache on reload might not be reliable. + +To clear the web cache in Excel, PowerPoint, and Word, use the personality menu of any task pane add-in. + +> [!NOTE] +> +> - The personality menu in task panes is only supported in Excel, PowerPoint, and Word. Because it isn't supported in Outlook, you must use the [option to clear both the web and Wef caches instead](#clear-the-web-and-wef-caches). +> - The personality menu is only shown in macOS Version 10.13.6 or later. + +From the add-in's task pane, choose the personality menu. Then, choose **Clear Web Cache**. + +![The "Clear web cache" option on the personality menu of an add-in's task pane.](../images/mac-clear-cache-menu.png) + +### Clear the web and Wef caches + +To clear both the web and Wef caches on Mac, delete the contents of the `~/Library/Containers/com.Microsoft.OsfWebHost/Data/` and `~/Library/Containers/com.microsoft.{host}/Data/Documents/wef` folders. Replace `{host}` with the Office application, such as `Excel`. + +> [!TIP] +> Use the terminal or Finder to search for the specified folders. To look for these folders via Finder, you must set Finder to show hidden files. Finder displays the folders inside the **Containers** directory by product name, such as **Microsoft Excel** instead of **com.microsoft.Excel**. + +Deleting the contents of the `~/Library/Containers/com.microsoft.{host}/Data/Documents/wef` folder removes all sideloaded add-ins from an application. + +> [!NOTE] +> If the `~/Library/Containers/com.Microsoft.OsfWebHost/Data/` folder doesn't exist, check for the following folders via terminal or Finder. If found, delete the contents of each folder. +> +> - `~/Library/Containers/com.microsoft.{host}/Data/Library/Caches/` where `{host}` is the Office application (e.g., `Excel`) +> - `~/Library/Containers/com.microsoft.{host}/Data/Library/Application Support/Microsoft/Office/16.0/Wef/` where `{host}` is the Office application (e.g., `Excel`) +> - `~/Library/Containers/com.microsoft.Office365ServiceV2/Data/Caches/com.microsoft.Office365ServiceV2/` +> - `~/Library/Containers/com.microsoft.Office365ServiceV2/Data/Library/Caches/com.microsoft.Office365ServiceV2/` ## Clear the Office cache on iOS -To clear the Office cache on iOS, call `window.location.reload(true)` from JavaScript in the add-in to force a reload. Alternatively, reinstall Office. +To clear the web cache on iOS, call `window.location.reload(true)` from JavaScript in the add-in. This forces the add-in to reload. Alternatively, reinstall Office. ## See also @@ -117,3 +175,4 @@ To clear the Office cache on iOS, call `window.location.reload(true)` from JavaS - [Sideload Office Add-ins for testing](sideload-office-add-ins-for-testing.md) - [Office Add-ins manifest](../develop/add-in-manifests.md) - [Validate an Office Add-in's manifest](troubleshoot-manifest.md) +- [Uninstall add-ins under development](uninstall-add-in.md) diff --git a/docs/testing/create-a-network-shared-folder-catalog-for-task-pane-and-content-add-ins.md b/docs/testing/create-a-network-shared-folder-catalog-for-task-pane-and-content-add-ins.md index 7faba749c3..9fcf682519 100644 --- a/docs/testing/create-a-network-shared-folder-catalog-for-task-pane-and-content-add-ins.md +++ b/docs/testing/create-a-network-shared-folder-catalog-for-task-pane-and-content-add-ins.md @@ -1,7 +1,7 @@ ---- +--- title: Sideload Office Add-ins for testing from a network share description: Learn how to sideload an Office Add-in for testing from a network share. -ms.date: 07/14/2024 +ms.date: 05/21/2025 ms.localizationpriority: medium --- @@ -117,7 +117,7 @@ There are two options for how you specify this trust. Follow the instructions fo ## Sideload your add-in -1. Put the manifest XML file of any add-in that you're testing into the shared folder catalog. Note that you deploy the web application itself to a web server. Be sure to specify the URL in the **\<SourceLocation\>** element of the manifest file. +1. Put the manifest XML file of any add-in that you're testing into the shared folder catalog. Note that you deploy the web application itself to a web server. Be sure to specify the URL in the `<SourceLocation>` element of the manifest file. > [!IMPORTANT] > [!include[HTTPS guidance](../includes/https-guidance.md)] @@ -125,7 +125,7 @@ There are two options for how you specify this trust. Follow the instructions fo > [!NOTE] > For Visual Studio projects, use the manifest built by the project in the `{projectfolder}\bin\Debug\OfficeAppManifests` folder. -1. In Excel, Word, or PowerPoint, select **Home** > **Add-ins** from the ribbon, then select **More Add-ins**. In Project, select **My Add-ins** on the **Project** tab of the ribbon. +1. In Excel, Word, or PowerPoint, select **Home** > **Add-ins** from the ribbon, then select **Advanced**. In Project, select **My Add-ins** on the **Project** tab of the ribbon. 1. Choose **SHARED FOLDER** at the top of the **Office Add-ins** dialog box. diff --git a/docs/testing/debug-add-ins-in-office-online.md b/docs/testing/debug-add-ins-in-office-online.md index daa8d86eba..fea399adeb 100644 --- a/docs/testing/debug-add-ins-in-office-online.md +++ b/docs/testing/debug-add-ins-in-office-online.md @@ -20,7 +20,7 @@ To debug your add-in by using Office on the web: 1. Run the project on localhost and sideload it to a document in Office on the web. For detailed sideloading instructions, see [Manually sideload Office Add-ins on the web](sideload-office-add-ins-for-testing.md#manually-sideload-an-add-in-to-office-on-the-web). -1. Open the browser's developer tools. This is usually done by pressing F12. Open the debugger tool and use it to set breakpoints and watch variables. For detailed help in using your browser's tool, see one of the following: +1. Open the browser's developer tools. This is usually done by pressing <kbd>F12</kbd>. Open the debugger tool and use it to set breakpoints and watch variables. For detailed help in using your browser's tool, see one of the following: - [Firefox](https://firefox-source-docs.mozilla.org/devtools-user/index.html) - [Safari](https://support.apple.com/guide/safari/use-the-developer-tools-in-the-develop-menu-sfri20948/mac) @@ -29,7 +29,7 @@ To debug your add-in by using Office on the web: > [!NOTE] > - Office on the web won't open in Internet Explorer. - > - The new Outlook on Window desktop client (preview) doesn't support the context menu or the keyboard shortcut to access the Microsoft Edge developer tools. Instead, you must run `olk.exe --devtools` from a command prompt. For more information, see the "Debug your add-in" section of [Develop Outlook add-ins for the new Outlook on Windows](../outlook/one-outlook.md#debug-your-add-in). + > - The new Outlook on Windows desktop client doesn't support the context menu or the keyboard shortcut to access the Microsoft Edge developer tools. Instead, you must run `olk.exe --devtools` from a command prompt. For more information, see the "Debug your add-in" section of [Develop Outlook add-ins for the new Outlook on Windows](../outlook/one-outlook.md#debug-your-add-in). ## Potential issues diff --git a/docs/testing/debug-add-ins-overview.md b/docs/testing/debug-add-ins-overview.md index 4a30cc6869..4c53091a2d 100644 --- a/docs/testing/debug-add-ins-overview.md +++ b/docs/testing/debug-add-ins-overview.md @@ -2,7 +2,7 @@ title: Debug Office Add-ins description: Find the Office Add-in debugging guidance for your development environment. ms.topic: overview -ms.date: 12/21/2023 +ms.date: 03/20/2025 ms.localizationpriority: high --- @@ -37,8 +37,8 @@ There are some special cases in which the debugging process differs from normal - **Debugging a [function command](../design/add-in-commands.md#types-of-add-in-commands) in a *non-shared* runtime**: - Outlook add-ins on a Windows development computer: [Debug function commands in Outlook add-ins](../outlook/debug-ui-less.md) - Other Office application add-ins or Outlook on a Mac development computer: [Debug a function command with a non-shared runtime](debug-function-command.md). -- **Debugging an event-based or spam-reporting Outlook add-in**: [Debug event-based and spam-reporting add-ins](../outlook/debug-autolaunch.md). -- **Debugging an add-in in the new Outlook on Windows desktop client (preview)**: See the "Debug your add-in" section of [Develop Outlook add-ins for the new Outlook on Windows](../outlook/one-outlook.md#debug-your-add-in). +- **Debugging an event-based or spam-reporting add-in**: [Debug event-based and spam-reporting add-ins](debug-autolaunch.md). +- **Debugging an add-in in the new Outlook on Windows desktop client**: See the "Debug your add-in" section of [Develop Outlook add-ins for the new Outlook on Windows](../outlook/one-outlook.md#debug-your-add-in). - **Debugging a Blazor-based add-in**: Debug the add-in the same way you would debug a Blazor web application. See [Debug ASP.NET Core Blazor WebAssembly](/aspnet/core/blazor/debug/). ## General guidance @@ -80,6 +80,15 @@ There is no desktop version of Office for Linux, so you'll need to [sideload the To debug an add-in that is already in staging or production, attach a debugger from the UI of the add-in. For instructions, see [Attach a debugger from the task pane](attach-debugger-from-task-pane.md). +## Versions of office.js for debugging + +There are debug versions of the Office JavaScript libraries. These versions are more human readable and easier to step through with a debugger. Use them when the Office JavaScript APIs aren't working as expected. Avoid using them when you publish and deploy your add-in. + +The debug versions are found at the following CDN locations. + +- Office JavaScript API library: `https://appsforoffice.microsoft.com/lib/1/hosted/office.debug.js` +- Office JavaScript API (preview) library: `https://appsforoffice.microsoft.com/lib/beta/hosted/office.debug.js` + ## See also - [Runtimes in Office Add-ins](runtimes.md) diff --git a/docs/testing/debug-add-ins-using-devtools-edge-chromium.md b/docs/testing/debug-add-ins-using-devtools-edge-chromium.md index f3c00ce7cb..9a2e56ceb0 100644 --- a/docs/testing/debug-add-ins-using-devtools-edge-chromium.md +++ b/docs/testing/debug-add-ins-using-devtools-edge-chromium.md @@ -1,7 +1,7 @@ --- title: Debug add-ins using developer tools for Microsoft Edge WebView2 description: Debug add-ins using the developer tools in Microsoft Edge WebView2 (Chromium-based). -ms.date: 07/14/2024 +ms.date: 09/18/2025 ms.localizationpriority: medium --- @@ -32,11 +32,11 @@ To determine which webview you're using, see [Browsers and webview controls used 1. Run the Microsoft Edge (Chromium-based) developer tools by one of these methods: - - Be sure the add-in's task pane has focus and press **Ctrl+Shift+I**. + - Be sure the add-in's task pane has focus and press <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>I</kbd>. - Right-click (or select and hold) the task pane to open the context menu and select **Inspect**, or open the [personality menu](../design/task-pane-add-ins.md#personality-menu) and select **Attach Debugger**. (The personality menu isn't supported in Outlook.) > [!NOTE] - > The new Outlook on Window desktop client (preview) doesn't support the context menu or the keyboard shortcut to access the Microsoft Edge developer tools. Instead, you must run `olk.exe --devtools` from a command prompt. For more information, see the "Debug your add-in" section of [Develop Outlook add-ins for the new Outlook on Windows](../outlook/one-outlook.md#debug-your-add-in). + > The new Outlook on Windows desktop client doesn't support the context menu or the keyboard shortcut to access the Microsoft Edge developer tools. Instead, you must run `olk.exe --devtools` from a command prompt. For more information, see the "Debug your add-in" section of [Develop Outlook add-ins for the new Outlook on Windows](../outlook/one-outlook.md#debug-your-add-in). 1. Open the **Sources** tab. 1. Open the file that you want to debug with the following steps. @@ -62,7 +62,13 @@ If your add-in uses the Office Dialog API, the dialog runs in a separate process 1. Open the dialog and be sure it has focus. 1. Open the Microsoft Edge (Chromium-based) developer tools by one of these methods: - - Press **Ctrl+Shift+I** or **F12**. + - Press <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>I</kbd> or <kbd>F12</kbd>. - Right-click (or select and hold) the dialog to open the context menu and select **Inspect**. 1. Use the tool the same as you would for code in a task pane. See [Debug a task pane add-in using Microsoft Edge (Chromium-based) developer tools](#debug-a-task-pane-add-in-using-microsoft-edge-chromium-based-developer-tools) earlier in this article. + +## Automatically open the Microsoft Edge (Chromium-based) developer tools to debug initialization + +[!INCLUDE[Automatically open the Microsoft Edge (Chromium-based) developer tools to debug initialization](../includes/auto-open-webview2-dev-tools.md)] + + diff --git a/docs/testing/debug-add-ins-using-devtools-edge-legacy.md b/docs/testing/debug-add-ins-using-devtools-edge-legacy.md index 2e39efd86f..1e6b4b17e4 100644 --- a/docs/testing/debug-add-ins-using-devtools-edge-legacy.md +++ b/docs/testing/debug-add-ins-using-devtools-edge-legacy.md @@ -1,7 +1,7 @@ --- title: Debug add-ins using developer tools for Microsoft Edge Legacy description: Debug add-ins using the developer tools in Microsoft Edge Legacy. -ms.date: 07/14/2024 +ms.date: 06/17/2025 ms.localizationpriority: medium --- @@ -19,14 +19,14 @@ To determine which browser or webview you're using, see [Browsers and webview co ## Debug a task pane add-in using Microsoft Edge DevTools Preview -1. Install the [Microsoft Edge DevTools Preview](https://www.microsoft.com/p/microsoft-edge-devtools-preview/9mzbfrmz0mnj?activetab=pivot%3Aoverviewtab). (The word "Preview" is in the name for historical reasons. There isn't a more recent version.) +1. Install the [Microsoft Edge DevTools Preview](https://apps.microsoft.com/detail/9mzbfrmz0mnj). (The word "Preview" is in the name for historical reasons. There isn't a more recent version.) > [!NOTE] > If your add-in has an [add-in command](../design/add-in-commands.md) that executes a function, the function runs in a hidden browser runtime process that the Microsoft Edge DevTools cannot detect or attach to, so the technique described in this article cannot be used to debug code in the function. 1. [Sideload](test-debug-non-local-server.md) and run the add-in. 1. Run the Microsoft Edge DevTools. -1. In the tools, open the **Local** tab. Your add-in will be listed by its name. (Only processes that are running in EdgeHTML appear on the tab. The tool can't attach to processes that are running in other browsers or webviews, including Microsoft Edge (WebView2) and Internet Explorer (Trident).) +1. In the tools, open the **Local** tab. Your add-in is listed by its name. (Only processes that are running in EdgeHTML appear on the tab. The tool can't attach to processes that are running in other browsers or webviews, including Microsoft Edge (WebView2) and Internet Explorer (Trident).) :::image type="content" source="../images/edge-devtools-with-add-in-process.png" alt-text="Edge DevTools showing a process named legacy-edge-debugging."::: @@ -34,7 +34,7 @@ To determine which browser or webview you're using, see [Browsers and webview co 1. Open the **Debugger** tab. 1. Open the file that you want to debug with the following steps. - 1. On the debugger task bar, select **Show find in files**. This will open a search window. + 1. On the debugger task bar, select **Show find in files**. This action opens a search window. 1. Enter a line of code from the file you want to debug in the search box. It should be something that's not likely to be in any other file. 1. Select the refresh button. 1. In the search results, select the line to open the code file in the pane above the search results. diff --git a/docs/testing/debug-add-ins-using-f12-tools-ie.md b/docs/testing/debug-add-ins-using-f12-tools-ie.md index 78912c555c..092f4e276b 100644 --- a/docs/testing/debug-add-ins-using-f12-tools-ie.md +++ b/docs/testing/debug-add-ins-using-f12-tools-ie.md @@ -1,7 +1,7 @@ ---- +--- title: Debug add-ins using developer tools for Internet Explorer description: Debug add-ins using the developer tools in Internet Explorer. -ms.date: 07/14/2024 +ms.date: 12/26/2024 ms.localizationpriority: medium --- @@ -22,7 +22,7 @@ To determine which browser or webview is being used on your computer, see [Brows ## Debug a task pane add-in using the F12 tools -Windows 10 and 11 include a web development tool called "F12" because it was originally launched by pressing F12 in Internet Explorer. F12 is now an independent application used to debug your add-in when it is running in the Internet Explorer webview control, Trident. The application is not available in earlier versions of Windows. +Windows 10 and 11 include a web development tool called "F12" because it was originally launched by pressing <kbd>F12</kbd> in Internet Explorer. F12 is now an independent application used to debug your add-in when it is running in the Internet Explorer webview control, Trident. The application is not available in earlier versions of Windows. > [!NOTE] > If your add-in has an [add-in command](../design/add-in-commands.md) that executes a function, the function runs in a hidden browser runtime process that the F12 tools cannot detect or attach to, so the technique described in this article cannot be used to debug code in the function. @@ -60,12 +60,12 @@ The following steps are the instructions for debugging your add-in. If you just ### Example add-in to test the F12 tools -This example uses Word and a free add-in from AppSource. +This example uses Word and a free add-in from Microsoft Marketplace. 1. Open Word and choose a blank document. -1. Select **Home** > **Add-ins**, then select **Get Add-ins**. +1. Select **Home** > **Add-ins**, then select **More Add-ins**. 1. In the **Office Add-ins** dialog, select the **STORE** tab. -1. Select the **QR4Office** add-in. It opens in a task pane. +1. Search for and select the **QR4Office** add-in. It opens in a task pane. 1. Launch the F12 development tools that corresponds to your version of Office as described in the preceding section. 1. In the F12 window, select **Home.html**. 1. In the **Debugger** tab, open the file **Home.js** as described in the preceding section. diff --git a/docs/testing/debug-autolaunch.md b/docs/testing/debug-autolaunch.md new file mode 100644 index 0000000000..94bb1120d5 --- /dev/null +++ b/docs/testing/debug-autolaunch.md @@ -0,0 +1,201 @@ +--- +title: Debug event-based or spam-reporting add-ins +description: Learn how to debug your Office Add-ins that implement event-based activation or integrated spam reporting. +ms.date: 07/15/2025 +ms.topic: how-to +ms.localizationpriority: medium +--- + +# Debug event-based or spam-reporting add-ins + +This article discusses the key debugging stages to enable and set breakpoints in your code as you implement [event-based activation](../develop/event-based-activation.md) or [integrated spam reporting](../outlook/spam-reporting.md) in your add-in. Before you proceed, we recommend reviewing the [troubleshooting guide](troubleshoot-event-based-and-spam-reporting-add-ins.md) for additional steps on how to resolve development errors. + +To begin debugging, select the tab for your applicable client. + +# [Web](#tab/web) + +Use your preferred browser's developer tools to debug your event-based add-in in Office on the web. For more information, see [Debug add-ins in Office on the web](debug-add-ins-in-office-online.md). + +# [Windows (new)](#tab/new-windows) + +To debug your add-in in [new Outlook on Windows desktop client](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627), run the following command to open Microsoft Edge DevTools. + +```command line +olk.exe --devtools +``` + +For more information, see the "Debug your add-in" section of [Develop Outlook add-ins for the new Outlook on Windows](../outlook/one-outlook.md#debug-your-add-in). + +# [Windows (classic)](#tab/windows) + +If you used the [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md) to create your add-in project (for example, by completing an [event-based activation walkthrough](../outlook/on-new-compose-events-walkthrough.md)), follow the **Created with Yeoman generator** option throughout this article. Otherwise, follow the **Other** steps. + +## Mark your add-in for debugging and set the debugger port + +1. Get your add-in's ID from the manifest. + + - **Add-in only manifest**: Use the value of the `<Id>` element child of the root `<OfficeApp>` element. + - **Unified manifest for Microsoft 365**: Use the value of the `"id"` property of the root anonymous `{ ... }` object. + +1. In the registry, mark your add-in for debugging. + + - **Created with Yeoman generator**: In a command line window, navigate to the root of your add-in folder then run the following command. + + ```command line + npm start + ``` + + In addition to building the code and starting the local server, this command sets the data of the `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\Developer\[Add-in ID]\UseDirectDebugger` registry DWORD value for this add-in to `1`. `[Add-in ID]` is your add-in's ID from the manifest. + + - **Other**: In the `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\Developer\[Add-in ID]\UseDirectDebugger` registry DWORD value, where `[Add-in ID]` is your add-in's ID from the manifest, set its data to `1`. + + [!include[Developer registry key](../includes/developer-registry-key.md)] + +1. In the registry key `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\Developer\[Add-in ID]`, where `[Add-in ID]` is your add-in's ID from the manifest, create a new `DWORD` value with the following configuration. + + - **Value name**: `DebuggerPort` + - **Value data (hexadecimal)**: `00002407` + + This sets the debugger port to `9223`. + +1. Start your Office application or restart it if it's already open. +1. Perform the action to initiate the event you're developing for, such as creating a new message to initiate the `OnNewMessageCompose` event or reporting spam messages. The **Debug Event-based handler** dialog should appear. Do *not* interact with the dialog yet. + + ![The Debug Event-based handler dialog in Windows.](../images/outlook-win-autolaunch-debug-dialog.png) + +## Configure and attach the debugger + +You can debug your add-in using the Microsoft Edge Inspect tool or Visual Studio Code. + +### Debug with Microsoft Edge + +1. Open Microsoft Edge and go to **edge://inspect/#devices**. +1. In the **Remote Target** section, look for your add-in using its ID from the manifest. Then, select **Inspect**. + + The DevTools window appears. + + > [!NOTE] + > It may take some time for your add-in to appear in the **Remote Target** section. You may need to refresh the page for the add-in to appear. + +1. In the **Sources** tab, go to **file://** > **Users/[User]/AppData/Local/Microsoft/Office/16.0/Wef/{[Office profile GUID]}/[Office account encoding]/Javascript/[Add-in ID]\_[Add-in Version]_[locale]** > **bundle.js**. For readability, this article refers to the file name as **bundle.js**, but exact name depends on the Office application. + - Excel: **bundle_excel.js** + - Outlook: **bundle.js** + - PowerPoint: **bundle_powerpoint.js** + - Word: **bundle_word.js** + + > [!TIP] + > There's no direct method to determine the Office profile GUID or mail account encoding used in the **bundle.js** file path. If you're debugging multiple add-ins simultaneously, the easiest way to access an add-in's **bundle.js** file from the DevTools window is to locate the add-in's ID in the file path. + +1. In the **bundle.js** file, place breakpoints where you want the debugger to stop. +1. [Run the debugger](#run-the-debugger). + +### Debug with Visual Studio Code + +To debug your add-in in Visual Studio Code, you must have at least version 1.56.1 installed. + +#### Configure the debugger + +Configure the debugger in Visual Studio Code. Follow the steps applicable to your add-in project. + +##### Created with Yeoman generator + +1. In the command line, run the following to open your add-in project in Visual Studio Code. + + ```command line + code . + ``` + +1. In Visual Studio Code, open the **./.vscode/launch.json** file and add the following excerpt to your list of configurations. Save your changes. + + ```json + { + "name": "Direct Debugging", + "type": "node", + "request": "attach", + "port": 9223, + "timeout": 600000, + "trace": true + } + ``` + +##### Other + +1. Create a new folder called **Debugging** (perhaps in your **Desktop** folder). +1. Open Visual Studio Code. +1. Go to **File** > **Open Folder**, navigate to the folder you created, then choose **Select Folder**. +1. On the Activity Bar, select **Run and Debug** (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>D</kbd>). + + ![The Run and Debug icon on the Activity Bar.](../images/vs-code-debug.png) + +1. Select the **create a launch.json file** link. + + ![The link located under the Run and Debug option to create a launch.json file in Visual Studio Code.](../images/vs-code-create-launch.json.png) + +1. In the **Select Environment** dropdown, select **Edge: Launch** to create a launch.json file. +1. Add the following excerpt to your list of configurations. Save your changes. + + ```json + { + "name": "Direct Debugging", + "type": "node", + "request": "attach", + "port": 9223, + "timeout": 600000, + "trace": true + } + ``` + +#### Attach the debugger + +The **bundle.js** file of an add-in contains the JavaScript code of your add-in. It's created when an Office on Windows application is opened. When Office starts, the **bundle.js** file of each installed add-in is cached in the **Wef** folder of your machine. + +1. To find the add-in's **bundle.js** file, navigate to the following folder in File Explorer. The text enclosed in `[]` represents your applicable Office and add-in information. + + ```text + %LOCALAPPDATA%\Microsoft\Office\16.0\Wef\{[Office profile GUID]}\[Office account encoding]\Javascript\[Add-in ID]_[Add-in Version]_[locale] + ``` + + [!INCLUDE [office-bundle-js](../includes/office-bundle-js.md)] + +1. Open **bundle.js** in Visual Studio Code. +1. Place breakpoints in **bundle.js** where you want the debugger to stop. +1. In the **DEBUG** dropdown, select **Direct Debugging**, then select the **Start Debugging** icon. + + ![The Direct Debugging option selected from configuration options in the Visual Studio Code Debug dropdown.](../images/outlook-win-autolaunch-debug-vsc.png) + +## Run the debugger + +After confirming that the debugger is attached, return to the Office application. In the **Debug Event-based handler** dialog, select **OK**. + +You can now reach your breakpoints to debug your event-based activation or spam-reporting code. + +> [!IMPORTANT] +> Starting in Version 2403 (Build 17425.20000), event-based and spam-reporting add-ins use the [V8 JavaScript engine](https://v8.dev/) to run JavaScript, regardless of whether debugging is turned on or off. In earlier versions, the Chakra JavaScript engine is used when debugging is off, but the V8 engine may be used when debugging is turned on. + +## Stop the debugger + +To stop debugging the rest of the current Office on Windows session, in the **Debug Event-based handler** dialog, choose **Cancel**. To re-enable debugging, restart the Office application. + +To prevent the **Debug Event-based handler** dialog from popping up and stop debugging for subsequent sessions, delete the associated registry key, `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\Developer\[Add-in ID]\UseDirectDebugger`, or set its value to `0`. + +## Stop the local server + +[!include[Instructions to stop web server and uninstall dev add-in](../includes/stop-uninstall-outlook-dev-add-in.md)] + +# [Mac](#tab/mac) + +Event-based add-ins that run in Office on Mac use the browser runtime. Because of this, you can debug your add-in using Safari Web Inspector. + +1. To use the Safari Web Inspector in Office, follow the steps in [Debugging with Safari Web Inspector on a Mac](debug-office-add-ins-on-ipad-and-mac.md#debugging-with-safari-web-inspector-on-a-mac). +1. Open Office, then [sideload your add-in](../testing/test-debug-office-add-ins.md#sideload-an-office-add-in-for-testing). +1. Perform an action that will initiate the event your add-in handles. For example, create a new message to initiate the `OnNewMessageCompose` event. This opens an empty Developer Window. The name of your add-in appears in the title bar of the window. +1. Right-click (or select and hold) anywhere in the Developer Window, then select **Inspect Element**. This opens the Inspector, where you can set breakpoints and debug your add-in. + +--- + +## See also + +- [Activate add-ins with events](../develop/event-based-activation.md) +- [Implement an integrated spam-reporting add-in](../outlook/spam-reporting.md) +- [Troubleshoot event-based and spam-reporting add-ins](troubleshoot-event-based-and-spam-reporting-add-ins.md) +- [Debug your add-in with runtime logging](runtime-logging.md) diff --git a/docs/testing/debug-desktop-using-edge-chromium.md b/docs/testing/debug-desktop-using-edge-chromium.md index 3094bd4f3e..98df805fc9 100644 --- a/docs/testing/debug-desktop-using-edge-chromium.md +++ b/docs/testing/debug-desktop-using-edge-chromium.md @@ -37,9 +37,9 @@ These instructions assume you have experience using the command line, understand 1. Open VS Code and open your project in it. -1. Choose **View** > **Run** or enter **Ctrl+Shift+D** to switch to debug view. +1. Choose **View** > **Run** or enter <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>D</kbd> to switch to debug view. -1. From the **RUN AND DEBUG** options, choose the Edge Chromium option for your host application, such as **Outlook Desktop (Edge Chromium)**. Select **F5** or choose **Run** > **Start Debugging** from the menu to begin debugging. This action automatically launches a local server in a Node window to host your add-in and then automatically opens the host application, such as Excel or Word. This may take several seconds. +1. From the **RUN AND DEBUG** options, choose the Edge Chromium option for your host application, such as **Outlook Desktop (Edge Chromium)**. Select <kbd>F5</kbd> or choose **Run** > **Start Debugging** from the menu to begin debugging. This action automatically launches a local server in a Node window to host your add-in and then automatically opens the host application, such as Excel or Word. This may take several seconds. > [!TIP] > If you aren't using a project created with Yo Office, you may be prompted to adjust a registry key. While in the root folder of your project, run the following in the command line. @@ -74,7 +74,7 @@ These instructions assume you have experience using the command line, understand > Breakpoints in calls of `Office.initialize` or `Office.onReady` are ignored. For details about these functions, see [Initialize your Office Add-in](../develop/initialize-add-in.md). > [!IMPORTANT] -> The best way to stop a debugging session is to select **Shift+F5** or choose **Run** > **Stop Debugging** from the menu. This action should close the Node server window and attempt to close the host application, but there'll be a prompt on the host application asking you whether to save the document or not. Make an appropriate choice and let the host application close. Avoid manually closing the Node window or host application. Doing so can cause bugs especially when you are stopping and starting debugging sessions repeatedly. +> The best way to stop a debugging session is to select <kbd>Shift</kbd>+<kbd>F5</kbd> or choose **Run** > **Stop Debugging** from the menu. This action should close the Node server window and attempt to close the host application, but there'll be a prompt on the host application asking you whether to save the document or not. Make an appropriate choice and let the host application close. Avoid manually closing the Node window or host application. Doing so can cause bugs especially when you are stopping and starting debugging sessions repeatedly. > > If debugging stops working---for example, if breakpoints are being ignored---stop debugging. Then, if necessary, close all host application windows and the Node window. Finally, close Visual Studio Code and reopen it. @@ -161,7 +161,7 @@ You can now debug your project using the VS Code debugger (F5). ### Appendix 1. In the error dialog box, select the **Cancel** button. -1. If debugging doesn't stop automatically, select **Shift+F5** or choose **Run** > **Stop Debugging** from the menu. +1. If debugging doesn't stop automatically, select <kbd>Shift</kbd>+<kbd>F5</kbd> or choose **Run** > **Stop Debugging** from the menu. 1. Close the Node window where the local server is running, if it doesn't close automatically. 1. Close the Office application if it doesn't close automatically. 1. Open the `\.vscode\launch.json` file in the project. diff --git a/docs/testing/debug-function-command.md b/docs/testing/debug-function-command.md index d57dcddd30..ffc9740c41 100644 --- a/docs/testing/debug-function-command.md +++ b/docs/testing/debug-function-command.md @@ -1,22 +1,22 @@ --- title: Debug a function command with a non-shared runtime description: Learn how to debug function commands. -ms.date: 08/18/2023 +ms.date: 06/17/2025 ms.localizationpriority: medium --- # Debug a function command with a non-shared runtime > [!IMPORTANT] -> If your add-in is [configured to use a shared runtime](../develop/configure-your-add-in-to-use-a-shared-runtime.md), you debug the code behind the function command just as you would the code behind a task pane. See [Debug Office Add-ins](debug-add-ins-overview.md) and note that a function command in an add-in with a [shared runtime](runtimes.md#shared-runtime) is *not* a special case as described in that article. +> If your add-in is [configured to use a shared runtime](../develop/configure-your-add-in-to-use-a-shared-runtime.md), debug the code behind the function command just as you would the code behind a task pane. See [Debug Office Add-ins](debug-add-ins-overview.md) and note that a function command in an add-in with a [shared runtime](runtimes.md#shared-runtime) is *not* a special case as described in that article. > [!NOTE] -> This article assumes that you are familiar with [function commands](../design/add-in-commands.md#types-of-add-in-commands). +> This article assumes that you're familiar with [function commands](../design/add-in-commands.md#types-of-add-in-commands). Function commands don't have a UI, so a debugger can't be attached to the process in which the function runs on desktop Office. (Outlook add-ins being developed on Windows are an exception to this. See [Debug function commands in Outlook add-ins on Windows](#debug-function-commands-in-outlook-add-ins-on-windows) later in this article.) So function commands, in add-ins with a non-shared runtime, must be debugged in Office on the web where the function runs in the overall browser process. Use the following steps. -1. Sideload the add-in in Office on the web, and then select the button or menu item that runs the function command. This is necessary to load the code file for the function command. -1. Open the browser's developer tools. This is usually done by pressing F12. The debugger in the tools attaches to the browser process. +1. [Sideload the add-in in Office on the web](sideload-office-add-ins-for-testing.md), and then select the button or menu item that runs the function command. This is necessary to load the code file for the function command. +1. Open the browser's developer tools. This is usually done by pressing <kbd>F12</kbd>. The debugger in the tools attaches to the browser process. 1. Apply breakpoints to the code as needed for the function command. 1. Rerun the function command. The process stops on your breakpoints. diff --git a/docs/testing/debug-initialize-onready.md b/docs/testing/debug-initialize-onready.md index ef38d6bcd5..809a5d543b 100644 --- a/docs/testing/debug-initialize-onready.md +++ b/docs/testing/debug-initialize-onready.md @@ -1,27 +1,41 @@ --- title: Debug the initialize and onReady functions description: Learn how to debug the Office.initialize and Office.onReady functions. -ms.date: 08/18/2023 +ms.date: 09/18/2025 ms.localizationpriority: medium --- # Debug the initialize and onReady functions > [!NOTE] -> This article assumes that you are familiar with [Initialize your Office Add-in](../develop/initialize-add-in.md). +> This article assumes that you're familiar with [Initialize your Office Add-in](../develop/initialize-add-in.md). The paradox of debugging the [Office.initialize](/javascript/api/office#office-office-initialize-function(1)) and [Office.onReady](/javascript/api/office#office-office-onready-function(1)) functions is that a debugger can only attach to a process that's running, but these functions run immediately as the add-in's runtime process starts up, before a debugger can attach. In most situations, restarting the add-in after a debugger is attached doesn't help because restarting the add-in closes the original runtime process *and the attached debugger* and starts a new process that has no debugger attached. -Fortunately, there's an exception. You can debug these functions using Office on the web, with the following steps. +Fortunately, there are two ways that you can debug these functions that are described in the following sections. + +## Debug using Office on the web + +To debug with Office on the web, use the following steps. 1. Sideload and run the add-in in Office on the web. This is usually done by opening an add-in's task pane or running a [function command](../design/add-in-commands.md#types-of-add-in-commands). *The add-in runs in the overall browser process, not a separate process as it would in desktop Office.* -1. Open the browser's developer tools. This is usually done by pressing F12. The debugger in the tools attaches to the browser process. +1. Open the browser's developer tools. This is usually done by pressing <kbd>F12</kbd>. The debugger in the tools attaches to the browser process. 1. Apply breakpoints as needed to the code in the `Office.initialize` or `Office.onReady` function. 1. *Relaunch the add-in's task pane or the function command* just as you did in step 1. This action does *not* close the browser process or the debugger. The `Office.initialize` or `Office.onReady` function runs again and processing stops on your breakpoints. > [!TIP] > For more detailed information, see [Debug add-ins in Office on the web](debug-add-ins-in-office-online.md). +## Debug using Office on Windows + +> [!NOTE] +> The technique described in this section works only when the add-in using the WebView2 webview control. To determine which webview you're using, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). + +> [!TIP] +> [!INCLUDE[Identify the webview through the add-in UI](../includes/identify-webview-in-ui.md)] + +[!INCLUDE[Automatically open the Microsoft Edge (Chromium-based) developer tools to debug initializatio](../includes/auto-open-webview2-dev-tools.md)] + ## See also - [Runtimes in Office Add-ins](runtimes.md) diff --git a/docs/testing/debug-office-add-ins-on-ipad-and-mac.md b/docs/testing/debug-office-add-ins-on-ipad-and-mac.md index 1acd07be54..fe1277b2c6 100644 --- a/docs/testing/debug-office-add-ins-on-ipad-and-mac.md +++ b/docs/testing/debug-office-add-ins-on-ipad-and-mac.md @@ -1,7 +1,7 @@ --- title: Debug Office Add-ins on a Mac description: Learn how to use a Mac to debug Office Add-ins. -ms.date: 07/09/2024 +ms.date: 02/04/2025 ms.localizationpriority: medium --- @@ -35,7 +35,7 @@ Then, open the Office application and [sideload your add-in](sideload-an-office- > [!NOTE] > -> - If you're debugging an [event-based](../outlook/autolaunch.md) or [spam-reporting](../outlook/spam-reporting.md) add-in in Outlook on Mac, follow the steps in [Debug your event-based or spam-reporting Outlook add-in](../outlook/debug-autolaunch.md) after configuring the `OfficeWebAddinDeveloperExtras` property. +> - If you're debugging an [event-based](../develop/event-based-activation.md) or [spam-reporting](../outlook/spam-reporting.md) add-in in Outlook on Mac, follow the steps in [Debug event-based or spam-reporting add-ins](debug-autolaunch.md) after configuring the `OfficeWebAddinDeveloperExtras` property. > - If you're trying to use the inspector and the dialog flickers, update Office to the latest version. If that doesn't resolve the flickering, try the following workaround. > > 1. Reduce the size of the dialog. @@ -45,4 +45,4 @@ Then, open the Office application and [sideload your add-in](sideload-an-office- ## Clearing the Office application's cache on a Mac -[!include[additional cache folders on Mac](../includes/mac-cache-folders.md)] +Add-ins are often cached in Office on Mac for performance reasons. For guidance on how to clear the Office cache on Mac, see [Clear the Office cache on Mac](clear-cache.md#clear-the-office-cache-on-mac). diff --git a/docs/testing/ie-11-testing.md b/docs/testing/ie-11-testing.md index a5cd2c5d90..4d4ead293d 100644 --- a/docs/testing/ie-11-testing.md +++ b/docs/testing/ie-11-testing.md @@ -1,7 +1,7 @@ ---- +--- title: Trident testing description: Test your Office Add-in on the Trident webview associated with Internet Explorer 11. -ms.date: 07/14/2024 +ms.date: 09/30/2025 ms.localizationpriority: medium --- @@ -14,24 +14,19 @@ If you plan to support older versions of Windows and Office, your add-in must wo > > Some combinations of platforms and Office versions, including volume-licensed perpetual versions through Office 2019, still use the webview controls that come with Internet Explorer 11 (called "Trident") and Microsoft Edge Legacy (called "EdgeHTML") to host add-ins, as explained in [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). Internet Explorer 11 was disabled in Windows 10 and Windows 11 in February 2023, and the UI for launching it was removed; but it's still installed on with those operating systems. So, Trident and other functionality from Internet Explorer can still be called programmatically by Office. > -> We recommend (but don't require) that you support these combinations, at least in a minimal way, by providing users of your add-in a graceful failure message when your add-in is launched in these webviews. Keep these additional points in mind: -> -> - Office on the web no longer opens in Internet Explorer or Microsoft Edge Legacy. Consequently, [AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center) doesn't test add-ins in Office on the web on these browsers. -> - AppSource still tests for combinations of platform and Office *desktop* versions that use Trident or EdgeHTML. However, it only issues a warning when the add-in doesn't support these webviews; the add-in isn't rejected by AppSource. -> - The [Script Lab tool](../overview/explore-with-script-lab.md) no longer supports Trident. +> We recommend (but don't require) that you support these combinations, at least in a minimal way, by providing users of your add-in a graceful failure message when your add-in is launched in these webviews. -If you plan to support older versions of Windows and Office, your add-in must work in the embeddable browser control called "Trident" that's provided by Internet Explorer 11. You can use a command line to switch from a more modern webview used by add-ins to Trident for this testing. For information about which versions of Windows and Office use the Internet Explorer 11 webview control, see [Browsers and webview controls used by Office Add-ins](../concepts/browsers-used-by-office-web-add-ins.md). +## Limitations, restrictions, and special considerations when working with Trident -> [!IMPORTANT] -> Trident doesn't support JavaScript versions later than ES5. If you want to use the syntax and features of ECMAScript 2015 or later, you have to use a transpiler or polyfill or both. For more information about these options, see [Support older Microsoft webviews and Office versions](../develop/support-ie-11.md). -> -> Also, Trident doesn't support some HTML5 features such as media, recording, and location. To learn more, see [Determine the webview the add-in is running in at runtime](../develop/support-ie-11.md#determine-the-webview-the-add-in-is-running-in-at-runtime). +When deciding whether, and how, to support Trident, keep these additional points in mind: -> [!NOTE] -> -> - Office on the web can't be opened in Internet Explorer 11, so you can't (and don't need to) test your add-in on Office on the web with Internet Explorer. -> -> - Internet Explorer's Enhanced Security Configuration (ESC) must be turned off for Office Web Add-ins to work. If you're using a Windows Server computer as your client when developing add-ins, note that ESC is turned on by default in Windows Server. +- Office on the web no longer opens in Internet Explorer or Microsoft Edge Legacy. Consequently, [Microsoft Marketplace](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center) doesn't test add-ins in Office on the web on these browsers. +- Microsoft Marketplace still tests for combinations of platform and Office *desktop* versions that use Trident or EdgeHTML. However, it only issues a warning when the add-in doesn't support these webviews; the add-in isn't rejected by Microsoft Marketplace. +- The [Script Lab tool](../overview/explore-with-script-lab.md) no longer supports Trident. +- Trident doesn't support JavaScript versions later than ES5. If you want to use the syntax and features of ECMAScript 2015 or later, you have to use a transpiler or polyfill or both. For more information about these options, see [Support older Microsoft webviews and Office versions](../develop/support-ie-11.md). +- Trident doesn't support some HTML5 features such as media, recording, and location. To learn more, see [Determine the webview the add-in is running in at runtime](../develop/support-ie-11.md#determine-the-webview-the-add-in-is-running-in-at-runtime). +- Office on the web can't be opened in Internet Explorer 11, so you can't (and don't need to) test your add-in on Office on the web with Internet Explorer. +- Internet Explorer's Enhanced Security Configuration (ESC) must be turned off for Office Web Add-ins to work. If you're using a Windows Server computer as your client when developing add-ins, note that ESC is turned on by default in Windows Server. ## Switch to the Trident webview diff --git a/docs/testing/runtime-logging.md b/docs/testing/runtime-logging.md index 68f3538bc6..e136b24a88 100644 --- a/docs/testing/runtime-logging.md +++ b/docs/testing/runtime-logging.md @@ -1,7 +1,7 @@ --- title: Debug your add-in with runtime logging description: Learn how to use runtime logging to debug your add-in. -ms.date: 05/05/2023 +ms.date: 11/08/2024 ms.localizationpriority: medium --- @@ -17,9 +17,10 @@ You can use runtime logging to debug your add-in's manifest as well as several i ## Use runtime logging from the command line -Enabling runtime logging from the command line is the fastest way to use this logging tool. These use npx, which is provided by default as part of npm@5.2.0+. If you have an earlier version of [npm](https://www.npmjs.com/), try [Runtime logging on Windows](#runtime-logging-on-windows) or [Runtime logging on Mac](#runtime-logging-on-mac) instructions, or [install npx](https://www.npmjs.com/package/npx). +Enabling runtime logging from the command line is the fastest way to use this logging tool. -[!INCLUDE[Office settings tool not supported on Mac](../includes/tool-nonsupport-mac-note.md)] +> [!IMPORTANT] +> The office-addin-dev-settings tool is not supported on Mac. See the section [Runtime logging on Mac](#runtime-logging-on-mac) for Mac-specific instructions. - To enable runtime logging: @@ -51,28 +52,6 @@ Enabling runtime logging from the command line is the fastest way to use this lo npx office-addin-dev-settings runtime-log --help ``` -## Runtime logging on Windows - -1. Make sure that you are running Office 2016 desktop build **16.0.7019** or later. - -1. Add the `RuntimeLogging` registry key under `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\Developer\`. - - [!include[Developer registry key](../includes/developer-registry-key.md)] - -1. Set the default value of the **RuntimeLogging** key to the full path of the file where you want the log to be written. The following example run in a `.reg` file sets the logging to the `C:\ClientLogs\log.txt` folder. - - ```registry - [HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Wef\Developer\RuntimeLogging] - @="C:\\ClientLogs\\log.txt"` - ``` - - > [!NOTE] - > The directory in which the log file will be written must already exist, and you must have write permissions to it. - -The following image shows what the registry should look like. To turn the feature off, remove the `RuntimeLogging` key from the registry. - -![The registry editor with a RuntimeLogging registry key.](../images/runtime-logging-registry.png) - ## Runtime logging on Mac 1. Make sure that you are running Office 2016 desktop build **16.27.19071500** or later. diff --git a/docs/testing/runtimes.md b/docs/testing/runtimes.md index 9bdac66a79..f903ceba6f 100644 --- a/docs/testing/runtimes.md +++ b/docs/testing/runtimes.md @@ -2,7 +2,7 @@ title: Runtimes in Office Add-ins description: Learn about the runtimes that are used by Office Add-ins. ms.topic: concept-article -ms.date: 08/07/2024 +ms.date: 07/03/2025 ms.localizationpriority: medium --- @@ -23,8 +23,8 @@ The following table shows the possible features of an add-in, according to each | Type of runtime | Add-in feature | |:-----|:-----| -| JavaScript-only | Excel [custom functions](../excel/custom-functions-overview.md)</br>(except when the runtime is [shared](#shared-runtime) or the add-in is running in Office on the web)</br></br>[Outlook event-based task](../outlook/autolaunch.md)</br>(only when the add-in is running in classic Outlook on Windows)</br></br>[Outlook integrated spam reporting feature](../outlook/spam-reporting.md)</br>(only when the add-in is running in classic Outlook on Windows)| -| browser | [task pane](../design/task-pane-add-ins.md)</br></br>[dialog](../develop/dialog-api-in-office-add-ins.md)</br></br>[function command](../design/add-in-commands.md#types-of-add-in-commands)</br></br>Excel [custom functions](../excel/custom-functions-overview.md)</br>(when the runtime is [shared](#shared-runtime) or the add-in is running in Office on the web)</br></br>[Outlook event-based task](../outlook/autolaunch.md)</br>(when the add-in is running in Outlook on Mac or Outlook on the web or in the [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627))</br></br>[Outlook integrated spam reporting feature](../outlook/spam-reporting.md)</br>(only when the add-in is running in Outlook on Mac or on the web or in the [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627))| +| JavaScript-only | Excel [custom functions](../excel/custom-functions-overview.md)</br>(except when the runtime is [shared](#shared-runtime) or the add-in is running in Office on the web)</br></br>[Excel, PowerPoint, or Word event-based task](../develop/event-based-activation.md)</br>(only when the add-in is running on Windows)</br></br>[Outlook event-based task](../outlook/autolaunch.md)</br>(only when the add-in is running in classic Outlook on Windows)</br></br>[Outlook integrated spam reporting feature](../outlook/spam-reporting.md)</br>(only when the add-in is running in classic Outlook on Windows)| +| browser | [task pane](../design/task-pane-add-ins.md)</br></br>[dialog](../develop/dialog-api-in-office-add-ins.md)</br></br>[function command](../design/add-in-commands.md#types-of-add-in-commands)</br></br>Excel [custom functions](../excel/custom-functions-overview.md)</br>(when the runtime is [shared](#shared-runtime) or the add-in is running in Office on the web)</br></br>[Excel, PowerPoint, or Word event-based task](../develop/event-based-activation.md)</br>(only when the add-in is running on Mac or the web)</br></br>[Outlook event-based task](../outlook/autolaunch.md)</br>(when the add-in is running in Outlook on Mac or Outlook on the web or in the [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627))</br></br>[Outlook integrated spam reporting feature](../outlook/spam-reporting.md)</br>(only when the add-in is running in Outlook on Mac or on the web or in the [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627))| The following table shows the same information organized by which type of runtime is used for the various possible features of an add-in. @@ -32,7 +32,8 @@ The following table shows the same information organized by which type of runtim |:-----|:-----|:-----|:-----| |Excel custom functions | JavaScript-only</br>(but *browser* when the runtime is shared)|browser| browser | |Outlook event-based tasks | JavaScript-only</br>(classic Outlook on Windows)</br></br>browser</br>(new Outlook on Windows) | browser | browser | -|Outlook integrated spam reporting feature (preview)| JavaScript-only</br>(classic Outlook on Windows)</br></br>browser</br>(new Outlook on Windows) | browser | browser | +|Event-based tasks on other applications | JavaScript-only | browser | browser | +|Outlook integrated spam reporting feature | JavaScript-only</br>(classic Outlook on Windows)</br></br>browser</br>(new Outlook on Windows) | browser | browser | |task pane | browser | browser | browser | |dialog | browser | browser | browser | |function command | browser | browser | browser | @@ -45,7 +46,7 @@ When an add-in is running on a platform other than the web, the following princi - An Outlook event-based or spam-reporting add-in runs in its own runtime process. > [!NOTE] - > The [event-based activation](../outlook/autolaunch.md) and [integrated spam reporting](../outlook/spam-reporting.md) features in Outlook must use the same runtime. Multiple runtimes aren't currently supported in Outlook. + > The [event-based activation](../develop/event-based-activation.md) and [integrated spam reporting](../outlook/spam-reporting.md) features in Outlook must use the same runtime. Multiple runtimes aren't currently supported in Outlook. - By default, task panes, function commands, and Excel custom functions each run in their own runtime process. However, for some Office host applications, the add-in manifest can be configured so that any two, or all three, can run in the same runtime. See [Shared runtime](#shared-runtime). @@ -131,7 +132,7 @@ This type of runtime is used in event-based and spam-reporting add-ins in classi - The user changes focus from the window where the event was triggered, such as a message compose window (only applies to event-based add-ins). > [!NOTE] - > The [event-based activation](../outlook/autolaunch.md) and [integrated spam reporting](../outlook/spam-reporting.md) features in Outlook must use the same runtime. Multiple runtimes aren't currently supported in Outlook. + > The [event-based activation](../develop/event-based-activation.md) and [integrated spam reporting](../outlook/spam-reporting.md) features in Outlook must use the same runtime. Multiple runtimes aren't currently supported in Outlook. A JavaScript-only runtime uses less memory and starts up faster than a browser runtime, but has fewer features. diff --git a/docs/testing/sideload-add-in-with-unified-manifest.md b/docs/testing/sideload-add-in-with-unified-manifest.md new file mode 100644 index 0000000000..183419d331 --- /dev/null +++ b/docs/testing/sideload-add-in-with-unified-manifest.md @@ -0,0 +1,180 @@ +--- +title: Sideload Office Add-ins that use the unified manifest for Microsoft 365 +description: Test your Office Add-in on Windows by sideloading. +ms.date: 08/13/2025 +ms.localizationpriority: medium +--- + +# Sideload Office Add-ins that use the unified manifest for Microsoft 365 + +The process of sideloading an add-in that uses the [Unified manifest for Microsoft 365](../develop/json-manifest-overview.md) varies depending on the tool you want to use and on how the add-in project was created. + +> [!NOTE] +> An add-in that uses the unified manifest can be sideloaded on Office on Windows, Version 2304 (Build 16320.20000) or later. Sideloading on Windows has the effect of sideloading to Office on the web too. Currently, it can't be sideloaded on Mac or iPad. + +## Sideload add-ins created with the Yeoman generator for Office Add-ins (Yo Office) + +Use the process described in [Sideload with a system prompt, bash shell, or terminal](#sideload-with-a-system-prompt-bash-shell-or-terminal). + +## Sideload with Microsoft 365 Agents Toolkit + +1. First, *make sure Office desktop application that you want to sideload into is closed.* +1. In Visual Studio Code, open Agents Toolkit. +1. Required for Outlook only: in the **ACCOUNTS** section, verify that you're signed into Microsoft 365. +1. Select **View** | **Run** in Visual Studio Code. In the **RUN AND DEBUG** dropdown menu, select one of these options as appropriate for your add-in. + + - **Excel Desktop (Edge Chromium)** + - **Outlook Desktop (Edge Chromium)** + - **PowerPoint Desktop (Edge Chromium)** + - **Word Desktop (Edge Chromium)** + +1. Press <kbd>F5</kbd>. The project builds and a Node dev-server window opens. This process may take a couple of minutes and then the desktop version of the Office application that you selected opens. You can now work with your add-in. For an Outlook add-in, be sure you're working in the **Inbox** of *your Microsoft 365 account identity*. +1. To stop debugging and uninstall the add-in, select **Run** | **Stop Debugging** in Visual Studio Code. Closing the server window doesn't reliably stop the server and closing the Office application doesn't reliably cause Office to unacquire the add-in. + + > [!NOTE] + > If the preceding step seems to have no effect, uninstall the add-in by opening a **TERMINAL** in Visual Studio Code, and then complete the uninstall step — the *last* step — of the section [Sideload with a system prompt, bash shell, or terminal](#sideload-with-a-system-prompt-bash-shell-or-terminal). + +## Sideload with a system prompt, bash shell, or terminal + +1. First, *make sure the Office desktop application that you want to sideload into is closed.* +1. Open a system prompt, bash shell, or the Visual Studio Code **TERMINAL**, and navigate to the root of the project. +1. The command to sideload the add-in depends on when the project was created. If the `"scripts"` section of the project's package.json file has a "start:desktop" script, then run `npm run start:desktop`; otherwise, run `npm run start`. The project builds and a Node dev-server window opens. This process may take a couple of minutes then the Office host application (Excel, Outlook, PowerPoint, or Word) desktop opens. +1. On some versions of Office, the add-in may not fully activate. For example, the add-in's buttons may not appear on the ribbon. If this happens, select the **Add-ins** button on the **Home** ribbon. On the flyout that opens, select the add-in. This completes the installation. +1. You can now work with your add-in. +1. When you're done working with your add-in, make sure to run the command `npm run stop`. Closing the server window doesn't reliably stop the server and closing the Office application doesn't reliably cause Office to unacquire the add-in. + +## Sideload other NodeJS and npm projects + +There are two tools you can use to sideload. + +### Sideload with the Office-Addin-Debugging tool + +1. To sideload the add-in, run the following command. This command puts the unified manifest and the two icon image files that are referenced in the manifest's `"icons"` property into a zip file and sideloads it to the Office application. It also starts a server in a separate NodeJS window to host the add-in files on localhost. For more details about this command, see [Office-Addin-Debugging](https://www.npmjs.com/package/office-addin-debugging). + + ```command line + npx office-addin-debugging start <relative-path-to-unified-manifest> desktop + ``` + +1. When you use office-addin-debugging to start an add-in, *always stop the session with the following command*. Closing the server window doesn't reliably stop the server and closing the Office application doesn't reliably cause Office to unacquire the add-in. + + ```command line + npx office-addin-debugging stop <relative-path-to-unified-manifest> + ``` + +### Sideload with Microsoft 365 Agents Toolkit CLI (command-line interface) + +1. Create a zip package. See [Manually create the add-in package file](#manually-create-the-add-in-package-file). + +1. In the root of the project, open a command prompt or bash shell and run the following command to install the Agents Toolkit CLI. + + ```command line + npm install -g @microsoft/m365agentstoolkit-cli + ``` + +1. Run the following command to sideload the add-in. + + ```command line + atk install --file-path <relative-path-to-zip-file> + ``` + + > [!IMPORTANT] + > This command returns some information about the add-in including an autogenerated title ID as shown in the following example. + > + > :::image type="content" source="../images/atk-cli-install.png" alt-text="The command 'atk install --file-path manifests/contoso/contoso.zip' and the system response including the user's account name, the title id GUID and the app id GUID."::: + > + > You'll need this title ID to end the sideloading and debugging session. It is recorded on Windows computers in the following Registry key: + > + > **HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Wef\Developer\OutlookSideloadManifestPath\TitleId** + > + > The string "Outlook" is in the key name for historical reasons, but it applies to any add-in installed with the Agents Toolkit CLI. + > + > Only the most recent add-in installed with the CLI is recorded. If you sideload an add-in with the CLI before you have uninstalled an earlier add-in you installed with the CLI, then there is no record of the earlier add-in's title ID in the Registry. So, we recommend that you also save it in a text file in the root of the project and name the file **TitleID.txt** on both Mac and Windows computers. + +1. When you use the Agents Toolkit CLI to start an add-in, *always stop the session with the following command*. Closing the server window doesn't reliably stop the server and closing the Office application doesn't reliably cause Office to unacquire the add-in. Replace "{title ID}" with the title ID of the add-in including the "U_" prefix; for example, `U_90d141c6-cf4f-40ee-b714-9df9ea593f39`. + + ```command line + atk uninstall --mode title-id --title-id {title ID} --interactive false + ``` + + > [!IMPORTANT] + > The [documentation for the `uninstall` command](/microsoftteams/platform/toolkit/teams-toolkit-cli?pivots=version-three#teamsapp-uninstall) describes a way to use the add-in's manifest ID instead of the title ID. Due to a bug in an API that the CLI calls, this option doesn't currently work. You must use the `uninstall` command given above and you must include the `--interactive false` option. + +## Sideload through the Teams app store + +Add-ins that use the unified manifest can be manually sideloaded through the Teams app store, even if they have no Teams-related functionality. The steps are as follows. + +1. Create an app package manually if it hasn't already been created by a tool. See [Manually create the add-in package file](#manually-create-the-add-in-package-file). +1. Close all Office applications, and then clear the Office cache following the instructions at [Manually clear the cache](../testing/clear-cache.md#manually-clear-the-cache). +1. Open Teams and select **Apps** from the app bar, then select **Manage your apps** at the bottom of the **Apps** pane. +1. Select **Upload an app** in the **Apps** dialog, and then in the dialog that opens, select **Upload a custom app**. +1. In the **Open** dialog, navigate to, and select, the app package. +1. Select **Add** in the dialog that opens. +1. When you're prompted that the app was added, *don't* open it in Teams. Instead, close Teams. +1. The next task is to start a local web server that hosts your project's HTML and JavaScript files. How you do this depends on several factors including the folder structure of your project, the tools you use, such as a bundler, task manager, server application, and how you have configured those tools. The following instruction applies only to projects that meet the following conditions. + + - There's a **webpack.config.js** file in the root of the project that is similar to the ones in add-in projects that are created with the [Yeoman Generator for Office Add-ins](../develop/yeoman-generator-overview.md) or [Microsoft 365 Agent Toolkit](../develop/agents-toolkit-overview.md). + - There's a **package.json** file in the root of the project similar to the ones created by the same two tools and the file has a "scripts" section with the following script in it. + + ```json + "dev-server": "webpack serve --mode development" + ``` + +1. In a command prompt or Visual Studio Code **TERMINAL** in the root of the project, run `npm run dev-server` to start the server on localhost. +1. Open the Office application that the add-in targets. Wait until the add-in has loaded. This may take as much as two minutes. Depending on your version of Office, ribbon buttons and other artifacts may appear automatically. In some versions, you need to manually activate the add-in: Select the **Add-ins** button on the **Home** ribbon, and then in the flyout that opens, select your add-in. It will have the name specified in the [`"name.short"`](/microsoft-365/extensibility/schema/root-name) property of the manifest. + +> [!IMPORTANT] +> When you want to end a testing session and make changes to the add-in that you sideloaded through the Teams app store, be sure to remove the add-in completely with the following steps. +> +> 1. Close the Office application. +> 1. Shut down the server. See the documentation for your server application for how to do this. For the webpack dev-server application, shutting it down depends on whether the server is running in the same window in which you ran `npm run dev-server` or a different window. If it's the same window, give the terminal focus and press <kbd>Ctrl</kbd>+<kbd>C</kbd>. Choose "Y" in response to the prompt to end the process. If it's in a different window, then in the window where you ran `npm run dev-server`, run `npm run stop`. +> 1. Clear the Office cache following the instructions at [Manually clear the cache](../testing/clear-cache.md#manually-clear-the-cache). +> 1. Open Teams and select **Apps** from the app bar, then select **Manage your apps** at the bottom of the **Apps** pane. +> 1. Find your add-in in the list of apps. It will have the name specified in the `"name.short"` property of the manifest. +> 1. Select the add-in from the list of apps to expand its row. +> 1. Select the trash can icon and then select **Remove** in the prompt. +> +> Make your changes and then sideload the add-in again. + +## Manually create the add-in package file + +When the unified manifest is used, the unit of installation and sideloading is a zip-formatted package file. This file is usually created for you by the tools you use to create and test your add-in, but there are scenarios in which you create it manually. To do so, use any zip utility to create a zip file that contains the following files. + +- The unified manifest, which goes in the root of the zip file. +- The two image files referenced in the `"icons"` property of the manifest. +- Any localization files that are referenced in the `"localizationInfo"` property of the manifest. +- Any declarative agent files that are referenced in the `"copilotAgents"` property. +- Any second-level supplementary files. For example, declarative agent configuration files sometimes reference second-level supplementary files, such as plugin configuration files. These should be included too. + +> [!IMPORTANT] +> *All of these files must have the same relative path in the zip file as specified in the manifest.* For example, if the path of the two image files is **assets/icon-64.png** and **assets/icon-128.png**, then you must include an **assets** folder with the two files in the zip package. Second-level files, such as plugin configuration files for declarative agents, must have the same relative path in the zip file as they do in the first-level file that references them. For example, if the relative path of a declarative agent file specified in the manifest is **agents/myAgent.json**, then you must include an **agents** folder in the zip package and put the **myAgent.json** file in it. If the declarative agent file, in turn, gives the relative path of **plugins/myPlugin.json** for a plugin configuration file, then you must include a **plugins** subfolder under the **agents** folder and put the **myPlugin.json** file in it. + +To maximize compatibility with Microsoft 365 development tools, we recommend that you keep the files that will be included in the package in a folder called **appPackage** in the root of your project, and that you put the package file in a subfolder named **build** in the **appPackage** folder. + +The following are examples of the recommended structure. The structure inside the **\build\appPackage.zip** file must mirror the structure of the **appPackage** folder, except for the **build** folder itself. + +```console +\appPackage + \assets + color.png + outline.png + \build + appPackage.zip + manifest.json +``` + +```console +\appPackage + \agents + myAgent.json + \plugins + myPlugin.json + \assets + color.png + outline.png + \build + appPackage.zip + \languages + fr-FR.json + es-MX.json + manifest.json +``` diff --git a/docs/testing/sideload-an-office-add-in-on-ipad.md b/docs/testing/sideload-an-office-add-in-on-ipad.md index 12a8dd33b4..596f4b24fa 100644 --- a/docs/testing/sideload-an-office-add-in-on-ipad.md +++ b/docs/testing/sideload-an-office-add-in-on-ipad.md @@ -1,7 +1,7 @@ --- title: Sideload Office Add-ins on iPad for testing description: Test your Office Add-in on iPad by sideloading. -ms.date: 09/09/2024 +ms.date: 02/12/2025 ms.localizationpriority: medium --- @@ -9,6 +9,8 @@ ms.localizationpriority: medium To see how your add-in will run in Office on iOS, you can sideload your add-in's manifest onto an iPad using iTunes. This action won't enable you to set breakpoints and debug your add-in's code while it's running, but you can see how it behaves and verify that the UI is usable and rendering appropriately. +[!INCLUDE [Unified manifest note about platform sideloading restrictions](../includes/unified-manifest-sideload-restrictions-note.md)] + > [!NOTE] > To sideload an Outlook add-in, see [Sideload Outlook add-ins for testing](../outlook/sideload-outlook-add-ins-for-testing.md). diff --git a/docs/testing/sideload-an-office-add-in-on-mac.md b/docs/testing/sideload-an-office-add-in-on-mac.md index a15d928468..f6a84ec473 100644 --- a/docs/testing/sideload-an-office-add-in-on-mac.md +++ b/docs/testing/sideload-an-office-add-in-on-mac.md @@ -1,7 +1,7 @@ --- title: Sideload Office Add-ins on Mac for testing description: Test your Office Add-in on Mac by sideloading. -ms.date: 02/09/2024 +ms.date: 02/12/2025 ms.localizationpriority: medium --- @@ -9,6 +9,8 @@ ms.localizationpriority: medium To see how your add-in will run on Office on Mac, you can sideload your add-in's manifest. This action won't enable you to set breakpoints and debug your add-in's code while it's running, but you can see how it behaves and verify that the UI is usable and rendering appropriately. +[!INCLUDE [Unified manifest note about platform sideloading restrictions](../includes/unified-manifest-sideload-restrictions-note.md)] + > [!NOTE] > To sideload an Outlook add-in, see [Sideload Outlook add-ins for testing](../outlook/sideload-outlook-add-ins-for-testing.md). @@ -16,17 +18,17 @@ To see how your add-in will run on Office on Mac, you can sideload your add-in's - A Mac running OS X v10.10 "Yosemite" or later with [Office on Mac](https://www.microsoft.com/microsoft-365/buy/compare-all-microsoft-365-products) installed. -- Word on Mac version 15.18 (160109). +- Word on Mac Version 15.18 (160109). -- Excel on Mac version 15.19 (160206). +- Excel on Mac Version 15.19 (160206). -- PowerPoint on Mac version 15.24 (160614). +- PowerPoint on Mac Version 15.24 (160614). - The manifest .xml file for the add-in you want to test. ## Sideload an add-in in Office on Mac -1. Use **Finder** to sideload the manifest file. Open **Finder** and then enter Command+Shift+G to open the **Go to folder** dialog. +1. Use **Finder** to sideload the manifest file. Open **Finder** and then enter <kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>G</kbd> to open the **Go to folder** dialog. 1. Enter one of the following filepaths, based on the application you want to use for sideloading. If the `wef` folder doesn't exist on your computer, create it. diff --git a/docs/testing/sideload-office-add-ins-for-testing.md b/docs/testing/sideload-office-add-ins-for-testing.md index 34f568528e..6e5a262f03 100644 --- a/docs/testing/sideload-office-add-ins-for-testing.md +++ b/docs/testing/sideload-office-add-ins-for-testing.md @@ -1,7 +1,7 @@ --- title: Sideload Office Add-ins to Office on the web description: Test your Office Add-in in Office on the web by sideloading. -ms.date: 08/17/2023 +ms.date: 07/29/2025 ms.localizationpriority: medium --- @@ -9,6 +9,11 @@ ms.localizationpriority: medium When you sideload an add-in, you're able to install the add-in without first putting it in an add-in catalog. This is useful when testing and developing your add-in because you can see how your add-in will appear and function. +> [!NOTE] +> +> - This article applies to **Excel**, **OneNote**, **PowerPoint**, and **Word** add-ins. For information on sideloading **Outlook** add-ins, see the article [Sideload Outlook add-ins for testing](../outlook/sideload-outlook-add-ins-for-testing.md). +> - This article applies to add-ins that use the add-in only manifest. For information about sideloading add-ins that use the [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md), see [Sideload Office Add-ins that use the unified manifest for Microsoft 365](sideload-add-in-with-unified-manifest.md). + When you sideload an add-in on the web, the add-in's manifest is stored in the browser's local storage, so if you clear the browser's cache, or switch to a different browser, you have to sideload the add-in again. The steps to sideload an add-in on the web vary based on the following factors. @@ -35,7 +40,7 @@ This process is supported for **Excel**, **OneNote**, **PowerPoint**, and **Word 1. Open a Command Prompt as an administrator. In the command line starting at the root directory of your project, run the following command. Replace "{url}" with the URL that you copied. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] 1. The first time you use this method to sideload an add-in on the web, you'll see a dialog asking you to enable developer mode. Select the checkbox for **Enable Developer Mode now** and select **OK**. @@ -45,7 +50,7 @@ This process is supported for **Excel**, **OneNote**, **PowerPoint**, and **Word ## Sideload an add-in on the web when using Visual Studio -If you're using Visual Studio to develop your add-in, press **F5** to open an Office document in *desktop* Office, create a blank document, and sideload the add-in. When you want to sideload to *Office on the web*, the process to sideload is similar to manual sideloading to the web. The only difference is that you must update the value of the **SourceURL** element, and possibly other elements, in your manifest to include the full URL where the add-in is deployed. +If you're using Visual Studio to develop your add-in, press <kbd>F5</kbd> to open an Office document in *desktop* Office, create a blank document, and sideload the add-in. When you want to sideload to *Office on the web*, the process to sideload is similar to manual sideloading to the web. The only difference is that you must update the value of the **SourceURL** element, and possibly other elements, in your manifest to include the full URL where the add-in is deployed. 1. In Visual Studio, choose **View** > **Properties Window**. @@ -67,13 +72,11 @@ If you're using Visual Studio to develop your add-in, press **F5** to open an Of This method doesn't use the command line and can be accomplished using commands only within the host application (such as Excel). -1. Open [Office on the web](https://office.com/). Open a document in **Excel**, **OneNote**, **PowerPoint**, or **Word**. - -1. Select **Home** > **Add-ins**, then select **More Add-ins**. +1. Open [Office on the web](https://office.com/). Open a document in **Excel**, **OneNote**, **PowerPoint**, or **Word**. -1. On the **Office Add-ins** dialog, select the **MY ADD-INS** tab, choose **Manage My Add-ins**, and then **Upload My Add-in**. +1. Select **Home** > **Add-ins**, then select **More Settings**. - ![The Office Add-ins dialog with a drop-down in the upper right reading "Manage my add-ins" and a drop-down below it with the option "Upload My Add-in".](../images/office-add-ins-my-account.png) +1. On the **Office Add-ins** dialog, select **Upload My Add-in**. 1. **Browse** to the add-in manifest file, and then select **Upload**. diff --git a/docs/testing/test-debug-non-local-server.md b/docs/testing/test-debug-non-local-server.md index 13c47dceb9..46fb1b4492 100644 --- a/docs/testing/test-debug-non-local-server.md +++ b/docs/testing/test-debug-non-local-server.md @@ -1,7 +1,7 @@ --- title: Test and debug Office Add-ins on a non-local server description: Learn how to test and debug your Office Add-in on a non-local host. -ms.date: 08/08/2024 +ms.date: 05/19/2025 ms.localizationpriority: medium --- @@ -12,16 +12,16 @@ When you've completed development and testing on a localhost and want to stage a > [!NOTE] > If you're working on a Windows computer, you may have another option for non-local testing. See [Sideload Office Add-ins for testing from a network share](create-a-network-shared-folder-catalog-for-task-pane-and-content-add-ins.md). -## Projects created with Teams Toolkit or the Office Yeoman Generator (Yo Office) +## Projects created with Microsoft 365 Agents Toolkit or the Office Yeoman Generator (Yo Office) -If your project was created with [Teams Toolkit](../develop/teams-toolkit-overview.md) or [Office Yeoman Generator (Yo Office)](../develop/yeoman-generator-overview.md), then the office-addin-debugging tool is already installed and your package.json file has `start` and `stop` scripts that invoke the tool. To use it for non-local testing, update the domain part of the URLs in your manifest to point to your staging server (or CDN as needed). Then run `npm run start` at the command line (or Visual Studio Code TERMINAL) to sideload the add-in for testing and debugging. +If your project was created with [Agents Toolkit](../develop/agents-toolkit-overview.md) or [Office Yeoman Generator (Yo Office)](../develop/yeoman-generator-overview.md), then the office-addin-debugging tool is already installed and your package.json file has `start` and `stop` scripts that invoke the tool. To use it for non-local testing, update the domain part of the URLs in your manifest to point to your staging server (or CDN as needed). Then run `npm run start` at the command line (or Visual Studio Code TERMINAL) to sideload the add-in for testing and debugging. > [!IMPORTANT] > The office-addin-debugging tool registers the add-in in the Windows registry or a special folder on a Mac. For an Outlook add-in, it also registers the add-in in Exchange. To avoid subtle bugs when developing, always end a testing session by running `npm run stop` to ensure that these registrations are removed and that the server process is fully stopped. *Manually closing the server, the command line window (or TERMINAL), Visual Studio Code, or the Office application doesn't remove these registrations.* ## Other projects -If your project wasn't created with Teams Toolkit or Yo Office, run the tool with npx in the root of the project. Invoke it with its `start` command followed by the relative path to the manifest. The following is an example. +If your project wasn't created with Agents Toolkit or Yo Office, run the tool with npx in the root of the project. Invoke it with its `start` command followed by the relative path to the manifest. The following is an example. ```command line npx office-addin-debugging start manifest.json diff --git a/docs/testing/test-debug-office-add-ins.md b/docs/testing/test-debug-office-add-ins.md index c2ee2758ca..d3010393fd 100644 --- a/docs/testing/test-debug-office-add-ins.md +++ b/docs/testing/test-debug-office-add-ins.md @@ -1,4 +1,4 @@ ---- +--- title: Test Office Add-ins description: Learn how to test your Office Add-in. ms.date: 07/12/2024 @@ -18,20 +18,20 @@ Office Add-ins run across major platforms, so you need to test an add-in in all ### Add-ins tested for Office on the web -Add-ins are tested for Office on the web with all major modern browsers, including Microsoft Edge (Chromium-based WebView2), Chrome, and Safari. Accordingly, you should test on these platforms and browsers before you submit to [AppSource](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center). For more information about validation, see [Commercial marketplace certification policies](/legal/marketplace/certification-policies), especially [section 1120.3](/legal/marketplace/certification-policies#11203-functionality), and the [Office Add-in application and availability page](/javascript/api/requirement-sets). +Add-ins are tested for Office on the web with all major modern browsers, including Microsoft Edge (Chromium-based WebView2), Chrome, and Safari. Accordingly, you should test on these platforms and browsers before you submit to [Microsoft Marketplace](/partner-center/marketplace-offers/submit-to-appsource-via-partner-center). For more information about validation, see [Commercial marketplace certification policies](/legal/marketplace/certification-policies), especially [section 1120.3](/legal/marketplace/certification-policies#11203-functionality), and the [Office Add-in application and availability page](/javascript/api/requirement-sets). -Office on the web no longer opens in Internet Explorer or Microsoft Edge Legacy (EdgeHTML). Consequently, AppSource doesn't test Office on the web on these browsers. Office still supports these browsers for add-in runtimes, so if you think you've encountered a bug in how add-ins run in them, please create an issue in the [office-js](https://github.com/OfficeDev/office-js/issues) repository. For more information, see [Support older Microsoft webviews and Office versions](../develop/support-ie-11.md) and [Troubleshoot EdgeHTML and WebView2 (Microsoft Edge) issues](../concepts/browsers-used-by-office-web-add-ins.md#troubleshoot-edgehtml-and-webview2-microsoft-edge-issues). +Office on the web no longer opens in Internet Explorer or Microsoft Edge Legacy (EdgeHTML). Consequently, Microsoft Marketplace doesn't test Office on the web on these browsers. Office still supports these browsers for add-in runtimes, so if you think you've encountered a bug in how add-ins run in them, please create an issue in the [office-js](https://github.com/OfficeDev/office-js/issues) repository. For more information, see [Support older Microsoft webviews and Office versions](../develop/support-ie-11.md) and [Troubleshoot EdgeHTML and WebView2 (Microsoft Edge) issues](../concepts/browsers-used-by-office-web-add-ins.md#troubleshoot-edgehtml-and-webview2-microsoft-edge-issues). ### Add-ins tested for Office on Windows -Some Office versions on Windows still use the webview controls that come with Internet Explorer and Microsoft Edge Legacy. AppSource tests whether your add-in supports these browser controls. If your add-in doesn't support these browser controls, AppSource only issues a warning and doesn't reject your add-in. In this instance, we recommend configuring a graceful failure message on your add-in for a smoother user experience. For further guidance, see [Support older Microsoft webviews and Office versions](../develop/support-ie-11.md). +Some Office versions on Windows still use the webview controls that come with Internet Explorer and Microsoft Edge Legacy. Microsoft Marketplace tests whether your add-in supports these browser controls. If your add-in doesn't support these browser controls, Microsoft Marketplace only issues a warning and doesn't reject your add-in. In this instance, we recommend configuring a graceful failure message on your add-in for a smoother user experience. For further guidance, see [Support older Microsoft webviews and Office versions](../develop/support-ie-11.md). ## Sideload an Office Add-in for testing You can use sideloading to install an Office Add-in for testing without having to first put it in an add-in catalog. The procedure for sideloading an add-in varies by platform, and in some cases, by product as well. The following articles each describe how to sideload Office Add-ins on a specific platform or within a specific product. > [!NOTE] -> Office Add-ins that use the unified manifest for Microsoft 365 are *directly* supported in Office on the web, in [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627), and in Office on Windows connected to a Microsoft 365 subscription, Version 2304 (Build 16320.00000) or later. When the app package that contains the unified manifest is sideloaded to a platform that doesn't directly support that type of manifest then, if the manifest has a valid "alternateIcons" property, an add-in only manifest is generated from the unified manifest and this manifest is the one that's sideloaded. +> Office Add-ins that use the unified manifest for Microsoft 365 are *directly* supported in Office on the web, in [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627), and in Office on Windows connected to a Microsoft 365 subscription, Version 2304 (Build 16320.00000) or later. When the app package that contains the unified manifest is sideloaded to a platform that doesn't directly support that type of manifest then an add-in only manifest is generated from the unified manifest and this manifest is the one that's sideloaded. - [Sideload Office Add-ins in Office on the web](sideload-office-add-ins-for-testing.md) - [Sideload Office Add-ins on Windows](test-debug-non-local-server.md) diff --git a/docs/testing/testing-and-troubleshooting.md b/docs/testing/testing-and-troubleshooting.md index 80c91a0d94..7262c351aa 100644 --- a/docs/testing/testing-and-troubleshooting.md +++ b/docs/testing/testing-and-troubleshooting.md @@ -1,8 +1,8 @@ ---- +--- title: Troubleshoot user errors with Office Add-ins description: Learn how to troubleshoot user errors in Office Add-ins. ms.topic: troubleshooting-problem-resolution -ms.date: 07/08/2024 +ms.date: 06/23/2025 ms.localizationpriority: medium --- @@ -18,8 +18,9 @@ The following table lists common error messages that users might encounter and s |Error message|Resolution| |:-----|:-----| -|App error: Catalog could not be reached|Verify firewall settings."Catalog" refers to AppSource. This message indicates that the user cannot access AppSource.| +|App error: Catalog could not be reached|Verify firewall settings."Catalog" refers to Microsoft Marketplace. This message indicates that the user cannot access Microsoft Marketplace.| |APP ERROR: This app could not be started. Close this dialog to ignore the problem or click "Restart" to try again.|Verify that the latest Office updates are installed, or update with the [Windows Installer](/officeupdates/office-updates-msi).| +|Error: Access denied. `E_ACCESSDENIED (0x80070005)` | The antivirus software installed on the machine might prevent the host app from creating a WebView2 process. To resolve this issue, add an exemption or exclusion to the antivirus for the `.exe` files in the Office root folder (`C:\Program Files\Microsoft Office\root\Office16`) or for the entire Office root folder. If this does not fix the issue, add an exemption or exclusion for the WebView2 process (`C:\Program Files (x86)\Microsoft\EdgeWebView\Application[latest installed version]\msedgewebview2.exe`). | |Error: Object doesn't support property or method 'defineProperty'|Confirm that Internet Explorer is not running in Compatibility Mode. Go to **Tools** > **Compatibility View Settings**.| |Sorry, we couldn't load the app because your browser version is not supported. Click here for a list of supported browser versions.|Make sure that the browser supports HTML5 local storage, or reset your Internet Explorer settings. For information about supported browsers, see [Requirements for running Office Add-ins](../concepts/requirements-for-running-office-add-ins.md).| diff --git a/docs/testing/troubleshoot-development-errors.md b/docs/testing/troubleshoot-development-errors.md index 44309a2755..c194fd201c 100644 --- a/docs/testing/troubleshoot-development-errors.md +++ b/docs/testing/troubleshoot-development-errors.md @@ -1,8 +1,8 @@ ---- +--- title: Troubleshoot development errors with Office Add-ins description: Learn how to troubleshoot development errors in Office Add-ins. ms.topic: troubleshooting-problem-resolution -ms.date: 08/15/2024 +ms.date: 02/12/2025 ms.localizationpriority: medium --- @@ -78,11 +78,14 @@ myChart.id = "5"; The following are some of the causes of this error. If you discover additional causes, please tell us with the feedback tool at the bottom of the page. -- If you are using Visual Studio, there may be a problem with the sideloading. Close all instances of the Office host and Visual Studio. Restart Visual Studio and try pressing F5 again. +- If you're using Visual Studio, there may be a problem with the sideloading. Close all instances of the Office host and Visual Studio. Restart Visual Studio and try pressing <kbd>F5</kbd> again. - The add-in's manifest has been removed from its deployment location, such as Centralized Deployment, a SharePoint catalog, or a network share. -- The value of the [ID](/javascript/api/manifest/id) element in the manifest has been changed directly in the deployed copy. If for any reason, you want to change this ID, first remove the add-in from the Office host, then replace the original manifest with the changed manifest. You many need to clear the Office cache to remove all traces of the original. See the [Clear the Office cache](clear-cache.md) article for instructions on clearing the cache for your operating system. -- The add-in's manifest has a `resid` that is not defined anywhere in the [Resources](/javascript/api/manifest/resources) section of the manifest, or there is a mismatch in the spelling of the `resid` between where it is used and where it is defined in the **\<Resources\>** section. -- There is a `resid` attribute somewhere in the manifest with more than 32 characters. A `resid` attribute, and the `id` attribute of the corresponding resource in the **\<Resources\>** section, cannot be more than 32 characters. +- If the add-in only manifest is being used, one of the following may apply. + + - The value of the [ID](/javascript/api/manifest/id) element in the manifest has been changed directly in the deployed copy. If for any reason, you want to change this ID, first remove the add-in from the Office host, then replace the original manifest with the changed manifest. You many need to clear the Office cache to remove all traces of the original. See the [Clear the Office cache](clear-cache.md) article for instructions on clearing the cache for your operating system. + - The add-in's manifest has a `resid` that isn't defined anywhere in the [Resources](/javascript/api/manifest/resources) section of the manifest, or there is a mismatch in the spelling of the `resid` between where it is used and where it is defined in the `<Resources>` section. + - There is a `resid` attribute somewhere in the manifest with more than 32 characters. A `resid` attribute, and the `id` attribute of the corresponding resource in the `<Resources>` section, cannot be more than 32 characters. + - The add-in has a custom Add-in Command but you are trying to run it on a platform that doesn't support them. For more information, see [Add-in commands requirement sets](/javascript/api/requirement-sets/common/add-in-commands-requirement-sets). ## Add-in doesn't work on Edge but it works on other browsers @@ -97,9 +100,9 @@ See [Troubleshoot Excel add-ins](../excel/excel-add-ins-troubleshooting.md) for See [Troubleshoot Word add-ins](../word/word-add-ins-troubleshooting.md) for possible causes. -## Manifest schema validation errors in Visual Studio projects +## Add-in only manifest schema validation errors in Visual Studio projects -If you're using newer features that require changes to the manifest file, you may get validation errors in Visual Studio. For example, when adding the **\<Runtimes\>** element to implement the [shared runtime](runtimes.md#shared-runtime), you may see the following validation error. +If you're using newer features that require changes to the add-in only manifest file, you may get validation errors in Visual Studio. For example, when adding the `<Runtimes>` element to implement the [shared runtime](runtimes.md#shared-runtime), you may see the following validation error. **The element 'Host' in namespace 'http://schemas.microsoft.com/office/taskpaneappversionoverrides' has invalid child element 'Runtimes' in namespace 'http://schemas.microsoft.com/office/taskpaneappversionoverrides'** @@ -109,7 +112,7 @@ If this occurs, you can update the XSD files that Visual Studio uses to the late 1. Open your project in Visual Studio. 1. In **Solution Explorer**, open the manifest.xml file. The manifest is typically in the first project under your solution. -1. Select **View** > **Properties Window** (F4). +1. Select **View** > **Properties Window** (<kbd>F4</kbd>). 1. Set the cursor selection in the manifest.xml so that the **Properties** window shows the **XML Document** properties. 1. In the **Properties** window, select the **Schemas** property, then select the ellipsis (...) to open the **XML Schemas** editor. Here you can find the exact folder location of all schema files your project uses. diff --git a/docs/testing/troubleshoot-event-based-and-spam-reporting-add-ins.md b/docs/testing/troubleshoot-event-based-and-spam-reporting-add-ins.md new file mode 100644 index 0000000000..b9c8ddfd47 --- /dev/null +++ b/docs/testing/troubleshoot-event-based-and-spam-reporting-add-ins.md @@ -0,0 +1,108 @@ +--- +title: Troubleshoot event-based and spam-reporting add-ins +description: Learn how to troubleshoot development errors in Office Add-ins that implement event-based activation or integrated spam reporting. +ms.date: 10/14/2025 +ms.topic: troubleshooting +ms.localizationpriority: medium +--- + +# Troubleshoot event-based and spam-reporting add-ins + +As you develop your [event-based](../develop/event-based-activation.md) or [spam-reporting](../outlook/spam-reporting.md) add-in, you may encounter issues, such as your add-in not loading or an event not occurring. The following sections provide guidance on how to troubleshoot your add-in. + +## Review feature prerequisites + +- Verify that the add-in is installed on a supported client. Some clients only support certain events or aspects of event-based activation or integrated spam reporting. For more information, see [Supported events](../develop/event-based-activation.md#supported-events) and [Implement an integrated spam-reporting add-in](../outlook/spam-reporting.md). +- Verify that your client supports the minimum requirement set needed. The integrated spam reporting feature was introduced in [requirement set 1.14](/javascript/api/requirement-sets/outlook/requirement-set-1.14/outlook-requirement-set-1.14). See the [Supported Events](../develop/event-based-activation.md#supported-events) for details about build numbers and requirement sets for event-based activation. +- Review the expected behavior and limitations of the feature. + + - [Event-based activation behavior and limitations](../develop/event-based-activation.md#behavior-and-limitations) + - [Smart Alerts behavior and scenarios](../outlook/onmessagesend-onappointmentsend-events.md#smart-alerts-feature-behavior-and-scenarios) + - [Integrated spam-reporting behavior and limitations](../outlook/spam-reporting.md#review-feature-behavior-and-limitations) + +## Check manifest and JavaScript requirements + +- Ensure that the following conditions are met in your add-in's manifest. + + - Verify that your add-in's source file location URL is publicly available and isn't blocked by a firewall. This URL is specified in the [SourceLocation element](/javascript/api/manifest/sourcelocation) of the add-in only manifest or the [`"extensions.runtimes.code.page"`](/microsoft-365/extensibility/schema/extension-runtime-code#page) property of the unified manifest for Microsoft 365. + - Verify that the `<Runtimes>` element (add-in only manifest) or `"extensions.runtimes.code"` property (unified manifest) correctly references the HTML or JavaScript file containing the event handlers. Classic Outlook on Windows and other Windows-based Office applications use the JavaScript file during runtime, while Office on the web, the new Outlook Mac UI, and [new Outlook on Windows](https://support.microsoft.com/office/656bb8d9-5a60-49b2-a98b-ba7822bc7627) use the HTML file. For an example of how this is configured in the manifest, see the "Configure the manifest" section of [Automatically set the subject of a new message or appointment](../outlook/on-new-compose-events-walkthrough.md#configure-the-manifest). + + For Windows clients (except for new Outlook on Windows), you must bundle all your event-handling JavaScript code into this JavaScript file referenced in the manifest. Note that a large JavaScript bundle may cause issues with the performance of your add-in. We recommend preprocessing heavy operations, so that they're not included in your event-handling code. + +- For Windows clients (except for new Outlook on Windows), when the JavaScript function specified in the manifest to handle an event runs, code in `Office.onReady()` and `Office.initialize` isn't run. We recommend adding any startup logic needed by event handlers, such as checking the user's client version, to the event handlers instead. + +- Verify that your event-handling JavaScript file calls `Office.actions.associate`. This ensures that the event handler name specified in the manifest is mapped to its JavaScript counterpart. The following code is an example. + + ```js + Office.actions.associate("onNewMessageComposeHandler", onNewMessageComposeHandler); + ``` + +- In classic Outlook on Windows versions prior to Version 2403 (Build 17425.20000), the JavaScript code of event-based and spam-reporting add-ins only supports [ECMAScript 2016](https://262.ecma-international.org/7.0/) and earlier specifications. Some examples of programming syntax to avoid are as follows. + - Avoid using `async` and `await` statements in your code. Including these in your JavaScript code will cause the add-in to time out. + - Avoid using the [conditional (ternary) operator](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) as it will prevent your add-in from loading. + + If your add-in has only one JavaScript file referenced by Outlook on the web, on Windows (new and classic), and on Mac, you must limit your code to ECMAScript 2016 to ensure that your add-in runs in earlier versions of classic Outlook on Windows. However, if you have a separate JavaScript file referenced by Outlook on the web, on Mac, recent versions of classic Outlook on Windows, and the new Outlook on Windows, you can implement a later ECMAScript specification in that file. + +## Check your webpack configuration + +On Windows clients (except for the new Outlook on Windows), if your event-based add-in uses webpack to bundle files and the event handlers never run, configure your add-in's webpack dev server to serve static files. This approach prevents webpack from adding code to your add-in's files that may be incompatible with the JavaScript runtime. Configure your add-in to use static files as follows: + +1. In the `webpack.config.js` file of your add-in, import the Node.js `path` module. + + ```javascript + const path = require("path"); + ``` + +1. In the same file, configure the webpack dev server to serve static files from the `dist` folder. + + ```javascript + ... + devServer: { + static: { + directory: path.join(__dirname, "dist"), + publicPath: "/public", + }, + ... + } + ... + ``` + +1. Run `npm run build`. +1. In your add-in's manifest, update the path to the event-handling JavaScript file to reference the built file served from the static directory. For example, `https://localhost:3000/public/launchevent.js`. + +## Debug your add-in + +- As you make changes to your add-in, be aware that: + - If you update the manifest, remove the add-in, then sideload it again. For information on how to remove a sideloaded add-in from Outlook, see [Sideload Outlook add-ins for testing](../outlook/sideload-outlook-add-ins-for-testing.md#remove-a-sideloaded-add-in). If you're using Outlook on Windows, you must also close and reopen Outlook. + - If you make changes to files other than the manifest, close and reopen the Office client on Windows or on Mac, or refresh the browser tab running Office on the web. + - If you're still unable to see your changes after performing these steps, [clear your Office cache](../testing/clear-cache.md). +- As you test your add-in in Office on Windows (excluding the new Outlook on Windows): + - For event-based add-ins, check [Event Viewer](/shows/inside/event-viewer) for any reported add-in errors. + 1. In Event Viewer, select **Windows Logs** > **Application**. + 1. From the **Actions** panel, select **Filter Current Log**. + 1. From the **Logged** dropdown, select your preferred log time frame. + 1. Select the **Error** checkbox. + 1. In the **Event IDs** field, enter **63**. + 1. Select **OK** to apply your filters. + + :::image type="content" source="../images/outlook-event-based-logs.png" alt-text="A sample of Event Viewer's Filter Current Log settings configured to only show Outlook errors with event ID 63 that occurred in the last hour."::: + + - Verify that the **bundle.js** file is downloaded to the following folder in File Explorer. The text enclosed in `[]` represents your applicable Office and add-in information. + + ```text + %LOCALAPPDATA%\Microsoft\Office\16.0\Wef\{[Office profile GUID]}\[Office account encoding]\Javascript\[Add-in ID]_[Add-in Version]_[locale] + ``` + + [!INCLUDE [office-bundle-js](../includes/office-bundle-js.md)] + +- As you test your add-in on desktop clients (excluding new Outlook on Windows) enable runtime logging to identify possible manifest and add-in installation issues. For guidance on how to use runtime logging, see [Debug your add-in with runtime logging](../testing/runtime-logging.md). +- Set breakpoints in your code to debug your add-in. For platform-specific instructions, see [Debug event-based and spam-reporting add-ins](debug-autolaunch.md). + +## Seek additional help + +If you still need help after performing the recommended troubleshooting steps, [open a GitHub issue](https://github.com/OfficeDev/office-js/issues/new?assignees=&labels=&template=bug_report.md&title=). Include screenshots, video recordings, or runtime logs to supplement your report. + +## See also + +- [Activate add-ins with events](../develop/event-based-activation.md) +- [Implement an integrated spam-reporting add-in](../outlook/spam-reporting.md) diff --git a/docs/testing/troubleshoot-manifest.md b/docs/testing/troubleshoot-manifest.md index c27f792878..a8aecd331a 100644 --- a/docs/testing/troubleshoot-manifest.md +++ b/docs/testing/troubleshoot-manifest.md @@ -1,7 +1,7 @@ --- title: Validate an Office Add-in's manifest description: Learn how to validate the manifest of an Office Add-in. -ms.date: 04/12/2024 +ms.date: 05/19/2025 ms.localizationpriority: medium --- @@ -14,7 +14,7 @@ You should validate your add-in's manifest file to ensure that it's correct and ## Validate your manifest with the validate command -If you used the [Teams Toolkit](../develop/teams-toolkit-overview.md) or [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md) to create your add-in, you can validate your project's manifest file with the following command in the root directory of your project. +If you used [Microsoft 365 Agents Toolkit](../develop/agents-toolkit-overview.md) or [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md) to create your add-in, you can validate your project's manifest file with the following command in the root directory of your project. ```command line npm run validate @@ -30,7 +30,7 @@ npx office-addin-manifest validate -p MANIFEST_FILE ## Validate your manifest with office-addin-manifest -If you didn't use the [Teams Toolkit](../develop/teams-toolkit-overview.md) or [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md) to create your add-in, you can validate the manifest by using [office-addin-manifest](https://www.npmjs.com/package/office-addin-manifest). +If you didn't use [Microsoft 365 Agents Toolkit](../develop/agents-toolkit-overview.md) or [Yeoman generator for Office Add-ins](../develop/yeoman-generator-overview.md) to create your add-in, you can validate the manifest by using [office-addin-manifest](https://www.npmjs.com/package/office-addin-manifest). 1. Install [Node.js](https://nodejs.org/download/). @@ -53,9 +53,9 @@ If you didn't use the [Teams Toolkit](../develop/teams-toolkit-overview.md) or [ > npx office-addin-manifest validate MANIFEST_FILE > ``` -## Validate the manifest in the UI of Teams Toolkit +## Validate the manifest in the UI of Agents Toolkit -If you're working in Teams Toolkit and using the unified manifest, you can use the toolkit's validation options. For instructions, see [Validate application](/microsoftteams/platform/toolkit/teamsfx-preview-and-customize-app-manifest#validate-application). +If you're working in Agents Toolkit and using the unified manifest, you can use the toolkit's validation options. For instructions, see [Validate application](/microsoftteams/platform/toolkit/teamsfx-preview-and-customize-app-manifest#validate-application). ## See also diff --git a/docs/testing/uninstall-add-in.md b/docs/testing/uninstall-add-in.md new file mode 100644 index 0000000000..b1ce272dd0 --- /dev/null +++ b/docs/testing/uninstall-add-in.md @@ -0,0 +1,155 @@ +--- +title: Uninstall add-ins under development +description: Learn how to prevent incomplete uninstallation of add-ins you are developing and how to remove incompletely uninstalled add-ins under development. +ms.topic: troubleshooting-problem-resolution +ms.date: 05/19/2025 +ms.localizationpriority: medium +--- + +# Uninstall add-ins under development + +Incompletely removed add-ins can leave artifacts on your computer, such as custom ribbon buttons or registry entries, during development. In this article, we call these "ghost add-ins". + +Outlook add-ins also might add these artifacts to other computers when you sign into Outlook on them with the same ID as you used to develop the add-in. + + > [!IMPORTANT] + > When you sign into Outlook, it downloads from Exchange, and sideloads, all the Outlook add-in manifests that are associated with your ID, *including add-ins that you are developing on a different computer using the same ID*. For example, any custom ribbon buttons defined in the manifest will appear for the add-in. + > + > If the URLs in the manifest point to a non-localhost server and that server is running and accessible to the non-development computer, then Outlook caches the add-in's files in the local file system and the add-in usually runs normally on the computer. Otherwise, the add-in doesn't function, but visible parts of it, such as custom ribbon buttons appear. They have the labels defined in the manifest. The add-in's button icons also appear if they were ever cached locally on the non-development computer and the cache was never cleared. Icon files aren't stored with Exchange, so if they were never cached on the non-development computer (or the cache has been cleared), then the buttons have default icons. + > + > Until the add-in's registration is removed from Exchange, the add-in will continue to appear. See [Remove a ghost add-in](#remove-a-ghost-add-in) for information about removing the registration in Exchange. + +This article provides some guidance to minimize the chance of these problems and to resolve them if they occur. + +## Prevent the problems + +When an add-in is sideloaded, several things happen: + +- A web server, usually on localhost, is started to serve the add-in's files (such as the HTML, CSS, and JavaScript files). +- These same files are cached on your development computer. +- The add-in is registered with the development computer. The registration is done with Registry entries on a Windows computer or with certain files saved to the file system on a Mac. +- Most tools for sideloading add-ins automatically open the Office application that the add-in targets. The tools also populate the application with any custom ribbon buttons or context menu items that are defined in the add-in's manifest. +- For an Outlook add-in, the add-in's manifest is registered with the Exchange service. + +### Use your tool's uninstall facility + +To prevent ghost add-ins, end every testing, debugging, and sideloading session by using the uninstall (also called unacquire) option that is provided by the tool that you used to start the session. Doing this reverses the effects of sideloading, as stated earlier in this article. + +The following list identifies, for each tool, how to uninstall but doesn't describe the procedures or syntax in detail. *Be sure to use the links to get complete instructions.* + +> [!NOTE] +> Some of these tools don't close the Office application that opened automatically. In that case, close the application manually immediately after ending the session. + +- **Yeoman generator for Office Add-ins (Yo Office)**: Use the `npm stop` script at the same command line where you started the session with `npm start`. For more information, see the various articles in the **Get started** and **Quick starts** sections and [Remove a sideloaded add-in](sideload-office-add-ins-for-testing.md). +- **Microsoft 365 Agents Toolkit for Visual Studio Code**: Select **Run** | **Stop Debugging** in Visual Studio Code. For more information, see the last step of [Create an Outlook Add-in project](../tutorials\outlook-tutorial.md#create-an-outlook-add-in-project) which also applies to non-Outlook add-ins. +- **Office Add-in Development Kit for Visual Studio Code**: With the Office Add-in Development Kit extension open, select **Stop Previewing Your Office Add-in**. For more information, see [Stop testing your add-in](../develop/development-kit-overview.md?tabs=vscode#stop-testing-your-office-add-in). +- **office-addin-debugging tool**: Use the `office-addin-debugging stop` command at the same command line where you started the session with `office-addin-debugging start`. For more information, see [Sideload with the Office-Addin-Debugging tool](../testing\sideload-add-in-with-unified-manifest.md#sideload-with-the-office-addin-debugging-tool). +- **Microsoft 365 Agents Toolkit CLI**: Use the `atk uninstall` command at the same command line where you started the session with `atk install`. For more information, see [Sideload with Microsoft 365 Agents Toolkit CLI](../testing\sideload-add-in-with-unified-manifest.md#sideload-with-microsoft-365-agents-toolkit-cli-command-line-interface). +- **Visual Studio**: Select **DEBUG** | **Stop debugging** in the menu, or press <kbd>Shift</kbd>+<kbd>F5</kbd>, or click the square red "stop" button on the debugging bar. Alternatively, closing the Office application also stops the session and uninstalls the add-in. For more information, see [First look at the Visual Studio debugger](/visualstudio/debugger/debugger-feature-tour). + +## Remove a ghost add-in + +To remove a ghost add-in, you need to remove the artifacts that were created when it was last sideloaded, remove its local registration, and for Outlook add-ins remove its registration in Exchange. + +> [!TIP] +> There's a fast way to remove a ghost add-in on Windows computers if the add-in was installed with the Teams Toolkit CLI. Try this first, and if it works, you can skip the remainder of this section. +> +> 1. Obtain the add-in's title ID from the Registry key **HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Wef\Developer\OutlookSideloadManifestPath\TitleId**. (The string "Outlook" is in the key name for historical reasons, but it applies to any add-in installed with the Agents Toolkit CLI.) +> 1. Run the following command in a command prompt, bash shell, or terminal. Replace "{title ID}" with the title ID of the add-in including the "U_" prefix; for example, `U_90d141c6-cf4f-40ee-b714-9df9ea593f39`. +> +> ```command line +> atk uninstall --mode title-id --title-id {title ID} --interactive false +> ``` + +The process for removing the add-in varies depending on whether the add-in is for Outlook or some other Office application. + +> [!NOTE] +> In the [unified manifest for Microsoft 365](../develop/unified-manifest-overview.md), an add-in can be configured to support Outlook and one or more other Office applications; that is, there's more than one member of the [`"extensions.requirements.scopes"`](/microsoft-365/extensibility/schema/requirements-extension-element#scopes) array in the manifest and one of the members is `"mail"` (or the `"extensions.requirements.scopes"` property isn't present). Treat an add-in that is configured in this way as an Outlook add-in. + +If the ghost add-in is not an Outlook add-in, skip to the section [Remove the add-in artifacts](#remove-the-add-in-artifacts). + +### Remove the Exchange registration of a ghost Outlook add-in + +1. Log into Outlook with the same ID you used when you sideloaded the add-in. +1. Open PowerShell as an Administrator. +1. Run the following commands. Answer "Yes" to all confirmation prompts. + + ```powershell + Install-Module -Name ExchangeOnlineManagement -RequiredVersion 3.4.0 + Set-ExecutionPolicy RemoteSigned + Connect-ExchangeOnline + ``` + + > [!NOTE] + > If the `Connect-ExchangeOnline` command returns the error "ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment", just run the command a second time. This is a well-known bug. + +1. Run the following command. Answer "Yes" to all confirmation prompts. + + ```powershell + Get-App | Format-Table -Auto DisplayName,AppId + ``` + + A list of the add-ins installed on Outlook displays. These will include built-in Microsoft add-ins and add-ins you have installed. Any ghost Outlook add-ins will also be listed. + +1. Find the ghost add-in in the list. If it was created with Yo Office or another Microsoft tool, it probably has the name "Contoso Task Pane Add-in". +1. Copy the App ID (a GUID) of the add-in. You need it for later steps. +1. Run the command `Remove-App -Identity {{The GUID OF YOUR ADD-IN HERE}}` (e.g., `Remove-App -Identity 26ead0cb-10dd-4ba2-86c6-4db111876652`). This command removes the add-in from Exchange. + + > [!WARNING] + > The removal of the registration needs to propagate to all Exchange servers. Wait at least three hours before continuing with the next step. + +1. Continue with the section [Remove the add-in artifacts](#remove-the-add-in-artifacts). + +### Remove the add-in artifacts + +> [!IMPORTANT] +> Carry out this procedure on all devices on which you have had the add-in sideloaded. + +1. Log out from all Office applications and then close them all, including Outlook. +1. [Clear the Office cache](clear-cache.md). If the ghost add-in supports Outlook, use [Clear the cache in Outlook manually](clear-cache.md#manually-clear-the-cache-in-outlook). +1. Continue with the section [Remove the local registration](#remove-the-local-registration). + +### Remove the local registration + +> [!IMPORTANT] +> Carry out this procedure on all computers on which you have had the add-in sideloaded. + +1. Delete the local registration of the ghost add-in. The process varies depending on the operating system. + + #### [Windows](#tab/windows) + + 1. Open the **Registry Editor**. + 1. Navigate to **Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\WEF\Developer**. This key lists the add-ins that are currently sideloaded, or were sideloaded in the past and weren't fully uninstalled. The **Data** value for each entry is the path to the add-in's manifest. The **Name** value varies depending on which version of which tool was used to create and sideload the add-in. If Visual Studio was used, the name is typically is also the path to the manifest. For other tools, the name is typically the add-in's ID. When an Office application launches, it reloads all add-ins listed in this key (that support the Office application). Reloading may have no practical or discernable effect if the add-in's artifacts have been deleted from the cache, or the manifest no longer exists at the path, or the add-in's files aren't being served by a server. + + Find the entry for the ghost add-in and delete it. If it is an Outlook add-in, then you have the ID from [removing the Exchange registration](#remove-the-exchange-registration-of-a-ghost-outlook-add-in). You can also use the path in the **Data** column to find the manifest to help identify the add-in the entry refers to and read the ID from the manifest. If any manifests listed in the **Data** column no longer exist at the specified path, then delete the entries for those manifests. + + :::image type="content" source="../images/addinRegistrationWindowsManifestPath.png" alt-text="The Windows registry for the key named Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\WEF\Developer." border="false"::: + + 1. Expand the **... Developer** node in the registry tree. Look for a subkey whose name is the same ghost add-in's ID. If it is there, delete it. + + :::image type="content" source="../images/addinRegistrationWindowsDeveloperSubkeys.png" alt-text="The Windows registry for the key named Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\WEF\Developer expanded to show subkeys." border="false"::: + + 1. Navigate to **Computer\HKEY_USERS\\{SID}\Software\Microsoft\Office\16.0\WEF\Developer**, where **{SID}** is the [SID](/windows-server/identity/ad-ds/manage/understand-security-identifiers) of the user you were signed in with when you sideloaded the add-in, and repeat the preceding two steps. + 1. Navigate to **Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Common\CustomUIValidationCache**. In the **Name** column, find all the entries that begin with the add-in's ID (a GUID) and delete them. Then navigate to **Computer\HKEY_USERS\\{SID}\Software\Microsoft\Office\16.0\Common\CustomUIValidationCache**, where **{SID}** is the SID of the user you were signed in with when you sideloaded the add-in, and repeat the process. + + :::image type="content" source="../images/addinRegistrationWindows.png" alt-text="The Windows registry for the key named Computer\HKEY_USERS\SID\Software\Microsoft\Office\16.0\Common\CustomUIValidationCache**, where SID is the SID of a user." border="false"::: + + #### [Mac](#tab/mac) + + For non-Outlook add-ins, the local registration on a Mac is removed when you clear the cache. See [Remove the add-in artifacts](#remove-the-add-in-artifacts). + + For ghost Outlook add-ins, remove the local registration on a Mac by using the **Add-Ins for Outlook** dialog in Outlook. Follow the guidance at [Remove a sideloaded Outlook add-in](../outlook/sideload-outlook-add-ins-for-testing.md#remove-a-sideloaded-add-in). + + --- + +2. If you are removing an Outlook add-in, continue with the section [Test for removal of Outlook add-ins](#test-for-removal-of-outlook-add-ins). + +### Test for removal of Outlook add-ins + +Open Outlook with the same identity you used when you created the add-in. If artifacts from the add-in (such as custom ribbon buttons) reappear after a few minutes or if event handlers from the add-in seem to be active, then the removal of the add-in's registration from Exchange hasn't propagated to all Exchange servers. Wait at least three hours and then repeat the procedures in the sections [Remove the add-in artifacts](#remove-the-add-in-artifacts) and [Remove the local registration](#remove-the-local-registration) on the computer where you observed the artifacts. + +## See also + +- [Troubleshoot development errors with Office Add-ins](troubleshoot-development-errors.md) +- [Clear the Office cache](clear-cache.md) +- The PowerShell reference for [Install-Module](/powershell/module/powershellget/install-module), [Set-ExecutionPolicy](/powershell/module/microsoft.powershell.security/set-executionpolicy), [Connect-ExchangeOnline](/powershell/exchange/connect-to-exchange-online-powershell), and [Get-App](/powershell/module/exchangepowershell/get-app). diff --git a/docs/toc.yml b/docs/toc.yml index 933f35de25..a0c340663f 100644 --- a/docs/toc.yml +++ b/docs/toc.yml @@ -1,4 +1,4 @@ -items: +items: - name: Office Add-ins Documentation href: index.yml @@ -30,11 +30,12 @@ items: href: quickstarts/project-quickstart.md - name: Word add-in href: quickstarts/word-quickstart-yo.md - - name: Single sign-on (SSO) - href: quickstarts/sso-quickstart.md - name: Explore Office JS APIs using Script Lab href: overview/explore-with-script-lab.md displayName: Excel, Word, PowerPoint + - name: Copy Script Lab snippet to Yo Office + href: overview/create-an-office-add-in-from-script-lab.md + displayName: 'code samples' - name: Samples href: overview/office-add-in-code-samples.md displayName: PnP, 'code samples' @@ -96,7 +97,15 @@ items: - name: Reference Office.js href: develop/referencing-the-javascript-api-for-office-library-from-its-cdn.md - name: Specify Office applications and API requirements - href: develop/specify-office-hosts-and-api-requirements.md + items: + - name: Specify Office applications and API requirements with the unified manifest + href: develop/specify-office-hosts-and-api-requirements-unified.md + - name: Specify Office applications and API requirements with the add-in only manifest + href: develop/specify-office-hosts-and-api-requirements.md + - name: Understand and use platform-specific requirement sets + href: develop/platform-specific-requirement-sets.md + - name: Check for API availability at runtime + href: develop/specify-api-requirements-runtime.md - name: Load sequence of an Office Add-in href: develop/loading-the-dom-and-runtime-environment.md - name: Initialize your add-in @@ -110,27 +119,34 @@ items: displayName: manifest - name: Configure your add-in to use a shared runtime href: develop/configure-your-add-in-to-use-a-shared-runtime.md + - name: Implement event-based activation + href: develop/event-based-activation.md + displayName: event-based activation - name: Run code on document open href: develop/run-code-on-document-open.md - name: Manifest items: - name: Overview href: develop/add-in-manifests.md - - name: Office Add-ins with the add-in only manifest - href: develop/xml-manifest-overview.md - - name: Office Add-ins with the unified manifest for Microsoft 365 - href: develop/unified-manifest-overview.md - - name: Compare the add-in only manifest with the unified manifest for Microsoft 365 - href: develop/json-manifest-overview.md - - name: Convert an add-in to use the unified manifest for Microsoft 365 - href: develop/convert-xml-to-json-manifest.md - - name: Add-in only manifest reference - href: reference/manifest-reference.md - - name: Extended overrides - href: develop/extended-overrides.md - - name: Find the proper order of manifest elements - href: develop/manifest-element-ordering.md - displayName: manifest + - name: Unified manifest for Microsoft 365 + items: + - name: Office Add-ins with the unified manifest for Microsoft 365 + href: develop/unified-manifest-overview.md + - name: Compare the add-in only manifest with the unified manifest for Microsoft 365 + href: develop/json-manifest-overview.md + - name: Convert an add-in to use the unified manifest for Microsoft 365 + href: develop/convert-xml-to-json-manifest.md + - name: Add-in only manifest + items: + - name: Office Add-ins with the add-in only manifest + href: develop/xml-manifest-overview.md + - name: Add-in only manifest reference + href: reference/manifest-reference.md + - name: Find the proper order of manifest elements + href: develop/manifest-element-ordering.md + - name: Update API and manifest version + href: develop/update-your-javascript-api-for-office-and-manifest-schema-version.md + displayName: manifest - name: Privacy, security, and storage items: - name: Overview of add-in privacy and security @@ -169,12 +185,16 @@ items: href: develop/troubleshoot-sso-in-office-add-ins.md - name: Enable SSO using nested app authentication href: develop/enable-nested-app-authentication-in-your-add-in.md + - name: Nested app authentication FAQ + href: outlook/faq-nested-app-auth-outlook-legacy-tokens.md - name: Office dialog API href: develop/auth-with-office-dialog-api.md - name: Identity providers href: develop/auth-external-add-ins.md - name: Access Microsoft Graph href: develop/authorize-to-microsoft-graph-without-sso.md + - name: Automatically save passwords in WebView2 + href: develop/auth-save-passwords.md - name: UI and UX items: - name: Overview @@ -189,7 +209,7 @@ items: href: design/accessibility-guidelines.md - name: Data visualization href: design/data-visualization-guidelines.md - - name: Voice + - name: Writing and style href: design/voice-guidelines.md - name: UX design language and patterns items: @@ -231,8 +251,6 @@ items: displayName: first run experience - name: Navigation href: design/navigation-patterns.md - - name: Design toolkits - href: design/design-toolkits.md - name: Interface elements items: - name: Overview @@ -247,7 +265,7 @@ items: href: develop/create-addin-commands-unified-manifest.md - name: Create custom contextual tabs href: design/contextual-tabs.md - - name: Enable and Disable Add-in Commands + - name: Change the availability of add-in commands href: design/disable-add-in-commands.md - name: Integrate built-in Office buttons into custom tabs href: design/built-in-button-integration.md @@ -255,6 +273,17 @@ items: href: design/custom-tab-placement.md - name: Content add-ins href: design/content-add-ins.md + - name: Copilot agents + items: + - name: Combine Copilot Agents with Office Add-ins + href: design/agent-and-add-in-overview.md + displayName: preview + - name: Build your first add-in as a Copilot skill + href: quickstarts/agent-and-add-in-quickstart.md + displayName: preview + - name: Add a Copilot agent to an add-in + href: develop/agent-and-add-in.md + displayName: preview - name: Dialog boxes items: - name: Use the Office dialog API in your Office Add-ins @@ -283,22 +312,48 @@ items: href: develop/development-kit-overview.md - name: Create add-ins with the Yeoman Generator href: develop/yeoman-generator-overview.md - - name: Create add-ins with the Teams Toolkit - href: develop/teams-toolkit-overview.md + - name: Create add-ins with the Microsoft 365 Agents Toolkit + href: develop/agents-toolkit-overview.md + - name: Import an add-in project to Microsoft 365 Agents Toolkit + href: develop/import-teams-toolkit.md - name: Develop add-ins with Visual Studio Code href: develop/develop-add-ins-vscode.md - - name: Create and Develop add-ins with Visual Studio + - name: Create and develop add-ins with Visual Studio items: - name: Overview href: develop/develop-add-ins-visual-studio.md displayName: Visual Studio + - name: Quick starts + items: + - name: Excel + items: + - name: Task pane + href: quickstarts/excel-quickstart-vs.md + displayName: Excel, Visual Studio + - name: Content + href: quickstarts/excel-quickstart-content.md + displayName: Excel, Visual Studio + - name: Outlook + href: quickstarts/outlook-quickstart-vs.md + displayName: Outlook, Visual Studio + - name: PowerPoint + items: + - name: Task pane + href: quickstarts/powerpoint-quickstart-vs.md + displayName: PowerPoint, Visual Studio + - name: Content + href: quickstarts/powerpoint-quickstart-content.md + displayName: PowerPoint, Visual Studio + - name: Word + href: quickstarts/word-quickstart-vs.md + displayName: Word, Visual Studio + - name: PowerPoint presentation tutorial + href: tutorials/powerpoint-tutorial-vs.md + displayName: Visual Studio - name: Get JavaScript IntelliSense in Visual Studio href: develop/get-javascript-intellisense-in-visual-studio.md - name: Convert JavaScript projects to TypeScript href: develop/convert-javascript-to-typescript.md - - name: Copy Script Lab snippet to Yo Office - href: overview/create-an-office-add-in-from-script-lab.md - displayName: 'code samples' - name: Develop add-ins with Angular href: develop/add-ins-with-angular2.md - name: Special requirements for add-ins on the iPad @@ -313,6 +368,8 @@ items: displayName: debug - name: Windows items: + - name: Sideload Office Add-ins that use the unified manifest for Microsoft 365 + href: testing/sideload-add-in-with-unified-manifest.md - name: Sideload Office Add-ins on Windows from a network share href: testing/create-a-network-shared-folder-catalog-for-task-pane-and-content-add-ins.md - name: Attach a debugger from the task pane @@ -350,6 +407,9 @@ items: - name: Clear the Office cache href: testing/clear-cache.md displayName: uninstall, sideload + - name: Uninstall add-in under development + href: testing/uninstall-add-in.md + displayName: uninstall - name: Debug with runtime logging href: testing/runtime-logging.md - name: Debug a function command with a non-shared runtime @@ -366,6 +426,14 @@ items: href: testing/testing-and-troubleshooting.md - name: Troubleshoot development errors href: testing/troubleshoot-development-errors.md + - name: Event-based add-ins + items: + - name: Debug event-based and spam-reporting add-ins + href: testing/debug-autolaunch.md + - name: SSO and CORS in event-based or spam-reporting add-ins + href: develop/use-sso-in-event-based-activation.md + - name: Troubleshoot event-based and spam-reporting add-ins + href: testing/troubleshoot-event-based-and-spam-reporting-add-ins.md - name: Performance items: - name: Avoid using the context.sync method in loops @@ -393,12 +461,19 @@ items: items: - name: Publish your add-in (Visual Studio) href: publish/package-your-add-in-using-visual-studio.md - - name: Stage an Office Add-in on Microsoft Azure + - name: Stage an Office Add-in on Microsoft Azure with Visual Studio href: publish/host-an-office-add-in-on-microsoft-azure.md - - name: Publish add-ins to AppSource + - name: Stage an Outlook add-in on Microsoft Azure with Visual Studio + href: publish/stage-outlook-add-in-azure.md + - name: Publish add-ins to Microsoft Marketplace href: publish/publish-office-add-ins-to-appsource.md - - name: AppSource validation policies + - name: Microsoft Marketplace validation policies href: /legal/marketplace/certification-policies + - name: Publish an add-in that requires admin consent + href: publish/publish-nested-app-auth-add-in.md + - name: Microsoft Marketplace options for add-ins with event-based activation + href: publish/autolaunch-store-options.md + displayName: event-based activation - name: Publish add-ins to a SharePoint app catalog href: publish/publish-task-pane-and-content-add-ins-to-an-add-in-catalog.md - name: Guidance for deploying on government clouds @@ -406,7 +481,7 @@ items: - name: Maintain your Office Add-in href: publish/maintain-breaking-changes.md - name: Trust custom protocol handlers to launch add-ins - href: publish/custom-protocol-handler.md + href: publish/manage-trust-options.md - name: Excel items: @@ -456,6 +531,9 @@ items: - name: Charts href: excel/excel-add-ins-charts.md displayName: Excel + - name: Data labels in charts + href: excel/excel-add-ins-charts-data-labels.md + displayName: Excel - name: Coauthoring in Excel add-ins href: excel/co-authoring-in-excel-add-ins.md displayName: Excel @@ -471,15 +549,27 @@ items: - name: Concepts href: excel/excel-data-types-concepts.md displayName: Excel - - name: Entity value cards + - name: Property values on basic types + href: excel/excel-data-types-add-properties-to-basic-cell-values.md + displayName: Excel + - name: Cards for cell value types href: excel/excel-data-types-entity-card.md displayName: Excel + - name: Linked Entity values + href: excel/excel-data-types-linked-entity-cell-values.md + displayName: Excel + - name: Add reference methods for dot function notation + href: excel/excel-add-ins-dot-functions.md + displayName: Excel - name: Data validation href: excel/excel-add-ins-data-validation.md displayName: Excel - name: Events href: excel/excel-add-ins-events.md displayName: Excel + - name: Notes + href: excel/excel-add-ins-notes.md + displayName: Excel - name: Performance optimization href: excel/performance.md displayName: Excel @@ -506,6 +596,9 @@ items: - name: Set range format href: excel/excel-add-ins-ranges-set-format.md displayName: Excel + - name: Add checkboxes + href: excel/excel-add-ins-ranges-checkboxes.md + displayName: Excel - name: Conditional formatting of ranges href: excel/excel-add-ins-conditional-formatting.md displayName: Excel @@ -551,12 +644,18 @@ items: - name: Tables href: excel/excel-add-ins-tables.md displayName: Excel + - name: Undo support + href: excel/excel-add-ins-undo-capabilities.md + displayName: Excel - name: Workbooks href: excel/excel-add-ins-workbooks.md displayName: Excel - name: Worksheets href: excel/excel-add-ins-worksheets.md displayName: Excel + - name: Worksheet display + href: excel/excel-add-ins-worksheet-display.md + displayName: Excel - name: Troubleshoot Excel add-ins href: excel/excel-add-ins-troubleshooting.md displayName: Excel @@ -573,9 +672,12 @@ items: - name: Custom functions tutorial href: tutorials/excel-tutorial-create-custom-functions.md displayName: Excel, Custom Functions - - name: Share custom function data with the task pane tutorial + - name: Share custom function data with the task pane href: tutorials/share-data-and-events-between-custom-functions-and-the-task-pane-tutorial.md displayName: Excel, Custom Functions + - name: Best practices + href: excel/custom-functions-get-started.md + displayName: Excel, Custom Functions - name: Naming and localization href: excel/custom-functions-naming.md displayName: Excel, Custom Functions @@ -588,27 +690,39 @@ items: - name: Autogenerate JSON metadata href: excel/custom-functions-json-autogeneration.md displayName: Excel, Custom Functions - - name: Batching custom function remote calls - href: excel/custom-functions-batching.md + - name: Manually create JSON metadata + href: excel/custom-functions-json.md displayName: Excel, Custom Functions - - name: Data types - href: excel/custom-functions-data-types-concepts.md + - name: Custom enums + href: excel/custom-functions-custom-enums.md displayName: Excel, Custom Functions - name: Call Excel JavaScript APIs href: excel/call-excel-apis-from-custom-function.md displayName: Excel, Custom Functions - - name: Extend custom functions with XLL user-defined functions - href: excel/make-custom-functions-compatible-with-xll-udf.md + - name: Data types + href: excel/custom-functions-data-types-concepts.md displayName: Excel, Custom Functions - - name: Manually create JSON metadata - href: excel/custom-functions-json.md + - name: Work with formula value preview + href: excel/custom-functions-formula-value-preview.md + displayName: Excel, Custom Functions + - name: Batch custom function remote calls + href: excel/custom-functions-batching.md + displayName: Excel, Custom Functions + - name: Extend custom functions with XLL add-ins + href: excel/make-custom-functions-compatible-with-xll-udf.md displayName: Excel, Custom Functions - name: Return a dynamic array href: excel/custom-functions-dynamic-arrays.md displayName: Excel, Custom Functions + - name: Volatile functions + href: excel/custom-functions-volatile.md + displayName: Excel, Custom Functions + - name: Web requests + href: excel/custom-functions-web-reqs.md + displayName: Excel, Custom Functions - name: Custom functions without a shared runtime items: - - name: Authentication for custom functions without a shared runtime + - name: Authentication href: excel/custom-functions-authentication.md displayName: Excel, Custom Functions - name: JavaScript-only runtime for custom functions @@ -617,13 +731,7 @@ items: - name: Debugging href: excel/custom-functions-debugging.md displayName: Excel, Custom Functions - - name: Volatile functions - href: excel/custom-functions-volatile.md - displayName: Excel, Custom Functions - - name: Web requests - href: excel/custom-functions-web-reqs.md - displayName: Excel, Custom Functions - - name: Troubleshooting + - name: Troubleshoot custom functions href: excel/custom-functions-troubleshooting.md displayName: Excel, Custom Functions @@ -666,6 +774,8 @@ items: displayName: Outlook - name: Develop Outlook add-ins for the new Outlook on Windows href: outlook/one-outlook.md + - name: Outlook add-in design guidelines + href: outlook/outlook-addin-design.md - name: Outlook JavaScript API displayName: Outlook items: @@ -678,18 +788,36 @@ items: - name: API reference - latest release href: reference/outlook-api-reference-latest.md displayName: Outlook - - name: Add-in requirements - href: outlook/add-in-requirements.md - - name: Outlook add-in design guidelines - href: outlook/outlook-addin-design.md + - name: Understanding add-in permissions + href: outlook/understanding-outlook-add-in-permissions.md + - name: Add-ins for Outlook on mobile devices + items: + - name: Overview + href: outlook/outlook-mobile-addins.md + displayName: outlook, add-ins, mobile + - name: Add support for Outlook on mobile devices + href: outlook/add-mobile-support.md + displayName: outlook, add-ins, mobile + - name: Outlook JavaScript API support on mobile devices + href: outlook/outlook-mobile-apis.md + displayName: outlook, add-ins, mobile + - name: Log appointment notes on mobile + href: outlook/mobile-log-appointments.md + displayName: outlook, add-ins, mobile + - name: Event-based activation in Outlook on mobile devices + href: outlook/mobile-event-based.md + displayName: outlook, add-ins, mobile, event-based activation - name: Event-based activation items: - name: Implement an event-based add-in - href: outlook/autolaunch.md + href: develop/event-based-activation.md displayName: event-based activation - name: Implement Smart Alerts to handle on-send events href: outlook/onmessagesend-onappointmentsend-events.md displayName: event-based activation + - name: Event-based activation in Outlook on mobile devices + href: outlook/mobile-event-based.md + displayName: event-based activation, mobile - name: Set the subject of a new mail item href: outlook/on-new-compose-events-walkthrough.md displayName: event-based activation @@ -699,15 +827,15 @@ items: - name: Update your signature when switching between accounts href: outlook/onmessagefromchanged-onappointmentfromchanged-events.md displayName: event-based activation - - name: Troubleshoot event-based and spam-reporting add-ins - href: outlook/troubleshoot-event-based-and-spam-reporting-add-ins.md - - name: AppSource options - href: outlook/autolaunch-store-options.md - displayName: event-based activation + - name: Create an encryption add-in + href: outlook/encryption-decryption.md + displayName: preview - name: Implement a spam reporting add-in href: outlook/spam-reporting.md - name: Activate add-in without Reading Pane or selected message href: outlook/contextless.md + - name: Drag and drop items into a task pane + href: outlook/drag-drop-items.md - name: Item multi-select href: outlook/item-multi-select.md - name: Pinnable task pane @@ -717,25 +845,36 @@ items: - name: Shared folders and shared mailboxes href: outlook/delegate-access.md displayName: delegate access - - name: Add-ins for Outlook on mobile devices - items: - - name: Overview - href: outlook/outlook-mobile-addins.md - displayName: outlook, add-ins, mobile - - name: Add support for Outlook on mobile devices - href: outlook/add-mobile-support.md - displayName: outlook, add-ins, mobile - - name: Outlook JavaScript API support on mobile devices - href: outlook/outlook-mobile-apis.md - displayName: outlook, add-ins, mobile - - name: Log appointment notes on mobile - href: outlook/mobile-log-appointments.md - displayName: outlook, add-ins, mobile - - name: Event-based activation in Outlook on mobile devices - href: outlook/mobile-event-based.md - displayName: outlook, add-ins, mobile, event-based activation - name: Create an online meeting add-in href: outlook/online-meeting.md + - name: Manage sensitivity labels + href: outlook/sensitivity-label.md + - name: Manage notifications + href: outlook/notifications.md + - name: Get or set body + href: outlook/insert-data-in-the-body.md + - name: Add and remove attachments + href: outlook/add-and-remove-attachments-to-an-item-in-a-compose-form.md + - name: Get attachments from server + href: outlook/get-attachments-of-an-outlook-item.md + - name: Get and set recipients + href: outlook/get-set-or-add-recipients.md + - name: Get and set subject + href: outlook/get-or-set-the-subject.md + - name: Manage delivery time of a message + href: outlook/delay-delivery.md + - name: Get or set add-in metadata + href: outlook/metadata-for-an-outlook-add-in.md + - name: Get or set internet headers + href: outlook/internet-headers.md + - name: Get or set categories + href: outlook/categories.md + - name: Get and set location + href: outlook/get-or-set-the-location-of-an-appointment.md + - name: Get or set recurrence + href: outlook/get-and-set-recurrence.md + - name: Get and set times + href: outlook/get-or-set-the-time-of-an-appointment.md - name: Contextual add-ins items: - name: Overview @@ -746,54 +885,14 @@ items: href: outlook/extension-module-outlook-add-ins.md - name: On-send add-ins href: outlook/outlook-on-send-addins.md - - name: Call Outlook REST APIs - href: outlook/use-rest-api.md - - name: Call Exchange web services - href: outlook/web-services.md - - name: Get or set item data - href: outlook/item-data.md - - name: Get or set categories - href: outlook/categories.md - - name: Get or set internet headers - href: outlook/internet-headers.md - - name: Get or set recurrence - href: outlook/get-and-set-recurrence.md - - name: Get or set add-in metadata - href: outlook/metadata-for-an-outlook-add-in.md - - name: Read scenario - items: - - name: Overview - href: outlook/read-scenario.md - - name: Get attachments - href: outlook/get-attachments-of-an-outlook-item.md - - name: Compose scenario + - name: External API integration items: - - name: Overview - href: outlook/compose-scenario.md - - name: Add and remove attachments - href: outlook/add-and-remove-attachments-to-an-item-in-a-compose-form.md - - name: Get and set item data - href: outlook/get-and-set-item-data-in-a-compose-form.md - - name: Get and set recipients - href: outlook/get-set-or-add-recipients.md - - name: Insert data in the body - href: outlook/insert-data-in-the-body.md - - name: Get and set subject - href: outlook/get-or-set-the-subject.md - - name: Get and set times - href: outlook/get-or-set-the-time-of-an-appointment.md - - name: Get and set location - href: outlook/get-or-set-the-location-of-an-appointment.md - - name: Manage sensitivity labels - href: outlook/sensitivity-label.md - - name: Manage delivery time of a message - href: outlook/delay-delivery.md - - name: Privacy and security - items: - - name: Overview - href: outlook/privacy-and-security.md - - name: Understanding add-in permissions - href: outlook/understanding-outlook-add-in-permissions.md + - name: Call the Microsoft Graph API + href: outlook/microsoft-graph.md + - name: Call Exchange web services + href: outlook/web-services.md + - name: Call Outlook REST APIs + href: outlook/use-rest-api.md - name: Authentication items: - name: Overview @@ -801,7 +900,7 @@ items: - name: Authenticate with SSO token href: outlook/authenticate-a-user-with-an-sso-token.md - name: SSO and CORS in event-based or spam-reporting add-ins - href: outlook/use-sso-in-event-based-activation.md + href: develop/use-sso-in-event-based-activation.md - name: Authenticate with an identity token href: outlook/authenticate-a-user-with-an-identity-token.md - name: Validate an identity token @@ -809,9 +908,7 @@ items: - name: Inside the identity token href: outlook/inside-the-identity-token.md - name: "Scenario: Implement single sign-on" - href: outlook/implement-sso-in-outlook-add-in.md - - name: Legacy token deprecation FAQ - href: outlook/faq-nested-app-auth-outlook-legacy-tokens.yml + href: outlook/implement-sso-in-outlook-add-in.md - name: Testing and tips items: - name: Overview @@ -825,9 +922,9 @@ items: - name: Debug function commands href: outlook/debug-ui-less.md - name: Troubleshoot event-based and spam-reporting add-ins - href: outlook/troubleshoot-event-based-and-spam-reporting-add-ins.md + href: testing/troubleshoot-event-based-and-spam-reporting-add-ins.md - name: Debug event-based and spam-reporting add-ins - href: outlook/debug-autolaunch.md + href: testing/debug-autolaunch.md - name: Tips for handling date values href: outlook/tips-for-handling-date-values-in-outlook-add-ins.md @@ -848,7 +945,7 @@ items: href: quickstarts/powerpoint-quickstart-content.md displayName: PowerPoint - name: PowerPoint add-in tutorial - href: tutorials/powerpoint-tutorial.md + href: tutorials/powerpoint-tutorial-yo.md displayName: PowerPoint - name: JavaScript API for PowerPoint items: @@ -858,6 +955,9 @@ items: - name: API reference href: reference/powerpoint-api-reference.md displayName: PowerPoint + - name: PowerPoint object model + href: powerpoint/core-concepts.md + displayName: PowerPoint - name: Add and delete slides href: powerpoint/add-slides.md displayName: PowerPoint @@ -876,7 +976,12 @@ items: - name: Work with shapes href: powerpoint/shapes.md displayName: PowerPoint - + - name: Bind shapes to a data source + href: powerpoint/bind-shapes-in-presentation.md + displayName: PowerPoint + - name: Work with tables + href: powerpoint/work-with-tables.md + displayName: PowerPoint - name: Project items: - name: Project add-ins documentation @@ -894,11 +999,8 @@ items: - name: Visio items: - - name: Visio documentation - href: visio/index.yml - displayName: Visio - name: Overview - href: reference/overview/visio-javascript-reference-overview.md + href: visio/visio-overview.md displayName: Visio - name: API reference href: reference/visio-api-reference.md @@ -924,6 +1026,9 @@ items: - name: 'Sample: Manage citations' href: word/citation-management.md displayName: Word + - name: 'Walkthrough: Add headers when a document opens' + href: word/add-headers-on-document-open.md + displayName: Word - name: Word JavaScript API items: - name: Overview @@ -944,6 +1049,12 @@ items: - name: Read and write data to the active selection href: develop/read-and-write-data-to-the-active-selection-in-a-document-or-spreadsheet.md displayName: Word + - name: Use annotations + href: word/annotations.md + displayName: Word + - name: Use fields + href: word/fields-guidance.md + displayName: Word - name: Use search options to find text href: word/search-option-guidance.md displayName: Word @@ -960,33 +1071,11 @@ items: items: - name: VSTO add-in developers' guide to Office Add-ins href: overview/learning-path-transition.md - - name: Quick starts - items: - - name: Excel - items: - - name: Task pane - href: quickstarts/excel-quickstart-vs.md - displayName: Excel - - name: Content - href: quickstarts/excel-quickstart-content.md - displayName: Excel - - name: Outlook - href: quickstarts/outlook-quickstart-vs.md - displayName: Outlook - - name: PowerPoint - items: - - name: Task pane - href: quickstarts/powerpoint-quickstart-vs.md - displayName: PowerPoint - - name: Content - href: quickstarts/powerpoint-quickstart-content.md - displayName: PowerPoint - - name: Word - href: quickstarts/word-quickstart-vs.md - displayName: Word + - name: Warnings and dependencies in the Node.js and npm world + href: overview/npm-warnings-advice.md - name: Share code from VSTO Add-in to Office Add-in href: tutorials/migrate-vsto-to-office-add-in-shared-code-library-tutorial.md - - name: Make your Office Add-in compatible with an existing COM add-in + - name: Make your Office Add-in compatible with an existing COM or VSTO add-in href: develop/make-office-add-in-compatible-with-existing-com-add-in.md displayName: manifest - name: Resources @@ -1000,6 +1089,8 @@ items: - name: External resources href: resources/resources-links-help.md displayName: Excel, Word, OneNote, Project, PowerPoint, Visio, Outlook + - name: Known issues + href: resources/resources-office-add-in-known-issues.md - name: Office Add-ins community call href: overview/office-add-ins-community-call.md diff --git a/docs/tutorials/excel-tutorial-create-custom-functions.md b/docs/tutorials/excel-tutorial-create-custom-functions.md index e8f059dbe8..58ef98d767 100644 --- a/docs/tutorials/excel-tutorial-create-custom-functions.md +++ b/docs/tutorials/excel-tutorial-create-custom-functions.md @@ -1,7 +1,7 @@ --- title: Excel custom functions tutorial description: In this tutorial, you will create an Excel add-in that contains a custom function that can perform calculations, request web data, or stream web data. -ms.date: 12/11/2023 +ms.date: 12/26/2024 ms.service: excel #Customer intent: As an add-in developer, I want to create custom functions in Excel to increase user productivity. ms.localizationpriority: high @@ -39,8 +39,6 @@ In this tutorial, you will: The Yeoman generator will create the project files and install supporting Node components. - [!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - 1. Navigate to the root folder of the project. ```command line @@ -60,11 +58,7 @@ In this tutorial, you will: # [Excel on Windows or Mac](#tab/excel-windows) -To test your add-in in Excel on Windows or Mac, run the following command. When you run this command, the local web server will start and Excel will open with your add-in loaded. - -```command line -npm run start:desktop -``` +The command to test your add-in in Excel on Windows or Mac depends on when the project was created. If the `"scripts"` section of the project's package.json file has a "start:desktop" script, then run `npm run start:desktop`; otherwise, run the command `npm run start`. The local web server will start and Excel will open with your add-in loaded. [!INCLUDE [alert use https](../includes/alert-use-https.md)] @@ -72,7 +66,7 @@ npm run start:desktop To test your add-in in Excel on the web, run the following command. When you run this command, the local web server will start. Replace "{url}" with the URL of an Excel document on your OneDrive or a SharePoint library to which you have permissions. -[!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] +[!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] [!INCLUDE [alert use https](../includes/alert-use-https.md)] @@ -86,7 +80,7 @@ Next, try out the `ADD` custom function by completing the following steps. 1. In Excel, go to any cell and enter `=CONTOSO`. Notice that the autocomplete menu shows the list of all functions in the `CONTOSO` namespace. -1. Run the `CONTOSO.ADD` function, with numbers `10` and `200` as input parameters, by typing the value `=CONTOSO.ADD(10,200)` in the cell and pressing enter. +1. Run the `CONTOSO.ADD` function, with numbers `10` and `200` as input parameters, by typing the value `=CONTOSO.ADD(10,200)` in the cell and pressing <kbd>Enter</kbd>. The `ADD` custom function computes the sum of the two numbers that you provided and returns the result of **210**. @@ -147,19 +141,19 @@ Integrating data from the Web is a great way to extend Excel through custom func :::image type="content" source="../images/excel-cf-select-add-in.png" alt-text="The My Add-ins dialog that shows active add-ins, with the My custom function add-in button highlighted."::: -1. Try out the new function. In cell **B1**, type the text **=CONTOSO.GETSTARCOUNT("OfficeDev", "Office-Add-in-Samples")** and press Enter. You should see that the result in cell **B1** is the current number of stars given to the [Office-Add-in-Samples repository](https://github.com/OfficeDev/Office-Add-in-Samples). +1. Try out the new function. In cell **B1**, type the text **=CONTOSO.GETSTARCOUNT("OfficeDev", "Office-Add-in-Samples")** and press <kbd>Enter</kbd>. You should see that the result in cell **B1** is the current number of stars given to the [Office-Add-in-Samples repository](https://github.com/OfficeDev/Office-Add-in-Samples). # [Excel on the web](#tab/excel-online) -1. In Excel, select **Home** > **Add-ins**, then select **More Add-ins**. +1. Select **Home** > **Add-ins**, then select **More Settings**. -1. In the Office Add-ins dialog, choose **Manage My Add-ins**, then select **Upload My Add-in**. +1. On the **Office Add-ins** dialog, select **Upload My Add-in**. 1. Choose **Browse...** and navigate to the root directory of the project that the Yeoman generator created. 1. Select the file **manifest.xml** and choose **Open**, then choose **Upload**. -1. Try out the new function. In cell **B1**, type the text **=CONTOSO.GETSTARCOUNT("OfficeDev", "Excel-Custom-Functions")** and press Enter. You should see that the result in cell **B1** is the current number of stars given to the [Excel-Custom-Functions Github repository](https://github.com/OfficeDev/Excel-Custom-Functions). +1. Try out the new function. In cell **B1**, type the text **=CONTOSO.GETSTARCOUNT("OfficeDev", "Excel-Custom-Functions")** and press <kbd>Enter</kbd>. You should see that the result in cell **B1** is the current number of stars given to the [Excel-Custom-Functions Github repository](https://github.com/OfficeDev/Excel-Custom-Functions). --- @@ -200,7 +194,7 @@ function clock(invocation) { } ``` -To try out the functions, type the text **=CONTOSO.CLOCK()** in cell **C1** and press enter. You should see the current date, which streams an update every second. While this clock is just a timer on a loop, you can use the same idea of setting a timer on more complex functions that make web requests for real-time data. +To try out the functions, type the text **=CONTOSO.CLOCK()** in cell **C1** and press <kbd>Enter</kbd>. You should see the current date, which streams an update every second. While this clock is just a timer on a loop, you can use the same idea of setting a timer on more complex functions that make web requests for real-time data. ## Troubleshooting diff --git a/docs/tutorials/excel-tutorial.md b/docs/tutorials/excel-tutorial.md index a86e75fb2b..c6ae0c7838 100644 --- a/docs/tutorials/excel-tutorial.md +++ b/docs/tutorials/excel-tutorial.md @@ -1,7 +1,7 @@ ---- +--- title: Excel add-in tutorial description: Build an Excel add-in that creates, populates, filters, and sorts a table, creates a chart, freezes a table header, protects a worksheet, and opens a dialog. -ms.date: 12/11/2023 +ms.date: 02/12/2025 ms.service: excel #Customer intent: As a developer, I want to build a Excel add-in that can interact with content in a Excel document. ms.localizationpriority: high @@ -23,7 +23,7 @@ In this tutorial, you'll create an Excel task pane add-in that: > [!TIP] > If you've already completed the [Build an Excel task pane add-in](../quickstarts/excel-quickstart-jquery.md) quick start using the Yeoman generator, and want to use that project as a starting point for this tutorial, go directly to the [Create a table](#create-a-table) section to start this tutorial. > -> If you want a completed version of this tutorial, head over to the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/excel-tutorial). +> If you want a completed version of this tutorial, visit the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/excel-tutorial). ## Prerequisites @@ -40,9 +40,12 @@ In this tutorial, you'll create an Excel task pane add-in that: ![The Yeoman Office Add-in generator command line interface.](../images/yo-office-excel.png) -After you complete the wizard, the generator creates the project and installs supporting Node components. You may need to manually run `npm install` in the root folder of your project if something fails during the initial setup. +Next, select the type of manifest that you'd like to use, either the **unified manifest for Microsoft 365** or the **add-in only manifest**. Most of the steps in this tutorial are the same regardless of the manifest type, but the [Protect a worksheet](#protect-a-worksheet) section has separate steps for each manifest type. -[!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] +> [!NOTE] +> Using the unified manifest for Microsoft 365 with Excel add-ins is in public developer preview. The unified manifest for Microsoft 365 shouldn't be used in production Excel add-ins. We invite you to try it out in test or development environments. For more information, see the [Microsoft 365 app manifest schema reference](/microsoft-365/extensibility/schema). + +After you complete the wizard, the generator creates the project and installs supporting Node components. You may need to manually run `npm install` in the root folder of your project if something fails during the initial setup. ## Create a table @@ -191,7 +194,7 @@ In this step of the tutorial, you'll programmatically test that your add-in supp - To test your add-in in Excel on the web, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of an Excel document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] 1. In Excel, choose the **Home** tab, and then choose the **Show Taskpane** button on the ribbon to open the add-in task pane. @@ -477,9 +480,120 @@ In this step of the tutorial, you'll add a button to the ribbon that toggles wor ### Configure the manifest to add a second ribbon button +The steps vary depending on the type of manifest. + +# [Unified manifest for Microsoft 365 (preview)](#tab/jsonmanifest) + +> [!NOTE] +> Using the unified manifest for Microsoft 365 with Excel add-ins is in public developer preview. The unified manifest for Microsoft 365 shouldn't be used in production Excel add-ins. We invite you to try it out in test or development environments. For more information, see the [Microsoft 365 app manifest schema reference](/microsoft-365/extensibility/schema). + +#### Configure the runtime for the ribbon button + +1. Open the manifest file **./manifest.json**. + +1. Find the **[`"extensions.runtimes"`](/microsoft-365/extensibility/schema/extension-runtimes-array?view=m365-app-prev&preserve-view=true)** array and add the following commands runtime object. + + ```json + "runtimes": [ + { + "id": "CommandsRuntime", + "type": "general", + "code": { + "page": "https://localhost:3000/commands.html" + }, + "lifetime": "short", + "actions": [ + { + "id": <!--TODO1: Set the action ID -->, + "type": "executeFunction", + } + ] + } + ] + ``` + +1. Find `TODO1` and replace it with **`"toggleProtection"`**. This matches the `id` for the JavaScript function you create in a later step. + + > [!TIP] + > The value of **[`"actions.id"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item#id)** must match the first parameter of the call to `Office.actions.associate` in your **commands.js** file. + +1. Ensure that the **[`"requirements.capabilities"`](/microsoft-365/extensibility/schema/requirements-extension-element-capabilities)** array contains an object that specifies the **`"AddinCommands"`** requirement set with a **`"minVersion"`** of **`"1.1"`**. + + ```json + "requirements": { + "capabilities": [ + { + "name": "AddinCommands", + "minVersion": "1.1" + } + ] + }, + ``` + +#### Configure the UI for the ribbon button + +1. After the **`"extensions.runtimes"`** array, add the following **[`"ribbons"`](/microsoft-365/extensibility/schema/element-extensions#ribbons)** array. + + ```json + "ribbons": [ + { + "contexts": [ + "default" + ], + "tabs": [ + { + "builtInTabID": <!--TODO1: Set the tab ID -->, + "groups": [ + { + "id": "worksheetProtectionGroup", + "label": "Contoso Add-in", + "controls": [ + { + "id": "toggleProtectionButton", + "type": "button", + "label": <!--TODO2: Label the button -->, + "icons": [ + { + "size": 16, + "url": "https://localhost:3000/assets/icon-16.png" + }, + { + "size": 32, + "url": "https://localhost:3000/assets/icon-32.png" + }, + { + "size": 80, + "url": "https://localhost:3000/assets/icon-80.png" + } + ], + "supertip": { + "title": "Toggle worksheet protection", + "description": "Enables or disables worksheet protection." + }, + "actionId": <!--TODO3: Set the action ID --> + } + ] + } + ] + } + ] + } + ] + ``` + +1. Find `TODO1` and replace it with **"TabHome"**. This ensures that the new button displays in the Home tab in Excel. For other available tab IDs, see [Find the IDs of built-in Office ribbon tabs](../develop/built-in-ui-ids.md). + +1. Find `TODO2` and replace it with **"Toggle worksheet protection"**. This is the label for your button in the Excel ribbon. + +1. Find `TODO3` and replace it with **`"toggleProtection"`**. This value must match the **[`"runtimes.actions.id"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item#id)** value. + +1. Save the file. + +# [Add-in only manifest](#tab/xmlmanifest) + 1. Open the manifest file **./manifest.xml**. -1. Locate the **\<Control\>** element. This element defines the **Show Taskpane** button on the **Home** ribbon you have been using to launch the add-in. We're going to add a second button to the same group on the **Home** ribbon. In between the closing **\</Control\>** tag and the closing **\</Group\>** tag, add the following markup. +1. Locate the `<Control>` element. This element defines the **Show Taskpane** button on the **Home** ribbon you have been using to launch the add-in. We're going to add a second button to the same group on the **Home** ribbon. In between the closing **\</Control\>** tag and the closing **\</Group\>** tag, add the following markup. ```xml <Control xsi:type="Button" id="<!--TODO1: Unique (in manifest) name for button -->"> @@ -571,6 +685,8 @@ In this step of the tutorial, you'll add a button to the ribbon that toggles wor 1. Save the file. +--- + ### Create the function that protects the sheet 1. Open the file **.\commands\commands.js**. @@ -691,7 +807,7 @@ These steps must be completed whenever your code needs to *read* information fro - To test your add-in in Excel on the web, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of an Excel document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] 1. On the **Home** tab in Excel, choose the **Toggle Worksheet Protection** button. Note that most of the controls on the ribbon are disabled (and visually grayed-out) as seen in the following screenshot. @@ -728,7 +844,7 @@ In this final step of the tutorial, you'll open a dialog in your add-in, pass a <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- For more information on Fluent UI, visit https://developer.microsoft.com/fluentui. --> - <link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/9.6.1/css/fabric.min.css"/> + <link rel="stylesheet" href="https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/office-ui-fabric-core/11.0.0/css/fabric.min.css"/> <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script> <script type="text/javascript" src="http://github.com/popup.js"></script> diff --git a/docs/tutorials/first-run-experience-tutorial.md b/docs/tutorials/first-run-experience-tutorial.md index 5171210a25..9c2b5e7409 100644 --- a/docs/tutorials/first-run-experience-tutorial.md +++ b/docs/tutorials/first-run-experience-tutorial.md @@ -1,19 +1,43 @@ ---- +--- title: First-run experience tutorial description: Learn how to implement a first-run experience for your Office Add-in. -ms.date: 09/06/2024 +ms.date: 08/12/2025 ms.topic: how-to ms.localizationpriority: medium --- # Build an Office Add-in with a basic first-run experience -In this article, you'll walk through the process of updating a task pane add-in to include a [first-run experience](../design/first-run-experience-patterns.md) using the value placemat pattern. When the user runs the add-in, the add-in determines whether or not to show the first-run experience by checking [local storage](../develop/persisting-add-in-state-and-settings.md#browser-storage) for a flag. +Implementing a first-run experience helps onboard users and highlights your add-in's value. This tutorial guides you through adding a simple first-run experience to your Office Add-in using local storage to track whether the user has previously launched the add-in. + +> [!NOTE] +> The [first-run experience](../design/first-run-experience-patterns.md) is a recommended pattern for Office Add-ins. It helps users understand your add-in's features and increases engagement. + +## What you'll learn + +- How to add a first-run UI to your add-in. +- How to use [browser local storage](../develop/persisting-add-in-state-and-settings.md#browser-storage) to persist user state. +- How to update your add-in's HTML, JavaScript, and CSS files to support the first-run experience. + +## Overview + +When a user opens your add-in for the first time, you'll display a welcome message and a list of key features. On subsequent launches, the add-in will skip the welcome and show the main UI. This is accomplished by checking for a flag in local storage and updating the UI accordingly. This tutorial provides instructions and screenshots for Excel but you can use a similar pattern to implement a first-run experience in other Office applications where Office Web Add-ins are supported. +## Steps + +Follow these steps to implement the first-run experience: + +1. **Update the HTML**: Add a container for the first-run experience. +2. **Update the JavaScript**: Check local storage and display the first-run UI if needed. +3. **Update the CSS**: Ensure the new UI is styled consistently. +4. **Test your add-in**: Verify the first-run experience works as expected. + +Let's get started! + > [!TIP] -> If you want a completed version of this tutorial, head over to the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/first-run-experience-tutorial). +> If you want a completed version of this tutorial, visit the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/first-run-experience-tutorial). ## Prerequisites @@ -110,7 +134,7 @@ Update the CSS file to ensure that the add-in UI is styled appropriately given t .ms-welcome__main, .ms-welcome__main > div { ``` -### Try it out +## Try it out 1. Ensure that the web server is running and the add-in has been sideloaded, then open the task pane. For details, see the instructions in the quick start you used. @@ -132,9 +156,11 @@ Using this tutorial, you implemented a basic [first-run experience](../design/fi - Update the features listed in the value placemat to match what your add-in actually does. - Implement a different pattern (for example, video placemat or carousel) that better showcases the benefits of your add-in. -- Use a more secure and robust option for tracking first-run state. For example, use storage partitioning if available, or implement a Single Sign-on (SSO) authentication solution. For more about available settings options, see [Persist add-in state and settings](../develop/persisting-add-in-state-and-settings.md). For more about available authentication options, see [Overview of authentication and authorization](../develop/overview-authn-authz.md). +- Use a more secure and robust option for tracking first-run state. For example, use storage partitioning if available, or implement a Single Sign-on (SSO) authentication solution. + - For more about available settings options, see [Persist add-in state and settings](../develop/persisting-add-in-state-and-settings.md). + - For more about available authentication options, see [Overview of authentication and authorization](../develop/overview-authn-authz.md). -If you're planning to make your add-in available in the AppSource marketplace, you'll need to have a robust and useful first-run experience. For more information, see [Best practices for developing Office Add-ins](../concepts/add-in-development-best-practices.md). +If you're planning to make your add-in available in Microsoft Marketplace, you must have a robust and useful first-run experience. For more information, see [Best practices for developing Office Add-ins](../concepts/add-in-development-best-practices.md). ## Code samples diff --git a/docs/tutorials/migrate-vsto-to-office-add-in-shared-code-library-tutorial.md b/docs/tutorials/migrate-vsto-to-office-add-in-shared-code-library-tutorial.md index eccf6e9415..3b2d723e96 100644 --- a/docs/tutorials/migrate-vsto-to-office-add-in-shared-code-library-tutorial.md +++ b/docs/tutorials/migrate-vsto-to-office-add-in-shared-code-library-tutorial.md @@ -1,7 +1,7 @@ --- title: 'Tutorial: Share code between both a VSTO Add-in and an Office Add-in by using a shared code library' description: Tutorial on how to share code between a VSTO Add-in and an Office Add-in. -ms.date: 02/07/2023 +ms.date: 05/19/2025 ms.service: microsoft-365 ms.localizationpriority: high --- @@ -14,7 +14,7 @@ Visual Studio Tools for Office (VSTO) Add-ins are great for extending Office to Office Add-ins use HTML, JavaScript, and additional web technologies to build Office solutions on all platforms. Migrating your existing VSTO Add-in to an Office Add-in is a great way to make your solution available across all platforms. -You may want to maintain both your VSTO Add-in and a new Office Add-in that both have the same functionality. This enables you to continue servicing your customers that use the VSTO Add-in on Office on Windows. This also enables you to provide the same functionality in an Office Add-in for customers across all platforms. You can also [Make your Office Add-in compatible with the existing VSTO Add-in](../develop/make-office-add-in-compatible-with-existing-com-add-in.md). +You may want to maintain both your VSTO Add-in and a new Office Add-in that both have the same functionality. This enables you to continue servicing your customers that use the VSTO Add-in on Office on Windows. This also enables you to provide the same functionality in an Office Add-in for customers across all platforms. You can also [Make your Office Add-in compatible with an existing COM or VSTO add-in](../develop/make-office-add-in-compatible-with-existing-com-add-in.md). However, it's best to avoid rewriting all the code from your VSTO Add-in for the Office Add-in. This tutorial shows how to avoid rewriting code by using a shared code library for both add-ins. @@ -36,14 +36,14 @@ Skills and techniques in this tutorial: To set up your development environment: -1. Install [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/). +1. Install [Visual Studio 2022](https://visualstudio.microsoft.com/downloads/). 1. Install the following workloads. - ASP.NET and web development - .NET Core cross-platform development - Office/SharePoint development - The following **Individual** components. - Visual Studio Tools for Office (VSTO) - - .NET Core 3.0 Runtime + - .NET Core 9.0 Runtime You also need the following: @@ -57,25 +57,25 @@ This tutorial uses the [VSTO Add-in shared library for Office Add-in](https://gi > [!NOTE] > The sample uses C#, but you can apply the techniques in this tutorial to a VSTO Add-in written in any .NET language. -1. Download the [VSTO Add-in shared library for Office Add-in](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/VSTO-shared-code-migration) PnP solution to a working folder on your computer. -1. Start Visual Studio 2019 and open the **/start/Cell-Analyzer.sln** solution. +1. Download the [VSTO Add-in shared library for Office Add-in](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/VSTO-shared-code-migration) sample to a working folder on your computer. +1. Start Visual Studio and open the **/start/Cell-Analyzer.sln** solution. 1. On the **Debug** menu, choose **Start Debugging**. -The add-in is a custom task pane for Excel. You can select any cell with text, and then choose the **Show unicode** button. In the **Result** section, the add-in will display a list of each character in the text along with its corresponding Unicode number. +The add-in is a custom task pane for Excel. You can select any cell with text, and then choose the **Show unicode** button. In the **Result** section, the add-in displays a list of each character in the text along with its corresponding Unicode number. ![The Cell Analyzer VSTO add-in running in Excel with the "Show unicode" button and empty Result section.](../images/pnp-cell-analyzer-vsto-add-in.png) ## Analyze types of code in the VSTO Add-in -The first technique to apply is to analyze the add-in for which parts of code can be shared. In general, project will break down into three types of code. +The first technique to apply is to analyze the add-in for which parts of code can be shared. In general, the project breaks down into three types of code. ### UI code -UI code interacts with the user. In VSTO UI code works through Windows Forms. Office Add-ins use HTML, CSS, and JavaScript for UI. Because of these differences, you can't share UI code with the Office Add-in. UI will need to be recreated in JavaScript. +UI code interacts with the user. In VSTO UI code works through Windows Forms. Office Add-ins use HTML, CSS, and JavaScript for UI. Because of these differences, you can't share UI code with the Office Add-in. The UI needs to be recreated in JavaScript. ### Document code -In VSTO, code interacts with the document through .NET objects, such as `Microsoft.Office.Interop.Excel.Range`. However, Office Add-ins use the Office.js library. Although these are similar, they aren't exactly the same. So again, you can't share document interaction code with the Office Add-in. +In VSTO, code interacts with the document through .NET objects, such as `Microsoft.Office.Interop.Excel.Range`. However, Office Add-ins use the Office JavaScript library (also called Office.js). Although these are similar, they aren't exactly the same. So again, you can't share document interaction code with the Office Add-in. ### Logic code diff --git a/docs/tutorials/outlook-tutorial.md b/docs/tutorials/outlook-tutorial.md index c19d9aa3c6..d8f2446a33 100644 --- a/docs/tutorials/outlook-tutorial.md +++ b/docs/tutorials/outlook-tutorial.md @@ -1,7 +1,7 @@ ---- +--- title: 'Tutorial: Build a message compose Outlook add-in' description: In this tutorial, you will build an Outlook add-in that inserts GitHub gists into the body of a new message. -ms.date: 04/12/2024 +ms.date: 01/07/2025 ms.service: outlook #Customer intent: As a developer, I want to create a message compose Outlook add-in. ms.localizationpriority: high @@ -22,7 +22,7 @@ In this tutorial, you will: > - Implement a task pane that inserts content into the body of a message > [!TIP] -> If you want a completed version of this tutorial (using the add-in only manifest), head over to the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/outlook-tutorial). +> If you want a completed version of this tutorial (using the add-in only manifest), visit the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/outlook-tutorial). ## Prerequisites @@ -130,8 +130,6 @@ The add-in that you'll create in this tutorial will read [gists](https://gist.gi After you complete the wizard, the generator creates the project and installs supporting Node components. - [!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - 1. Navigate to the root directory of the project. ```command line @@ -164,7 +162,7 @@ Make the following updates in the manifest file to specify some basic informatio # [Unified manifest for Microsoft 365](#tab/jsonmanifest) -1. Locate the "description" property, replace the default "short" and "long" values with descriptions of the add-in, and save the file. +1. Locate the `"description"` property, replace the default `"short"` and `"long"` values with descriptions of the add-in, and save the file. ```json "description": { @@ -177,13 +175,13 @@ Make the following updates in the manifest file to specify some basic informatio # [Add-in only manifest](#tab/xmlmanifest) -1. Locate the **\<ProviderName\>** element and replace the default value with your company name. +1. Locate the `<ProviderName>` element and replace the default value with your company name. ```xml <ProviderName>Contoso</ProviderName> ``` -1. Locate the **\<Description\>** element, replace the default value with a description of the add-in, and save the file. +1. Locate the `<Description>` element, replace the default value with a description of the add-in, and save the file. ```xml <Description DefaultValue="Allows users to access their GitHub gists."/> @@ -233,7 +231,7 @@ Take the following steps: 1. Open the **manifest.json** file. -1. In the "extensions.runtimes" array, there are two runtime objects. For the second one, with the "id" of "CommandsRuntime", change the "actions.id" to "insertDefaultGist". This is the name of a function that you create in a later step. When you're done, the runtime object should look like the following: +1. In the [`"extensions.runtimes"`](/microsoft-365/extensibility/schema/extension-runtimes-array?view=m365-app-prev&preserve-view=true) array, there are two runtime objects. For the second one, with the `"id"` of `"CommandsRuntime"`, change the [`"actions.id"`](/microsoft-365/extensibility/schema/extension-runtimes-actions-item#id) to `"insertDefaultGist"`. This is the name of a function that you create in a later step. When you're done, the runtime object should look like the following: ```json { @@ -254,7 +252,7 @@ Take the following steps: } ``` -1. Change the item in the "extensions.ribbons.contexts" array to "mailCompose". This means the buttons will appear only in a new message or reply window. +1. Change the item in the [`"extensions.ribbons.contexts"`](/microsoft-365/extensibility/schema/extension-ribbons-array#contexts) array to `"mailCompose"`. This means the buttons will appear only in a new message or reply window. ```json "contexts": [ @@ -262,27 +260,27 @@ Take the following steps: ], ``` -1. The "extensions.ribbons.tabs.groups" array has a group object in it. Make the following changes to this object. +1. The [`"extensions.ribbons.tabs.groups"`](/microsoft-365/extensibility/schema/extension-ribbons-array-tabs-item#groups) array has a group object in it. Make the following changes to this object. - 1. Change the "id" property to "msgComposeCmdGroup". - 1. Change the "label" property to "Git the gist". + 1. Change the `"id"` property to `"msgComposeCmdGroup"`. + 1. Change the `"label"` property to "Git the gist". -1. That same group object has a "controls" array with two control objects. We need to make changes to the JSON for each of them. In the first one, take these steps. +1. That same group object has a `"controls"` array with two control objects. We need to make changes to the JSON for each of them. In the first one, take these steps. - 1. Change the "id" to "msgComposeInsertGist". - 1. Change the "label" to "Insert gist". - 1. Change the "supertip.title" to "Insert gist". - 1. Change the "supertip.description" to "Displays a list of your gists and allows you to insert their contents into the current message." + 1. Change the `"id"` to `"msgComposeInsertGist"`. + 1. Change the `"label"` to "Insert gist". + 1. Change the `"supertip.title"` to "Insert gist". + 1. Change the `"supertip.description"` to "Displays a list of your gists and allows you to insert their contents into the current message." 1. In the second control object, take these steps. - 1. Change the "id" to "msgComposeInsertDefaultGist". - 1. Change the "label" to "Insert default gist". - 1. Change the "supertip.title" to "Insert default gist". - 1. Change the "supertip.description" to "Inserts the content of the gist you mark as default into the current message." - 1. Change the "actionId" to "insertDefaultGist". This matches the "action.id" of the "CommandsRuntime" that you set in an earlier step. + 1. Change the `"id"` to `"msgComposeInsertDefaultGist"`. + 1. Change the `"label"` to "Insert default gist". + 1. Change the `"supertip.title"` to "Insert default gist". + 1. Change the `"supertip.description"` to "Inserts the content of the gist you mark as default into the current message." + 1. Change the `"actionId"` to `"insertDefaultGist"`. This matches the `"action.id"` of the `"CommandsRuntime"` that you set in an earlier step. - When you're done, the "ribbons" property should look like the following: + When you're done, the [`"ribbons"`](/microsoft-365/extensibility/schema/element-extensions#ribbons) property should look like the following: ```json "ribbons": [ @@ -377,7 +375,7 @@ Take the following steps: 1. Open the **manifest.xml** file. -1. Locate the **\<ExtensionPoint\>** element with type **MessageReadCommandSurface** and delete it (including its closing tag). This removes the add-in buttons from the read message window. +1. Locate the `<ExtensionPoint>` element with type **MessageReadCommandSurface** and delete it (including its closing tag). This removes the add-in buttons from the read message window. ### Add the MessageComposeCommandSurface extension point @@ -385,15 +383,15 @@ Take the following steps: 1. Immediately before this line, insert the following XML markup. Note the following about this markup. - - The **\<ExtensionPoint\>** with `xsi:type="MessageComposeCommandSurface"` indicates that you're defining buttons to add to the compose message window. + - The `<ExtensionPoint>` with `xsi:type="MessageComposeCommandSurface"` indicates that you're defining buttons to add to the compose message window. - - By using an **\<OfficeTab\>** element with `id="TabDefault"`, you're indicating you want to add the buttons to the default tab on the ribbon. + - By using an `<OfficeTab>` element with `id="TabDefault"`, you're indicating you want to add the buttons to the default tab on the ribbon. - - The **\<Group\>** element defines the grouping for the new buttons, with a label set by the **groupLabel** resource. + - The `<Group>` element defines the grouping for the new buttons, with a label set by the **groupLabel** resource. - - The first **\<Control\>** element contains an **\<Action\>** element with `xsi:type="ShowTaskPane"`, so this button opens a task pane. + - The first `<Control>` element contains an `<Action>` element with `xsi:type="ShowTaskPane"`, so this button opens a task pane. - - The second **\<Control\>** element contains an **\<Action\>** element with `xsi:type="ExecuteFunction"`, so this button invokes a JavaScript function contained in the function file. + - The second `<Control>` element contains an `<Action>` element with `xsi:type="ExecuteFunction"`, so this button invokes a JavaScript function contained in the function file. ```xml <!-- Message Compose --> @@ -438,11 +436,11 @@ Take the following steps: ### Update resources in the manifest -The previous code references labels, tooltips, and URLs that you need to define before the manifest will be valid. You'll specify this information in the **\<Resources\>** section of the manifest. +The previous code references labels, tooltips, and URLs that you need to define before the manifest will be valid. You'll specify this information in the `<Resources>` section of the manifest. -1. In **manifest.xml**, locate the **\<Resources\>** element in the manifest file and delete the entire element (including its closing tag). +1. In **manifest.xml**, locate the `<Resources>` element in the manifest file and delete the entire element (including its closing tag). -1. In that same location, add the following markup to replace the **\<Resources\>** element you just removed. +1. In that same location, add the following markup to replace the `<Resources>` element you just removed. ```xml <Resources> @@ -523,10 +521,10 @@ Let's start by creating the UI for the dialog. <title>Settings - + - + @@ -965,7 +963,7 @@ This add-in's **Insert default gist** button is a UI-less button that invokes a ### Update the function file (HTML) -A function that's invoked by a UI-less button must be defined in the file that's specified by the **\** element in the manifest for the corresponding form factor. This add-in's manifest specifies `https://localhost:3000/commands.html` as the function file. +A function that's invoked by a UI-less button must be defined in the file that's specified by the `` element in the manifest for the corresponding form factor. This add-in's manifest specifies `https://localhost:3000/commands.html` as the function file. 1. Open the **./src/commands/commands.html** and replace the entire contents with the following markup. @@ -978,7 +976,7 @@ A function that's invoked by a UI-less button must be defined in the file that's - + @@ -1212,10 +1210,10 @@ This add-in's **Insert gist** button opens a task pane and displays the user's g Contoso Task Pane Add-in - + - + diff --git a/docs/tutorials/powerpoint-tutorial-vs.md b/docs/tutorials/powerpoint-tutorial-vs.md new file mode 100644 index 0000000000..27fd0b2d0a --- /dev/null +++ b/docs/tutorials/powerpoint-tutorial-vs.md @@ -0,0 +1,644 @@ +--- +title: PowerPoint add-in tutorial using Visual Studio +description: "In this tutorial, you'll use Visual Studio to build a PowerPoint add-in that inserts an image, inserts text, gets slide metadata, and navigates between slides." +ms.date: 01/16/2025 +ms.service: powerpoint +#Customer intent: As a developer, I want to build a PowerPoint add-in that can interact with content in a PowerPoint document. +ms.localizationpriority: high +--- + +# Tutorial: Create a PowerPoint task pane add-in with Visual Studio + +In this tutorial, you'll create a PowerPoint task pane add-in that: + +> [!div class="checklist"] +> +> - Adds an image to a slide +> - Adds text to a slide +> - Gets slide metadata +> - Adds new slides +> - Navigates between slides + +> [!TIP] +> If you want a completed version of this tutorial, visit the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/powerpoint-tutorial). + +## Prerequisites + +- [Visual Studio 2019 or later](https://www.visualstudio.com/vs/), with the **Office/SharePoint development** workload installed. + + > [!NOTE] + > If you've previously installed Visual Studio, [use the Visual Studio Installer](/visualstudio/install/modify-visual-studio) to ensure that the **Office/SharePoint development** workload is installed. + +- Office connected to a Microsoft 365 subscription (including Office on the web). + + > [!NOTE] + > If you don't already have Office, you might qualify for a Microsoft 365 E5 developer subscription to use for development through the [Microsoft 365 Developer Program](https://aka.ms/m365devprogram); for details, see the [FAQ](/office/developer-program/microsoft-365-developer-program-faq#who-qualifies-for-a-microsoft-365-e5-developer-subscription-). Alternatively, you can [sign up for a 1-month free trial](https://www.microsoft.com/microsoft-365/try) or [purchase a Microsoft 365 plan](https://www.microsoft.com/microsoft-365/business/compare-all-microsoft-365-business-products-g). + +## Create your add-in project + +Complete the following steps to create a PowerPoint add-in project using Visual Studio. + +1. Choose **Create a new project**. + +1. Using the search box, enter **add-in**. Choose **PowerPoint Web Add-in**, then select **Next**. + +1. Name the project `HelloWorld`, and select **Create**. + +1. In the **Create Office Add-in** dialog window, choose **Add new functionalities to PowerPoint**, and then choose **Finish** to create the project. + +1. Visual Studio creates a solution and its two projects appear in **Solution Explorer**. The **Home.html** file opens in Visual Studio. + + ![The Visual Studio Solution Explorer window showing HelloWorld and HelloWorldWeb, the two projects in the HelloWorld solution.](../images/powerpoint-tutorial-solution-explorer.png) + +1. The following NuGet packages must be installed. Install them on the **HelloWorldWeb** project using the **NuGet Package Manager** in Visual Studio. See Visual Studio help for instructions. The second of these may be installed automatically when you install the first. + + - Microsoft.AspNet.WebApi.WebHost + - Microsoft.AspNet.WebApi.Core + + > [!IMPORTANT] + > When you're using the **NuGet Package Manager** to install these packages, do **not** install the recommended update to jQuery. The jQuery version installed with your Visual Studio solution matches the jQuery call within the solution files. + +1. Use the **NuGet Package Manager** to update the Newtonsoft.Json package to version 13.0.3 or later. Then delete the **app.config** file if it was added to the **HelloWorld** project. + +### Explore the Visual Studio solution + +[!include[Description of Visual Studio projects](../includes/quickstart-vs-solution.md)] + +### Update code + +Edit the add-in code as follows to create the framework that you'll use to implement add-in functionality in subsequent steps of this tutorial. + +1. **Home.html** specifies the HTML that will be rendered in the add-in's task pane. In **Home.html**, find the **div** with `id="content-main"`, replace that entire **div** with the following markup, and save the file. + + ```html + +

+
+ + + + +
+
+ ``` + +1. Open the file **Home.js** in the root of the web application project. This file specifies the script for the add-in. Replace the entire contents with the following code and save the file. + + ```js + (function () { + "use strict"; + + let messageBanner; + + Office.onReady(function () { + $(document).ready(function () { + // Initialize the FabricUI notification mechanism and hide it. + const element = document.querySelector('.MessageBanner'); + messageBanner = new components.MessageBanner(element); + messageBanner.hideBanner(); + + // TODO1: Assign event handler for insert-image button. + // TODO4: Assign event handler for insert-text button. + // TODO6: Assign event handler for get-slide-metadata button. + // TODO8: Assign event handlers for add-slides and the four navigation buttons. + }); + }); + + // TODO2: Define the insertImage function. + + // TODO3: Define the insertImageFromBase64String function. + + // TODO5: Define the insertText function. + + // TODO7: Define the getSlideMetadata function. + + // TODO9: Define the addSlides and navigation functions. + + // Helper function for displaying notifications. + function showNotification(header, content) { + $("#notification-header").text(header); + $("#notification-body").text(content); + messageBanner.showBanner(); + messageBanner.toggleExpansion(); + } + })(); + ``` + +## Insert an image + +Complete the following steps to add code that retrieves the [Bing](https://www.bing.com) photo of the day and inserts that image into a slide. + +1. Using Solution Explorer, add a new folder named **Controllers** to the **HelloWorldWeb** project. + + ![The Visual Studio Solution Explorer window showing the Controllers folder highlighted in the HelloWorldWeb project.](../images/powerpoint-tutorial-solution-explorer-controllers.png) + +1. Right-click (or select and hold) the **Controllers** folder and select **Add** > **New Scaffolded Item...**. + +1. In the **Add Scaffold** dialog window, select **Web API 2 Controller - Empty** and choose the **Add** button. + +1. In the **Add Controller** dialog window, enter **PhotoController** as the controller name and choose the **Add** button. Visual Studio creates and opens the **PhotoController.cs** file. + + > [!IMPORTANT] + > The scaffolding process doesn't complete properly on some versions of Visual Studio after version 16.10.3. If you have the **Global.asax** and **./App_Start/WebApiConfig.cs** files, then skip to step 6. + > + > ![The Visual Studio Solution Explorer window showing the scaffolded files highlighted in the HelloWorldWeb project.](../images/powerpoint-tutorial-solution-explorer-scaffolded.png) + +1. If you're missing scaffolding files from the **HelloWorldWeb** project, add them as follows. + + 1. Using Solution Explorer, add a new folder named **App_Start** to the **HelloWorldWeb** project. + + 1. Right-click (or select and hold) the **App_Start** folder and select **Add** > **Class...**. + + 1. In the **Add New Item** dialog, name the file **WebApiConfig.cs** then choose the **Add** button. + + 1. Replace the entire contents of the **WebApiConfig.cs** file with the following code. + + ```cs + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using System.Web.Http; + + namespace HelloWorldWeb.App_Start + { + public static class WebApiConfig + { + public static void Register(HttpConfiguration config) + { + config.MapHttpAttributeRoutes(); + + config.Routes.MapHttpRoute( + name: "DefaultApi", + routeTemplate: "api/{controller}/{id}", + defaults: new { id = RouteParameter.Optional } + ); + } + } + } + ``` + + 1. In the Solution Explorer, right-click (or select and hold) the **HelloWorldWeb** project and select **Add** > **New Item...**. + + 1. In the **Add New Item** dialog, search for "global", select **Global Application Class**, then choose the **Add** button. By default, the file is named **Global.asax**. + + 1. Replace the entire contents of the **Global.asax.cs** file with the following code. + + ```cs + using HelloWorldWeb.App_Start; + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using System.Web.Http; + using System.Web.Security; + using System.Web.SessionState; + + namespace HelloWorldWeb + { + public class WebApiApplication : System.Web.HttpApplication + { + protected void Application_Start() + { + GlobalConfiguration.Configure(WebApiConfig.Register); + } + } + } + ``` + + 1. In the Solution Explorer, right-click (or select and hold) the **Global.asax** file and choose **View Markup**. + + 1. Replace the entire contents of the **Global.asax** file with the following code. + + ```XML + <%@ Application Codebehind="Global.asax.cs" Inherits="HelloWorldWeb.WebApiApplication" Language="C#" %> + ``` + +1. Replace the entire contents of the **PhotoController.cs** file with the following code that calls the Bing service to retrieve the photo of the day as a Base64-encoded string. When you use the Office JavaScript API to insert an image into a document, the image data must be specified as a Base64-encoded string. + + ```csharp + using System; + using System.IO; + using System.Net; + using System.Text; + using System.Web.Http; + using System.Xml; + + namespace HelloWorldWeb.Controllers + { + public class PhotoController : ApiController + { + public string Get() + { + string url = "http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1"; + + // Create the request. + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + WebResponse response = request.GetResponse(); + + using (Stream responseStream = response.GetResponseStream()) + { + // Process the result. + StreamReader reader = new StreamReader(responseStream, Encoding.UTF8); + string result = reader.ReadToEnd(); + + // Parse the XML response and get the URL. + XmlDocument doc = new XmlDocument(); + doc.LoadXml(result); + string photoURL = "http://bing.com/" + doc.SelectSingleNode("/images/image/url").InnerText; + + // Fetch the photo and return it as a Base64-encoded string. + return getPhotoFromURL(photoURL); + } + } + + private string getPhotoFromURL(string imageURL) + { + var webClient = new WebClient(); + byte[] imageBytes = webClient.DownloadData(imageURL); + return Convert.ToBase64String(imageBytes); + } + } + } + ``` + +1. In the **Home.html** file, replace `TODO1` with the following markup. This markup defines the **Insert Image** button that will appear within the add-in's task pane. + + ```html + + ``` + +1. In the **Home.js** file, replace `TODO1` with the following code to assign the event handler for the **Insert Image** button. + + ```js + $('#insert-image').on("click", insertImage); + ``` + +1. In the **Home.js** file, replace `TODO2` with the following code to define the `insertImage` function. This function fetches the image from the Bing web service and then calls the `insertImageFromBase64String` function to insert that image into the document. + + ```js + function insertImage() { + // Get image from web service (as a Base64-encoded string). + $.ajax({ + url: "/api/photo/", + dataType: "text", + success: function (result) { + insertImageFromBase64String(result); + }, error: function (xhr, status, error) { + showNotification("Error", "Oops, something went wrong."); + } + }); + } + ``` + +1. In the **Home.js** file, replace `TODO3` with the following code to define the `insertImageFromBase64String` function. This function uses the Office JavaScript API to insert the image into the document. Note: + + - The `coercionType` option that's specified as the second parameter of the `setSelectedDataAsync` request indicates the type of data being inserted. + + - The `asyncResult` object encapsulates the result of the `setSelectedDataAsync` request, including status and error information if the request failed. + + ```js + function insertImageFromBase64String(image) { + // Call Office.js to insert the image into the document. + Office.context.document.setSelectedDataAsync(image, { + coercionType: Office.CoercionType.Image + }, + function (asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + showNotification("Error", asyncResult.error.message); + } + }); + } + ``` + +### Test the add-in + +1. Using Visual Studio, test the newly created PowerPoint add-in by pressing F5 or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. + + ![The Start button highlighted in Visual Studio.](../images/powerpoint-tutorial-start.png) + +1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. + + ![The Show Taskpane button highlighted on the Home ribbon in PowerPoint.](../images/powerpoint-tutorial-show-taskpane-button.png) + +1. In the task pane, choose the **Insert Image** button to add the Bing photo of the day to the current slide. + + ![The PowerPoint add-in with the Insert Image button highlighted.](../images/powerpoint-tutorial-insert-image-button.png) + + > [!NOTE] + > If you get an error "Could not find file [...]\bin\roslyn\csc.exe", then do the following: + > + > 1. Open the **.\Web.config** file. + > 1. Find the `` node for the .cs `extension`, then remove the `type` attribute and its value. + > 1. Save the file. + +1. In Visual Studio, stop the add-in by pressing Shift+F5 or choosing the **Stop** button. PowerPoint will automatically close when the add-in is stopped. + + ![The Stop button highlighted in Visual Studio.](../images/powerpoint-tutorial-stop.png) + +## Customize user interface (UI) elements + +Complete the following steps to add markup that customizes the task pane UI. + +1. In the **Home.html** file, replace `TODO2` with the following markup to add a header section and title to the task pane. Note: + + - The styles that begin with `ms-` are defined by [Fabric Core in Office Add-ins](../design/fabric-core.md), a JavaScript front-end framework for building user experiences for Office. The **Home.html** file includes a reference to the Fabric Core stylesheet. + + ```html +
+
+
+
My PowerPoint add-in
+
+
+
+ ``` + +1. In the **Home.html** file, find the **div** with `class="footer"` and delete that entire **div** to remove the footer section from the task pane. + +### Test the add-in + +1. Using Visual Studio, test the PowerPoint add-in by pressing F5 or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. + + ![The Start button highlighted in Visual Studio.](../images/powerpoint-tutorial-start.png) + +1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. + + ![The Show Taskpane button highlighted on the PowerPoint Home ribbon.](../images/powerpoint-tutorial-show-taskpane-button.png) + +1. Notice that the task pane now contains a header section and title, and no longer contains a footer section. + + ![The PowerPoint add-in with Insert Image button.](../images/powerpoint-tutorial-new-task-pane-ui.png) + +1. In Visual Studio, stop the add-in by pressing Shift+F5 or choosing the **Stop** button. PowerPoint will automatically close when the add-in is stopped. + + ![The Stop button highlighted in Visual Studio.](../images/powerpoint-tutorial-stop.png) + +## Insert text + +Complete the following steps to add code that inserts text into the title slide which contains the [Bing](https://www.bing.com) photo of the day. + +1. In the **Home.html** file, replace `TODO3` with the following markup. This markup defines the **Insert Text** button that will appear within the add-in's task pane. + + ```html +

+ + ``` + +1. In the **Home.js** file, replace `TODO4` with the following code to assign the event handler for the **Insert Text** button. + + ```js + $('#insert-text').on("click", insertText); + ``` + +1. In the **Home.js** file, replace `TODO5` with the following code to define the `insertText` function. This function inserts text into the current slide. + + ```js + function insertText() { + Office.context.document.setSelectedDataAsync('Hello World!', + function (asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + showNotification("Error", asyncResult.error.message); + } + }); + } + ``` + +### Test the add-in + +1. Using Visual Studio, test the add-in by pressing F5 or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. + + ![The Start button highlighted in Visual Studio.](../images/powerpoint-tutorial-start.png) + +1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. + + ![The Show Taskpane button on the Home ribbon in PowerPoint.](../images/powerpoint-tutorial-show-taskpane-button.png) + +1. In the task pane, choose the **Insert Image** button to add the Bing photo of the day to the current slide and choose a design for the slide that contains a text box for the title. + + ![The selected PowerPoint title slide and the Insert Image button highlighted in the add-in.](../images/powerpoint-tutorial-insert-image-slide-design.png) + +1. Put your cursor in the text box on the title slide and then in the task pane, choose the **Insert Text** button to add text to the slide. + + ![The selected PowerPoint title slide with the Insert Text button highlighted in the add-in.](../images/powerpoint-tutorial-insert-text.png) + +1. In Visual Studio, stop the add-in by pressing Shift+F5 or choosing the **Stop** button. PowerPoint will automatically close when the add-in is stopped. + + ![The Stop button highlighted in Visual Studio.](../images/powerpoint-tutorial-stop.png) + +## Get slide metadata + +Complete the following steps to add code that retrieves metadata for the selected slide. + +1. In the **Home.html** file, replace `TODO4` with the following markup. This markup defines the **Get Slide Metadata** button that will appear within the add-in's task pane. + + ```html +

+ + ``` + +1. In the **Home.js** file, replace `TODO6` with the following code to assign the event handler for the **Get Slide Metadata** button. + + ```js + $('#get-slide-metadata').on("click", getSlideMetadata); + ``` + +1. In the **Home.js** file, replace `TODO7` with the following code to define the `getSlideMetadata` function. This function retrieves metadata for the selected slides and writes it to a popup dialog window within the add-in task pane. + + ```js + function getSlideMetadata() { + Office.context.document.getSelectedDataAsync(Office.CoercionType.SlideRange, + function (asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + showNotification("Error", asyncResult.error.message); + } else { + showNotification("Metadata for selected slides:", JSON.stringify(asyncResult.value), null, 2); + } + } + ); + } + ``` + +### Test the add-in + +1. Using Visual Studio, test the add-in by pressing F5 or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. + + ![The Start button in Visual Studio.](../images/powerpoint-tutorial-start.png) + +1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. + + ![The Show Taskpane button on the PowerPoint Home ribbon.](../images/powerpoint-tutorial-show-taskpane-button.png) + +1. In the task pane, choose the **Get Slide Metadata** button to get the metadata for the selected slide. The slide metadata is written to the popup dialog window at the bottom of the task pane. In this case, the `slides` array within the JSON metadata contains one object that specifies the `id`, `title`, and `index` of the selected slide. If multiple slides had been selected when you retrieved slide metadata, the `slides` array within the JSON metadata would contain one object for each selected slide. + + ![The Get Slide Metadata button highlighted in the add-in.](../images/powerpoint-tutorial-get-slide-metadata.png) + +1. In Visual Studio, stop the add-in by pressing Shift+F5 or choosing the **Stop** button. PowerPoint will automatically close when the add-in is stopped. + + ![The Stop button in Visual Studio.](../images/powerpoint-tutorial-stop.png) + +## Navigate between slides + +Complete the following steps to add code that navigates between the slides of a document. + +1. In the **Home.html** file, replace `TODO5` with the following markup. This markup defines the four navigation buttons that will appear within the add-in's task pane. + + ```html +

+ +

+ +

+ +

+ +

+ + ``` + +1. In the **Home.js** file, replace `TODO8` with the following code to assign the event handlers for the **Add Slides** and four navigation buttons. + + ```js + $('#add-slides').on("click", addSlides); + $('#go-to-first-slide').on("click", goToFirstSlide); + $('#go-to-next-slide').on("click", goToNextSlide); + $('#go-to-previous-slide').on("click", goToPreviousSlide); + $('#go-to-last-slide').on("click", goToLastSlide); + ``` + +1. In the **Home.js** file, replace `TODO9` with the following code to define the `addSlides` and navigation functions. Each of these functions uses the `goToByIdAsync` method to select a slide based upon its position in the document (first, last, previous, and next). + + ```js + async function addSlides() { + await PowerPoint.run(async function (context) { + context.presentation.slides.add(); + context.presentation.slides.add(); + + await context.sync(); + + showNotification("Success", "Slides added."); + goToLastSlide(); + }); + } + + function goToFirstSlide() { + Office.context.document.goToByIdAsync(Office.Index.First, Office.GoToType.Index, + function (asyncResult) { + if (asyncResult.status == "failed") { + showNotification("Error", asyncResult.error.message); + } + }); + } + + function goToLastSlide() { + Office.context.document.goToByIdAsync(Office.Index.Last, Office.GoToType.Index, + function (asyncResult) { + if (asyncResult.status == "failed") { + showNotification("Error", asyncResult.error.message); + } + }); + } + + function goToPreviousSlide() { + Office.context.document.goToByIdAsync(Office.Index.Previous, Office.GoToType.Index, + function (asyncResult) { + if (asyncResult.status == "failed") { + showNotification("Error", asyncResult.error.message); + } + }); + } + + function goToNextSlide() { + Office.context.document.goToByIdAsync(Office.Index.Next, Office.GoToType.Index, + function (asyncResult) { + if (asyncResult.status == "failed") { + showNotification("Error", asyncResult.error.message); + } + }); + } + ``` + +### Test the add-in + +1. Using Visual Studio, test the add-in by pressing F5 or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. + + ![The Start button highlighted on the Visual Studio toolbar.](../images/powerpoint-tutorial-start.png) + +1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. + + ![The Show Taskpane button highlighted on the Home ribbon in PowerPoint.](../images/powerpoint-tutorial-show-taskpane-button.png) + +1. In the task pane, choose the **Add Slides** button. Two new slides are added to the document and the last slide in the document is selected and displayed. + + ![The Add Slides button highlighted in the add-in.](../images/powerpoint-tutorial-add-slides-1.png) + +1. In the task pane, choose the **Go to First Slide** button. The first slide in the document is selected and displayed. + + ![The Go to First Slide button highlighted in the add-in.](../images/powerpoint-tutorial-go-to-first-slide.png) + +1. In the task pane, choose the **Go to Next Slide** button. The next slide in the document is selected and displayed. + + ![The Go to Next Slide button highlighted in the add-in.](../images/powerpoint-tutorial-go-to-next-slide.png) + +1. In the task pane, choose the **Go to Previous Slide** button. The previous slide in the document is selected and displayed. + + ![The Go to Previous Slide button highlighted in the add-in.](../images/powerpoint-tutorial-go-to-previous-slide.png) + +1. In the task pane, choose the **Go to Last Slide** button. The last slide in the document is selected and displayed. + + ![The Go to Last Slide button highlighted in the add-in.](../images/powerpoint-tutorial-go-to-last-slide.png) + +1. In Visual Studio, stop the add-in by pressing Shift+F5 or choosing the **Stop** button. PowerPoint will automatically close when the add-in is stopped. + + ![The Stop button highlighted on the Visual Studio toolbar.](../images/powerpoint-tutorial-stop.png) + +## Code samples + +- [Completed PowerPoint add-in tutorial](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/powerpoint-tutorial): The result of completing this tutorial. + +## Next steps + +In this tutorial, you created a PowerPoint add-in that inserts an image, inserts text, gets slide metadata, and navigates between slides. To learn more about building PowerPoint add-ins, continue to the following articles. + +> [!div class="nextstepaction"] +> [PowerPoint add-ins overview](../powerpoint/powerpoint-add-ins.md) + +> [!div class="nextstepaction"] +> [Develop Office Add-ins with Visual Studio](../develop/develop-add-ins-visual-studio.md) + +## See also + +- [Office Add-ins platform overview](../overview/office-add-ins.md) +- [Develop Office Add-ins](../develop/develop-overview.md) diff --git a/docs/tutorials/powerpoint-tutorial.md b/docs/tutorials/powerpoint-tutorial-yo.md similarity index 53% rename from docs/tutorials/powerpoint-tutorial.md rename to docs/tutorials/powerpoint-tutorial-yo.md index 8ad4ac8361..4de30efdca 100644 --- a/docs/tutorials/powerpoint-tutorial.md +++ b/docs/tutorials/powerpoint-tutorial-yo.md @@ -1,7 +1,7 @@ --- title: PowerPoint add-in tutorial -description: In this tutorial, you will build a PowerPoint add-in that inserts an image, inserts text, gets slide metadata, and navigates between slides. -ms.date: 12/11/2023 +description: "In this tutorial, you'll build a PowerPoint add-in that inserts an image, inserts text, gets slide metadata, and navigates between slides." +ms.date: 11/20/2024 ms.service: powerpoint #Customer intent: As a developer, I want to build a PowerPoint add-in that can interact with content in a PowerPoint document. ms.localizationpriority: high @@ -9,7 +9,7 @@ ms.localizationpriority: high # Tutorial: Create a PowerPoint task pane add-in -In this tutorial, you'll use Visual Studio Code (VS Code), Visual Studio, or your preferred code editor to create a PowerPoint task pane add-in that: +In this tutorial, you'll create a PowerPoint task pane add-in that: > [!div class="checklist"] > @@ -19,16 +19,12 @@ In this tutorial, you'll use Visual Studio Code (VS Code), Visual Studio, or you > - Adds new slides > - Navigates between slides -[!include[Choose your editor](../includes/quickstart-choose-editor.md)] - -# [Yeoman generator](#tab/yeomangenerator) - ## Create the add-in > [!TIP] > If you've already completed the [Build your first PowerPoint task pane add-in](../quickstarts/powerpoint-quickstart-yo.md) quick start using the Yeoman generator, and want to use that project as a starting point for this tutorial, go directly to the [Insert an image](#insert-an-image) section to start this tutorial. > -> If you want a completed version of this tutorial, head over to the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/powerpoint-tutorial-yo). +> If you want a completed version of this tutorial, visit the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/powerpoint-tutorial-yo). ### Prerequisites @@ -47,8 +43,6 @@ In this tutorial, you'll use Visual Studio Code (VS Code), Visual Studio, or you After you complete the wizard, the generator creates the project and installs supporting Node components. -[!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - ### Complete setup 1. Navigate to the root directory of the project. @@ -227,7 +221,7 @@ Complete the following steps to add code that inserts an image into a slide. - To test your add-in in PowerPoint on a browser, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of a PowerPoint document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] 1. If the add-in task pane isn't already open in PowerPoint, choose the **Home** tab, and then choose the **Show Taskpane** button on the ribbon to open the add-in task pane. @@ -280,7 +274,7 @@ Complete the following steps to add markup that customizes the task pane UI. - To test your add-in in PowerPoint on a browser, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of a PowerPoint document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] 1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. @@ -347,7 +341,7 @@ Complete the following steps to add code that inserts text into the title slide - To test your add-in in PowerPoint on a browser, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of a PowerPoint document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] 1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. @@ -422,7 +416,7 @@ Complete the following steps to add code that retrieves metadata for the selecte - To test your add-in in PowerPoint on a browser, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of a PowerPoint document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] 1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. @@ -533,7 +527,7 @@ Complete the following steps to add code that navigates between the slides of a - To test your add-in in PowerPoint on a browser, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of a PowerPoint document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] 1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. @@ -569,622 +563,9 @@ Complete the following steps to add code that navigates between the slides of a - [Completed PowerPoint add-in tutorial](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/powerpoint-tutorial-yo): The result of completing this tutorial. -# [Visual Studio](#tab/visualstudio) - -> [!TIP] -> If you want a completed version of this tutorial, head over to the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/powerpoint-tutorial). - -## Prerequisites - -- [Visual Studio 2019 or later](https://www.visualstudio.com/vs/), with the **Office/SharePoint development** workload installed. - - > [!NOTE] - > If you've previously installed Visual Studio, [use the Visual Studio Installer](/visualstudio/install/modify-visual-studio) to ensure that the **Office/SharePoint development** workload is installed. - -- Office connected to a Microsoft 365 subscription (including Office on the web). - - > [!NOTE] - > If you don't already have Office, you might qualify for a Microsoft 365 E5 developer subscription to use for development through the [Microsoft 365 Developer Program](https://aka.ms/m365devprogram); for details, see the [FAQ](/office/developer-program/microsoft-365-developer-program-faq#who-qualifies-for-a-microsoft-365-e5-developer-subscription-). Alternatively, you can [sign up for a 1-month free trial](https://www.microsoft.com/microsoft-365/try) or [purchase a Microsoft 365 plan](https://www.microsoft.com/microsoft-365/business/compare-all-microsoft-365-business-products-g). - -## Create your add-in project - -Complete the following steps to create a PowerPoint add-in project using Visual Studio. - -1. Choose **Create a new project**. - -1. Using the search box, enter **add-in**. Choose **PowerPoint Web Add-in**, then select **Next**. - -1. Name the project `HelloWorld`, and select **Create**. - -1. In the **Create Office Add-in** dialog window, choose **Add new functionalities to PowerPoint**, and then choose **Finish** to create the project. - -1. Visual Studio creates a solution and its two projects appear in **Solution Explorer**. The **Home.html** file opens in Visual Studio. - - ![The Visual Studio Solution Explorer window showing HelloWorld and HelloWorldWeb, the two projects in the HelloWorld solution.](../images/powerpoint-tutorial-solution-explorer.png) - -1. The following NuGet packages must be installed. Install them on the **HelloWorldWeb** project using the **NuGet Package Manager** in Visual Studio. See Visual Studio help for instructions. The second of these may be installed automatically when you install the first. - - - Microsoft.AspNet.WebApi.WebHost - - Microsoft.AspNet.WebApi.Core - - > [!IMPORTANT] - > When you're using the **NuGet Package Manager** to install these packages, do **not** install the recommended update to jQuery. The jQuery version installed with your Visual Studio solution matches the jQuery call within the solution files. - -1. Use the **NuGet Package Manager** to update the Newtonsoft.Json package to version 13.0.3 or later. Then delete the **app.config** file if it was added to the **HelloWorld** project. - -### Explore the Visual Studio solution - -[!include[Description of Visual Studio projects](../includes/quickstart-vs-solution.md)] - -### Update code - -Edit the add-in code as follows to create the framework that you'll use to implement add-in functionality in subsequent steps of this tutorial. - -1. **Home.html** specifies the HTML that will be rendered in the add-in's task pane. In **Home.html**, find the **div** with `id="content-main"`, replace that entire **div** with the following markup, and save the file. - - ```html - -
-
- - - - -
-
- ``` - -1. Open the file **Home.js** in the root of the web application project. This file specifies the script for the add-in. Replace the entire contents with the following code and save the file. - - ```js - (function () { - "use strict"; - - let messageBanner; - - Office.onReady(function () { - $(document).ready(function () { - // Initialize the FabricUI notification mechanism and hide it. - const element = document.querySelector('.MessageBanner'); - messageBanner = new components.MessageBanner(element); - messageBanner.hideBanner(); - - // TODO1: Assign event handler for insert-image button. - // TODO4: Assign event handler for insert-text button. - // TODO6: Assign event handler for get-slide-metadata button. - // TODO8: Assign event handlers for add-slides and the four navigation buttons. - }); - }); - - // TODO2: Define the insertImage function. - - // TODO3: Define the insertImageFromBase64String function. - - // TODO5: Define the insertText function. - - // TODO7: Define the getSlideMetadata function. - - // TODO9: Define the addSlides and navigation functions. - - // Helper function for displaying notifications. - function showNotification(header, content) { - $("#notification-header").text(header); - $("#notification-body").text(content); - messageBanner.showBanner(); - messageBanner.toggleExpansion(); - } - })(); - ``` - -## Insert an image - -Complete the following steps to add code that retrieves the [Bing](https://www.bing.com) photo of the day and inserts that image into a slide. - -1. Using Solution Explorer, add a new folder named **Controllers** to the **HelloWorldWeb** project. - - ![The Visual Studio Solution Explorer window showing the Controllers folder highlighted in the HelloWorldWeb project.](../images/powerpoint-tutorial-solution-explorer-controllers.png) - -1. Right-click (or select and hold) the **Controllers** folder and select **Add** > **New Scaffolded Item...**. - -1. In the **Add Scaffold** dialog window, select **Web API 2 Controller - Empty** and choose the **Add** button. - -1. In the **Add Controller** dialog window, enter **PhotoController** as the controller name and choose the **Add** button. Visual Studio creates and opens the **PhotoController.cs** file. - - > [!IMPORTANT] - > The scaffolding process doesn't complete properly on some versions of Visual Studio after version 16.10.3. If you have the **Global.asax** and **./App_Start/WebApiConfig.cs** files, then skip to step 6. - > - > ![The Visual Studio Solution Explorer window showing the scaffolded files highlighted in the HelloWorldWeb project.](../images/powerpoint-tutorial-solution-explorer-scaffolded.png) - -1. If you're missing scaffolding files from the **HelloWorldWeb** project, add them as follows. - - 1. Using Solution Explorer, add a new folder named **App_Start** to the **HelloWorldWeb** project. - - 1. Right-click (or select and hold) the **App_Start** folder and select **Add** > **Class...**. - - 1. In the **Add New Item** dialog, name the file **WebApiConfig.cs** then choose the **Add** button. - - 1. Replace the entire contents of the **WebApiConfig.cs** file with the following code. - - ```cs - using System; - using System.Collections.Generic; - using System.Linq; - using System.Web; - using System.Web.Http; - - namespace HelloWorldWeb.App_Start - { - public static class WebApiConfig - { - public static void Register(HttpConfiguration config) - { - config.MapHttpAttributeRoutes(); - - config.Routes.MapHttpRoute( - name: "DefaultApi", - routeTemplate: "api/{controller}/{id}", - defaults: new { id = RouteParameter.Optional } - ); - } - } - } - ``` - - 1. In the Solution Explorer, right-click (or select and hold) the **HelloWorldWeb** project and select **Add** > **New Item...**. - - 1. In the **Add New Item** dialog, search for "global", select **Global Application Class**, then choose the **Add** button. By default, the file is named **Global.asax**. - - 1. Replace the entire contents of the **Global.asax.cs** file with the following code. - - ```cs - using HelloWorldWeb.App_Start; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Web; - using System.Web.Http; - using System.Web.Security; - using System.Web.SessionState; - - namespace HelloWorldWeb - { - public class WebApiApplication : System.Web.HttpApplication - { - protected void Application_Start() - { - GlobalConfiguration.Configure(WebApiConfig.Register); - } - } - } - ``` - - 1. In the Solution Explorer, right-click (or select and hold) the **Global.asax** file and choose **View Markup**. - - 1. Replace the entire contents of the **Global.asax** file with the following code. - - ```XML - <%@ Application Codebehind="Global.asax.cs" Inherits="HelloWorldWeb.WebApiApplication" Language="C#" %> - ``` - -1. Replace the entire contents of the **PhotoController.cs** file with the following code that calls the Bing service to retrieve the photo of the day as a Base64-encoded string. When you use the Office JavaScript API to insert an image into a document, the image data must be specified as a Base64-encoded string. - - ```csharp - using System; - using System.IO; - using System.Net; - using System.Text; - using System.Web.Http; - using System.Xml; - - namespace HelloWorldWeb.Controllers - { - public class PhotoController : ApiController - { - public string Get() - { - string url = "http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1"; - - // Create the request. - HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); - WebResponse response = request.GetResponse(); - - using (Stream responseStream = response.GetResponseStream()) - { - // Process the result. - StreamReader reader = new StreamReader(responseStream, Encoding.UTF8); - string result = reader.ReadToEnd(); - - // Parse the XML response and get the URL. - XmlDocument doc = new XmlDocument(); - doc.LoadXml(result); - string photoURL = "http://bing.com/" + doc.SelectSingleNode("/images/image/url").InnerText; - - // Fetch the photo and return it as a Base64-encoded string. - return getPhotoFromURL(photoURL); - } - } - - private string getPhotoFromURL(string imageURL) - { - var webClient = new WebClient(); - byte[] imageBytes = webClient.DownloadData(imageURL); - return Convert.ToBase64String(imageBytes); - } - } - } - ``` - -1. In the **Home.html** file, replace `TODO1` with the following markup. This markup defines the **Insert Image** button that will appear within the add-in's task pane. - - ```html - - ``` - -1. In the **Home.js** file, replace `TODO1` with the following code to assign the event handler for the **Insert Image** button. - - ```js - $('#insert-image').on("click", insertImage); - ``` - -1. In the **Home.js** file, replace `TODO2` with the following code to define the `insertImage` function. This function fetches the image from the Bing web service and then calls the `insertImageFromBase64String` function to insert that image into the document. - - ```js - function insertImage() { - // Get image from web service (as a Base64-encoded string). - $.ajax({ - url: "/api/photo/", - dataType: "text", - success: function (result) { - insertImageFromBase64String(result); - }, error: function (xhr, status, error) { - showNotification("Error", "Oops, something went wrong."); - } - }); - } - ``` - -1. In the **Home.js** file, replace `TODO3` with the following code to define the `insertImageFromBase64String` function. This function uses the Office JavaScript API to insert the image into the document. Note: - - - The `coercionType` option that's specified as the second parameter of the `setSelectedDataAsync` request indicates the type of data being inserted. - - - The `asyncResult` object encapsulates the result of the `setSelectedDataAsync` request, including status and error information if the request failed. - - ```js - function insertImageFromBase64String(image) { - // Call Office.js to insert the image into the document. - Office.context.document.setSelectedDataAsync(image, { - coercionType: Office.CoercionType.Image - }, - function (asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - showNotification("Error", asyncResult.error.message); - } - }); - } - ``` - -### Test the add-in - -1. Using Visual Studio, test the newly created PowerPoint add-in by pressing **F5** or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. - - ![The Start button highlighted in Visual Studio.](../images/powerpoint-tutorial-start.png) - -1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. - - ![The Show Taskpane button highlighted on the Home ribbon in PowerPoint.](../images/powerpoint-tutorial-show-taskpane-button.png) - -1. In the task pane, choose the **Insert Image** button to add the Bing photo of the day to the current slide. - - ![The PowerPoint add-in with the Insert Image button highlighted.](../images/powerpoint-tutorial-insert-image-button.png) - - > [!NOTE] - > If you get an error "Could not find file [...]\bin\roslyn\csc.exe", then do the following: - > - > 1. Open the **.\Web.config** file. - > 1. Find the **\** node for the .cs `extension`, then remove the `type` attribute and its value. - > 1. Save the file. - -1. In Visual Studio, stop the add-in by pressing **Shift+F5** or choosing the **Stop** button. PowerPoint will automatically close when the add-in is stopped. - - ![The Stop button highlighted in Visual Studio.](../images/powerpoint-tutorial-stop.png) - -## Customize user interface (UI) elements - -Complete the following steps to add markup that customizes the task pane UI. - -1. In the **Home.html** file, replace `TODO2` with the following markup to add a header section and title to the task pane. Note: - - - The styles that begin with `ms-` are defined by [Fabric Core in Office Add-ins](../design/fabric-core.md), a JavaScript front-end framework for building user experiences for Office. The **Home.html** file includes a reference to the Fabric Core stylesheet. - - ```html -
-
-
-
My PowerPoint add-in
-
-
-
- ``` - -1. In the **Home.html** file, find the **div** with `class="footer"` and delete that entire **div** to remove the footer section from the task pane. - -### Test the add-in - -1. Using Visual Studio, test the PowerPoint add-in by pressing **F5** or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. - - ![The Start button highlighted in Visual Studio.](../images/powerpoint-tutorial-start.png) - -1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. - - ![The Show Taskpane button highlighted on the PowerPoint Home ribbon.](../images/powerpoint-tutorial-show-taskpane-button.png) - -1. Notice that the task pane now contains a header section and title, and no longer contains a footer section. - - ![The PowerPoint add-in with Insert Image button.](../images/powerpoint-tutorial-new-task-pane-ui.png) - -1. In Visual Studio, stop the add-in by pressing **Shift+F5** or choosing the **Stop** button. PowerPoint will automatically close when the add-in is stopped. - - ![The Stop button highlighted in Visual Studio.](../images/powerpoint-tutorial-stop.png) - -## Insert text - -Complete the following steps to add code that inserts text into the title slide which contains the [Bing](https://www.bing.com) photo of the day. - -1. In the **Home.html** file, replace `TODO3` with the following markup. This markup defines the **Insert Text** button that will appear within the add-in's task pane. - - ```html -

- - ``` - -1. In the **Home.js** file, replace `TODO4` with the following code to assign the event handler for the **Insert Text** button. - - ```js - $('#insert-text').on("click", insertText); - ``` - -1. In the **Home.js** file, replace `TODO5` with the following code to define the `insertText` function. This function inserts text into the current slide. - - ```js - function insertText() { - Office.context.document.setSelectedDataAsync('Hello World!', - function (asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - showNotification("Error", asyncResult.error.message); - } - }); - } - ``` - -### Test the add-in - -1. Using Visual Studio, test the add-in by pressing **F5** or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. - - ![The Start button highlighted in Visual Studio.](../images/powerpoint-tutorial-start.png) - -1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. - - ![The Show Taskpane button on the Home ribbon in PowerPoint.](../images/powerpoint-tutorial-show-taskpane-button.png) - -1. In the task pane, choose the **Insert Image** button to add the Bing photo of the day to the current slide and choose a design for the slide that contains a text box for the title. - - ![The selected PowerPoint title slide and the Insert Image button highlighted in the add-in.](../images/powerpoint-tutorial-insert-image-slide-design.png) - -1. Put your cursor in the text box on the title slide and then in the task pane, choose the **Insert Text** button to add text to the slide. - - ![The selected PowerPoint title slide with the Insert Text button highlighted in the add-in.](../images/powerpoint-tutorial-insert-text.png) - -1. In Visual Studio, stop the add-in by pressing **Shift+F5** or choosing the **Stop** button. PowerPoint will automatically close when the add-in is stopped. - - ![The Stop button highlighted in Visual Studio.](../images/powerpoint-tutorial-stop.png) - -## Get slide metadata - -Complete the following steps to add code that retrieves metadata for the selected slide. - -1. In the **Home.html** file, replace `TODO4` with the following markup. This markup defines the **Get Slide Metadata** button that will appear within the add-in's task pane. - - ```html -

- - ``` - -1. In the **Home.js** file, replace `TODO6` with the following code to assign the event handler for the **Get Slide Metadata** button. - - ```js - $('#get-slide-metadata').on("click", getSlideMetadata); - ``` - -1. In the **Home.js** file, replace `TODO7` with the following code to define the `getSlideMetadata` function. This function retrieves metadata for the selected slides and writes it to a popup dialog window within the add-in task pane. - - ```js - function getSlideMetadata() { - Office.context.document.getSelectedDataAsync(Office.CoercionType.SlideRange, - function (asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - showNotification("Error", asyncResult.error.message); - } else { - showNotification("Metadata for selected slides:", JSON.stringify(asyncResult.value), null, 2); - } - } - ); - } - ``` - -### Test the add-in - -1. Using Visual Studio, test the add-in by pressing **F5** or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. - - ![The Start button in Visual Studio.](../images/powerpoint-tutorial-start.png) - -1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. - - ![The Show Taskpane button on the PowerPoint Home ribbon.](../images/powerpoint-tutorial-show-taskpane-button.png) - -1. In the task pane, choose the **Get Slide Metadata** button to get the metadata for the selected slide. The slide metadata is written to the popup dialog window at the bottom of the task pane. In this case, the `slides` array within the JSON metadata contains one object that specifies the `id`, `title`, and `index` of the selected slide. If multiple slides had been selected when you retrieved slide metadata, the `slides` array within the JSON metadata would contain one object for each selected slide. - - ![The Get Slide Metadata button highlighted in the add-in.](../images/powerpoint-tutorial-get-slide-metadata.png) - -1. In Visual Studio, stop the add-in by pressing **Shift+F5** or choosing the **Stop** button. PowerPoint will automatically close when the add-in is stopped. - - ![The Stop button in Visual Studio.](../images/powerpoint-tutorial-stop.png) - -## Navigate between slides - -Complete the following steps to add code that navigates between the slides of a document. - -1. In the **Home.html** file, replace `TODO5` with the following markup. This markup defines the four navigation buttons that will appear within the add-in's task pane. - - ```html -

- -

- -

- -

- -

- - ``` - -1. In the **Home.js** file, replace `TODO8` with the following code to assign the event handlers for the **Add Slides** and four navigation buttons. - - ```js - $('#add-slides').on("click", addSlides); - $('#go-to-first-slide').on("click", goToFirstSlide); - $('#go-to-next-slide').on("click", goToNextSlide); - $('#go-to-previous-slide').on("click", goToPreviousSlide); - $('#go-to-last-slide').on("click", goToLastSlide); - ``` - -1. In the **Home.js** file, replace `TODO9` with the following code to define the `addSlides` and navigation functions. Each of these functions uses the `goToByIdAsync` method to select a slide based upon its position in the document (first, last, previous, and next). - - ```js - async function addSlides() { - await PowerPoint.run(async function (context) { - context.presentation.slides.add(); - context.presentation.slides.add(); - - await context.sync(); - - showNotification("Success", "Slides added."); - goToLastSlide(); - }); - } - - function goToFirstSlide() { - Office.context.document.goToByIdAsync(Office.Index.First, Office.GoToType.Index, - function (asyncResult) { - if (asyncResult.status == "failed") { - showNotification("Error", asyncResult.error.message); - } - }); - } - - function goToLastSlide() { - Office.context.document.goToByIdAsync(Office.Index.Last, Office.GoToType.Index, - function (asyncResult) { - if (asyncResult.status == "failed") { - showNotification("Error", asyncResult.error.message); - } - }); - } - - function goToPreviousSlide() { - Office.context.document.goToByIdAsync(Office.Index.Previous, Office.GoToType.Index, - function (asyncResult) { - if (asyncResult.status == "failed") { - showNotification("Error", asyncResult.error.message); - } - }); - } - - function goToNextSlide() { - Office.context.document.goToByIdAsync(Office.Index.Next, Office.GoToType.Index, - function (asyncResult) { - if (asyncResult.status == "failed") { - showNotification("Error", asyncResult.error.message); - } - }); - } - ``` - -### Test the add-in - -1. Using Visual Studio, test the add-in by pressing **F5** or choosing the **Start** button to launch PowerPoint with the **Show Taskpane** add-in button displayed on the ribbon. The add-in will be hosted locally on IIS. - - ![The Start button highlighted on the Visual Studio toolbar.](../images/powerpoint-tutorial-start.png) - -1. If the add-in task pane isn't already open in PowerPoint, select the **Show Taskpane** button on the ribbon to open it. - - ![The Show Taskpane button highlighted on the Home ribbon in PowerPoint.](../images/powerpoint-tutorial-show-taskpane-button.png) - -1. In the task pane, choose the **Add Slides** button. Two new slides are added to the document and the last slide in the document is selected and displayed. - - ![The Add Slides button highlighted in the add-in.](../images/powerpoint-tutorial-add-slides-1.png) - -1. In the task pane, choose the **Go to First Slide** button. The first slide in the document is selected and displayed. - - ![The Go to First Slide button highlighted in the add-in.](../images/powerpoint-tutorial-go-to-first-slide.png) - -1. In the task pane, choose the **Go to Next Slide** button. The next slide in the document is selected and displayed. - - ![The Go to Next Slide button highlighted in the add-in.](../images/powerpoint-tutorial-go-to-next-slide.png) - -1. In the task pane, choose the **Go to Previous Slide** button. The previous slide in the document is selected and displayed. - - ![The Go to Previous Slide button highlighted in the add-in.](../images/powerpoint-tutorial-go-to-previous-slide.png) - -1. In the task pane, choose the **Go to Last Slide** button. The last slide in the document is selected and displayed. - - ![The Go to Last Slide button highlighted in the add-in.](../images/powerpoint-tutorial-go-to-last-slide.png) - -1. In Visual Studio, stop the add-in by pressing **Shift+F5** or choosing the **Stop** button. PowerPoint will automatically close when the add-in is stopped. - - ![The Stop button highlighted on the Visual Studio toolbar.](../images/powerpoint-tutorial-stop.png) - -## Code samples - -- [Completed PowerPoint add-in tutorial](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/powerpoint-tutorial): The result of completing this tutorial. - ---- - ## Next steps -In this tutorial, you've created a PowerPoint add-in that inserts an image, inserts text, gets slide metadata, and navigates between slides. To learn more about building PowerPoint add-ins, continue to the following article. +In this tutorial, you created a PowerPoint add-in that inserts an image, inserts text, gets slide metadata, and navigates between slides. To learn more about building PowerPoint add-ins, continue to the following article. > [!div class="nextstepaction"] > [PowerPoint add-ins overview](../powerpoint/powerpoint-add-ins.md) diff --git a/docs/tutorials/word-tutorial.md b/docs/tutorials/word-tutorial.md index ae07bf4ee2..0ee4ea781e 100644 --- a/docs/tutorials/word-tutorial.md +++ b/docs/tutorials/word-tutorial.md @@ -1,7 +1,7 @@ --- title: Word add-in tutorial description: In this tutorial, you'll build a Word add-in that inserts (and replaces) text ranges, paragraphs, images, HTML, tables, and content controls. You'll also learn how to format text and how to insert (and replace) content in content controls. -ms.date: 12/11/2023 +ms.date: 01/16/2025 ms.service: word #Customer intent: As a developer, I want to build a Word add-in that can interact with content in a Word document. ms.localizationpriority: high @@ -22,7 +22,7 @@ In this tutorial, you'll create a Word task pane add-in that: > [!TIP] > If you've already completed the [Build your first Word task pane add-in](../quickstarts/word-quickstart-yo.md) quick start, and want to use that project as a starting point for this tutorial, go directly to the [Insert a range of text](#insert-a-range-of-text) section to start this tutorial. > -> If you want a completed version of this tutorial, head over to the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/word-tutorial). +> If you want a completed version of this tutorial, visit the [Office Add-ins samples repo on GitHub](https://github.com/OfficeDev/Office-Add-in-samples/tree/main/Samples/tutorials/word-tutorial). ## Prerequisites @@ -37,12 +37,10 @@ In this tutorial, you'll create a Word task pane add-in that: - **What do you want to name your add-in?** `My Office Add-in` - **Which Office client application would you like to support?** `Word` -![The previous prompts and answers given to the Yeoman generator in a command line interface.](../images/yo-office-word.png) +:::image type="content" source="../images/yo-office-word.png" alt-text="The previous prompts and answers given to the Yeoman generator in a command line interface."::: After you complete the wizard, the generator creates the project and installs supporting Node components. -[!include[Yeoman generator next steps](../includes/yo-office-next-steps.md)] - ## Insert a range of text In this step of the tutorial, you'll programmatically test that your add-in supports the user's current version of Word, and then insert a paragraph into the document. @@ -143,11 +141,11 @@ In this step of the tutorial, you'll programmatically test that your add-in supp - To test your add-in in Word on the web, run the following command in the root directory of your project. When you run this command, the local web server starts. Replace "{url}" with the URL of a Word document on your OneDrive or a SharePoint library to which you have permissions. - [!INCLUDE [npm start:web command syntax](../includes/start-web-sideload-instructions.md)] + [!INCLUDE [npm start on web command syntax](../includes/start-web-sideload-instructions.md)] 1. In Word, if the "My Office Add-in" task pane isn't already open, choose the **Home** tab, and then choose the **Show Taskpane** button on the ribbon to open the add-in task pane. - ![The Show Taskpane button highlighted in Word.](../images/word-quickstart-addin-2b.png) + :::image type="content" source="../images/word-quickstart-addin-2b.png" alt-text="The Show Taskpane button highlighted in Word."::: 1. In the task pane, choose the **Insert Paragraph** button. @@ -155,7 +153,7 @@ In this step of the tutorial, you'll programmatically test that your add-in supp 1. Choose the **Insert Paragraph** button again. Note that the new paragraph appears above the previous one because the `insertParagraph` method is inserting at the start of the document's body. - ![The Insert Paragraph button in the add-in.](../images/word-tutorial-insert-paragraph-2.png) + :::image type="content" source="../images/word-tutorial-insert-paragraph-2.png" alt-text="The Insert Paragraph button in the add-in."::: 1. [!include[Instructions to stop web server and uninstall dev add-in](../includes/stop-uninstall-dev-add-in.md)] @@ -301,7 +299,7 @@ In this step of the tutorial, you'll apply a built-in style to text, apply a cus 1. Choose the **Change Font** button. The font of the second paragraph changes to 18 pt., bold, Courier New. - ![The results of applying the styles and fonts defined for the add-in buttons Apply Style, Apply Custom Style, and Change font.](../images/word-tutorial-apply-styles-and-font-2.png) + :::image type="content" source="../images/word-tutorial-apply-styles-and-font-2.png" alt-text="The results of applying the styles and fonts defined for the add-in buttons Apply Style, Apply Custom Style, and Change font."::: ## Replace text and insert text @@ -541,7 +539,7 @@ async function insertTextIntoRange() { 1. Choose the **Change Quantity Term** button. Note that "many" replaces the selected text. - ![The results of choosing the add-in buttons Insert Abbreviation, Add Version Info, and Change Quantity Term.](../images/word-tutorial-text-replace-2.png) + :::image type="content" source="../images/word-tutorial-text-replace-2.png" alt-text="The results of choosing the add-in buttons Insert Abbreviation, Add Version Info, and Change Quantity Term."::: ## Insert images, HTML, and tables @@ -720,7 +718,7 @@ Complete the following steps to define the image that you'll insert into the doc 1. Choose the **Insert Table** button and note that a table is inserted after the second paragraph. - ![The results of choosing the add-in buttons Insert Image, Insert HTML, and Insert Table.](../images/word-tutorial-insert-image-html-table-2.png) + :::image type="content" source="../images/word-tutorial-insert-image-html-table-2.png" alt-text="The results of choosing the add-in buttons Insert Image, Insert HTML, and Insert Table."::: ## Create and update content controls @@ -837,6 +835,7 @@ In this step of the tutorial, you'll learn how to create Rich Text content contr 1. Choose the **Rename Service** button and note that the text of the content control changes to "Fabrikam Online Productivity Suite". ![The results of choosing the add-in buttons Create Content Control and Rename Service.](../images/word-tutorial-content-control-2.png) + :::image type="content" source="../images/word-tutorial-content-control-2.png" alt-text="The results of choosing the add-in buttons Create Content Control and Rename Service."::: ## Next steps diff --git a/docs/visio/index.yml b/docs/visio/index.yml deleted file mode 100644 index 8081640bbe..0000000000 --- a/docs/visio/index.yml +++ /dev/null @@ -1,47 +0,0 @@ -### YamlMime:Landing - -title: Visio documentation # < 60 chars -summary: You can use the Visio JavaScript APIs to embed Visio diagrams in SharePoint Online. Learn how to use the Visio JavaScript APIs with Visio on the web to build solutions for SharePoint Online. # < 160 chars - -metadata: - title: Visio documentation # Required; page title displayed in search results. Include the brand. < 60 chars. - description: Resources for learning about embedding Visio diagrams in SharePoint. # Required; article description that is displayed in search results. < 160 chars. - ms.service: visio #Required - ms.topic: landing-page # Required - ms.date: 03/29/2021 #Required; mm/dd/yyyy format. - ms.localizationpriority: high - -# linkListType: architecture | concept | deploy | download | get-started | how-to-guide | learn | overview | quickstart | reference | sample | tutorial | video | whats-new - -landingContent: -# Cards and links should be based on top customer tasks or top subjects -# Start card title with a verb - # Card (optional) - - title: About Visio JavaScript API - linkLists: - - linkListType: overview - links: - - text: What is Visio JavaScript API? - url: ../reference/overview/visio-javascript-reference-overview.md - - linkListType: get-started - links: - - text: Create a script that displays the shape text of the selected shape - url: ../reference/overview/visio-javascript-reference-overview.md#get-started - - linkListType: reference - links: - - text: Explore the Visio JavaScript API - url: /javascript/api/visio - - # Card - - title: Resources - linkLists: - - linkListType: reference - links: - - text: Ask questions - url: https://stackoverflow.com/questions/tagged/office-js - - text: Request features - url: https://aka.ms/m365dev-suggestions - - text: Report issues - url: https://github.com/officedev/office-js/issues - - text: Office Add-ins additional resources - url: ../resources/resources-links-help.md diff --git a/docs/reference/overview/visio-javascript-reference-overview.md b/docs/visio/visio-overview.md similarity index 77% rename from docs/reference/overview/visio-javascript-reference-overview.md rename to docs/visio/visio-overview.md index e5b2146418..a4f1fe5a2f 100644 --- a/docs/reference/overview/visio-javascript-reference-overview.md +++ b/docs/visio/visio-overview.md @@ -1,18 +1,18 @@ --- title: Visio JavaScript API overview description: Overview of the Visio JavaScript API. -ms.date: 07/18/2022 +ms.date: 07/15/2025 ms.service: visio ms.topic: overview ms.custom: scenarios:getting-started -ms.localizationpriority: high +ms.localizationpriority: medium --- # Visio JavaScript API overview -You can use the Visio JavaScript APIs to embed Visio diagrams in *classic* SharePoint pages in SharePoint Online. (This extensibility feature is not supported in on-premise SharePoint or on SharePoint Framework pages.) +You can use the Visio JavaScript APIs to embed Visio diagrams in *classic* SharePoint pages in SharePoint Online. (This extensibility feature isn't supported in on-premises SharePoint or SharePoint Framework pages.) -An embedded Visio diagram is a diagram that is stored in a SharePoint document library and displayed on a SharePoint page. To embed a Visio diagram, display it in an HTML `