diff --git a/.github/images/chili-peppers.jpg b/.github/images/chili-peppers.jpg new file mode 100644 index 000000000..4645d4e04 Binary files /dev/null and b/.github/images/chili-peppers.jpg differ diff --git a/.github/images/crustacean.jpg b/.github/images/crustacean.jpg new file mode 100644 index 000000000..121835e5a Binary files /dev/null and b/.github/images/crustacean.jpg differ diff --git a/.github/images/dried-legume.jpg b/.github/images/dried-legume.jpg new file mode 100644 index 000000000..9e2889b05 Binary files /dev/null and b/.github/images/dried-legume.jpg differ diff --git a/.github/images/fruit.jpg b/.github/images/fruit.jpg new file mode 100644 index 000000000..a487e83b5 Binary files /dev/null and b/.github/images/fruit.jpg differ diff --git a/.github/images/green-leaf.jpg b/.github/images/green-leaf.jpg new file mode 100644 index 000000000..0b96fbfcf Binary files /dev/null and b/.github/images/green-leaf.jpg differ diff --git a/.github/workflows/auto-publish.yml b/.github/workflows/auto-publish.yml new file mode 100644 index 000000000..72a284cc6 --- /dev/null +++ b/.github/workflows/auto-publish.yml @@ -0,0 +1,39 @@ +name: auto-publish +run-name: Automatically publish snippets +on: + schedule: + - cron: '15 10 * * TUE' + - cron: '15 10 * * THU' +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 prod + run: | + echo "Checking out prod branch" + git checkout prod + - name: Merge from main into prod + run: | + echo "Merging from main to prod" + git merge main + - name: Push changes + run: | + echo "Pushing changes to prod branch" + git push origin prod + diff --git a/.gitignore b/.gitignore index a133b9391..2d2f29ea5 100644 --- a/.gitignore +++ b/.gitignore @@ -64,4 +64,6 @@ npm-debug.log* ~$* # Used to ignore "playlists", but having those checked-in for diffing purposes is very useful, so undoing the ignore: -# playlists/** \ No newline at end of file +# playlists/** + +package-lock.json \ No newline at end of file diff --git a/README.md b/README.md index 5722c3af0..0fe20ada1 100644 --- a/README.md +++ b/README.md @@ -11,92 +11,91 @@ A collection of code snippets built with [Script Lab](//github.com/OfficeDev/scr ### One-time tasks 1. [Fork](https://help.github.com/articles/about-forks/) this project into your GitHub account. -2. Clone your fork to your development computer. -3. Ensure that you have Node, version 6.10+, installed. (To check the version run the command `node -v`.) -4. Install `yarn` as a global package `npm install yarn --global`. -5. Be sure your CLI is in the root of the office-js-snippets repo and run `yarn install`. (It is similar to `npm install`.) -6. Set up the original \OfficeDev\office-js-snippets as the upstream repo for your local repo by following the steps in [Configuring a remote for a fork](https://help.github.com/articles/configuring-a-remote-for-a-fork/). -7. If you'll be using Visual Studio Code as your editor, install the [TSLint](https://marketplace.visualstudio.com/items?itemName=eg2.tslint) extension for Visual Studio Code. +1. Clone your fork to your development computer. +1. Ensure that you have Node, version 6.10+, installed. (To check the version run the command `node -v`.) +1. Be sure your CLI is in the root of the office-js-snippets repo and run `npm install` to install all dependencies. +1. Set up the original \OfficeDev\office-js-snippets as the upstream repo for your local repo by following the steps in [Configuring a remote for a fork](https://help.github.com/articles/configuring-a-remote-for-a-fork/). +1. If you'll be using Visual Studio Code as your editor, install the [TSLint](https://marketplace.visualstudio.com/items?itemName=eg2.tslint) extension for Visual Studio Code. ### Adding a new sample > For the git tasks in this procedure, the instructions assume that you're using a CLI. You are welcome to use a GUI git client. Consult the client's help to learn how to carry out the same tasks. -1. Create a snippet using [Script Lab](https://github.com/OfficeDev/script-lab/blob/master/README.md#what-is). Ensure that the name and description are what you want to be shown publicly. Use standard TypeScript indentation. Improper indentation can cause a failure of the build that you run in a later step. See also the [**Style guidelines**](#style-guidelines) section below. -2. Choose the Share icon, and then choose **Copy to Clipboard**. -3. Paste the contents into a text editor. -4. Near the top of the file, you will see the line `api_set: {}`. This needs to be changed to specify the host API version of the most recently added API that is used in your snippet. For example, if the snippet is for Excel and it uses some APIs that were introduced in Excel API 1.3, some in 1.4, and some in 1.5, then you need to specify `ExcelApi 1.5` as the value of the `api_set` property. Put a line break and four spaces before the value and no {} characters. To continue the example, when you're done the property would look like this: +1. Create a snippet using [Script Lab](https://github.com/OfficeDev/script-lab/blob/master/README.md#what-is). Ensure that the name and description are what you want to be shown publicly. Make sure to keep your snippet small. Use standard TypeScript indentation. Improper indentation can cause a failure of the build that you run in a later step. See also the [**Style guidelines**](#style-guidelines) and [**Size restrictions**](#size-restrictions) sections below. +1. Choose the Share icon, and then choose **Copy to Clipboard**. +1. Paste the contents into a text editor. +1. Near the top of the file, you will see the line `api_set: {}`. This needs to be changed to specify the host API version of the most recently added API that is used in your snippet. For example, if the snippet is for Excel and it uses some APIs that were introduced in Excel API 1.3, some in 1.4, and some in 1.5, then you need to specify `ExcelApi 1.5` as the value of the `api_set` property. Put a line break and four spaces before the value and no {} characters. To continue the example, when you're done the property would look like this: ```yaml api_set: ExcelApi: '1.5' ``` -5. Check the name and description property values, also near the top of the file, and edit as needed. -6. Save the file **somewhere outside of the office-js-snippets project**. (You will move it into the project in a later step.) The file name must have a ".yaml" extension and it must be in [`kebab-case`](http://wiki.c2.com/?KebabCase). For examples, see the existing *.yaml files in the subfolders of the `samples` folder of the project. -7. Make sure the main branch of your fork is in sync with the main branch of the upstream \OfficeDev\office-js-snippets repo by following the steps in [Syncing a fork](https://help.github.com/articles/syncing-a-fork/). -8. Create a new branch at the **office-js-snippets** root folder of your local repo by running the command `git checkout -b {name_of_your_new_branch}`. (This will create and checkout the new branch. *Stay in this branch for all the remaining steps.*) Each snippet should have its own branch. Suggestion: use the name of the yaml file that you created above (without the extension) as the branch name. -9. Decide the folder where your snippet should be added. All snippet files must reside within the appropriate subfolder inside the `samples` folder. Within the `samples` folder, the structure of subfolders is as follows: +1. Check the name and description property values, also near the top of the file, and edit as needed. +1. Save the file **somewhere outside of the office-js-snippets project**. (You will move it into the project in a later step.) The file name must have a ".yaml" extension and it must be in [`kebab-case`](http://wiki.c2.com/?KebabCase). For examples, see the existing *.yaml files in the subfolders of the `samples` folder of the project. +1. Make sure the main branch of your fork is in sync with the main branch of the upstream \OfficeDev\office-js-snippets repo by following the steps in [Syncing a fork](https://help.github.com/articles/syncing-a-fork/). +1. Create a new branch at the **office-js-snippets** root folder of your local repo by running the command `git checkout -b {name_of_your_new_branch}`. (This will create and checkout the new branch. *Stay in this branch for all the remaining steps.*) Each snippet should have its own branch. Suggestion: use the name of the yaml file that you created above (without the extension) as the branch name. +1. Decide the folder where your snippet should be added. All snippet files must reside within the appropriate subfolder inside the `samples` folder. Within the `samples` folder, the structure of subfolders is as follows: - - The base folders such as `excel`, `word`, etc. primarily represent the various host applications. - - Within each base folder, group folders organize snippets into various categories. - - Within each group folder, each .yaml file represents a snippet. + - The base folders such as `excel`, `word`, etc. primarily represent the various host applications. + - Within each base folder, group folders organize snippets into various categories. + - Within each group folder, each .yaml file represents a snippet. - > **Note**: If your snippet doesn't fit with any existing group folder, create a new group folder inside the base folder. If the existing folders in the base folder begin with numbers, such as `03-range`, then your new folder should also begin with a number. Since the numbers determine the sequence of the groups in Script Lab, use a number between the numbers of the groups between which you want the new folder to appear. + > **Note**: If your snippet doesn't fit with any existing group folder, create a new group folder inside the base folder. If the existing folders in the base folder begin with numbers, such as `03-range`, then your new folder should also begin with a number. Since the numbers determine the sequence of the groups in Script Lab, use a number between the numbers of the groups between which you want the new folder to appear. -10. Open one of the `.yaml` files already in the group folder. If it has an `order` property near the top, then the snippets in the group folder are ordered in a particular sequence in Script Lab. Add an `order` property to the top of your `.yaml` file and give it a number that is between the order numbers of the snippets between which you want it to appear. -11. Copy your `.yaml` file to the chosen group folder. -12. Run `yarn start`. If there are no problems, the output will end with a `Done!`. If there are errors, review the output to check what caused the build validation to fail, and fix as needed. See [**Known errors and fixes**](#known-errors-and-fixes-in-the-build-tool) for more information. +1. Open one of the `.yaml` files already in the group folder. If it has an `order` property near the top, then the snippets in the group folder are ordered in a particular sequence in Script Lab. Add an `order` property to the top of your `.yaml` file and give it a number that is between the order numbers of the snippets between which you want it to appear. +1. Copy your `.yaml` file to the chosen group folder. +1. Run `npm start`. If there are no problems, the output will end with a `Done!`. If there are errors, review the output to check what caused the build validation to fail, and fix as needed. See [**Known errors and fixes**](#known-errors-and-fixes-in-the-build-tool) for more information. - > **Note**: The `yarn start` command adds an `id` property to the top of the file. + > **Note**: The `npm start` command adds an `id` property to the top of the file. -13. Re-run `yarn start`, and fix errors, until the build succeeds. -14. Run `git status`. You should see that, in addition to your new `.yaml` file (or possibly new folder), a `playlist\{host}.yaml` file (where `{host}` is `excel`, `word`, etc.) has also been changed. This is expected. The build tool you just ran added a reference to your new snippet to this file. -15. Run the following two commands. The commit message should be a brief description of what the snippet demonstrates; for example, `"shows how to use getWhatever method"`. +1. Re-run `npm start`, and fix errors, until the build succeeds. +1. Run `git status`. You should see that, in addition to your new `.yaml` file (or possibly new folder), a `playlist\{host}.yaml` file (where `{host}` is `excel`, `word`, etc.) has also been changed. This is expected. The build tool you just ran added a reference to your new snippet to this file. +1. Run the following two commands. The commit message should be a brief description of what the snippet demonstrates; for example, `"shows how to use getWhatever method"`. ``` git add -A git commit -m "{commit message}" ``` -16. Push the snippet to your fork by running: +1. Push the snippet to your fork by running: ``` git push --set-upstream origin {name_of_your_new_branch} ``` -17. You now create a [pull request](https://help.github.com/articles/about-pull-requests/). In your fork on GitHub, *switch to your new branch*. -18. Choose **New pull request**. -19. On the **Open a pull request** page, verify that: +1. You now create a [pull request](https://help.github.com/articles/about-pull-requests/). In your fork on GitHub, *switch to your new branch*. +1. Choose **New pull request**. +1. On the **Open a pull request** page, verify that: - - the base fork is `OfficeDev/office-js-snippets` - - the base branch is `main` - - the head fork is `{your-GitHub-account}/office-js-snippets` - - the "compare" branch is `{name_of_your_new_branch}`. + - the base fork is `OfficeDev/office-js-snippets` + - the base branch is `main` + - the head fork is `{your-GitHub-account}/office-js-snippets` + - the "compare" branch is `{name_of_your_new_branch}`. -20. The title of the pull request defaults to your commit message. Change it as needed and optionally add a comment to provide additional information about the pull request to the reviewers. -21. All pull requests to office-js-snippets must be approved by at least one reviewer. On the right side of the page is a **Reviewers** section. You can optionally suggest one or more people to review the pull request. (GitHub sometimes lists one or more admins of the repo by default, but it is not consistent in doing this.) Your pull request will be reviewed even if you don't suggest anyone. -22. Choose **Create pull request**. The page for your pull request will open. There will initially be a message on the page saying **Some checks haven’t completed yet**. An online version of the same build tool that you ran locally is testing the files again. It usually takes a few minutes. +1. The title of the pull request defaults to your commit message. Change it as needed and optionally add a comment to provide additional information about the pull request to the reviewers. +1. All pull requests to office-js-snippets must be approved by at least one reviewer. On the right side of the page is a **Reviewers** section. You can optionally suggest one or more people to review the pull request. (GitHub sometimes lists one or more admins of the repo by default, but it is not consistent in doing this.) Your pull request will be reviewed even if you don't suggest anyone. +1. Choose **Create pull request**. The page for your pull request will open. There will initially be a message on the page saying **Some checks haven’t completed yet**. An online version of the same build tool that you ran locally is testing the files again. It usually takes a few minutes. - > **Note**: Since your pull request passed locally, it should pass the online test too. Once in a while, the online test fails when the local test passed. This is usually a bug in the online test service. If this happens, cancel the pull request, wait a few hours, and then repeat the steps for creating a pull request. + > **Note**: Since your pull request passed locally, it should pass the online test too. Once in a while, the online test fails when the local test passed. This is usually a bug in the online test service. If this happens, cancel the pull request, wait a few hours, and then repeat the steps for creating a pull request. -23. The reviewers may make comments on your pull request and ask you to make changes. Make changes in Script Lab and then repeat the process of creating the `.yaml` file. You do not have to create the new branch again, but make sure it is checked out when you copy the changed `.yaml` file over the previous version. After you commit and push the changed version to your fork, the new version is automatically added to your existing pull request. *Do **not** create a new pull request.* -24. When the reviewers are satisfied, your pull request will be merged to the `main` branch and the pull request will be closed. +1. The reviewers may make comments on your pull request and ask you to make changes. Make changes in Script Lab and then repeat the process of creating the `.yaml` file. You do not have to create the new branch again, but make sure it is checked out when you copy the changed `.yaml` file over the previous version. After you commit and push the changed version to your fork, the new version is automatically added to your existing pull request. *Do **not** create a new pull request.* +1. When the reviewers are satisfied, your pull request will be merged to the `main` branch and the pull request will be closed. - > **Note**: In a few days, the repo admins will merge your snippet into the `prod` branch. It will then appear in **Samples** area of Script Lab. (It is in the **My Snippets** area as soon as you create it.) + > **Note**: In a few days, the repo admins will merge your snippet into the `prod` branch. It will then appear in **Samples** area of Script Lab. (It is in the **My Snippets** area as soon as you create it.) -25. Optionally, you can delete the branch you created from your fork and/or your local clone. +1. Optionally, you can delete the branch you created from your fork and/or your local clone. #### Known errors and fixes in the build tool - An error saying that `name` has upper-case letters or other disallowed characters is *not* referring to the `name` property in the file. It is referring to the file name itself. You'll also get this error, if the file extension is not `.yaml`. -## Style guidelines: +## Style guidelines Basic snippet structure is as follows: ```ts -$("#run").click(() => tryCatch(run)); +$("#run").on("click", () => tryCatch(run)); async function run() { await Word.run(async (context) => { @@ -121,26 +120,35 @@ async function tryCatch(callback) { A few style rules to observe: -* Use standard TypeScript indentation. -* For each button, define a corresponding `async` function to be run when the button is clicked. The `async` function can be called "run" if there is only one button on the page -- otherwise, name it as you will. -* Each button-click handler should invoke the `tryCatch` function, passing in the name of the `async` function to be executed when the button is clicked. -* All HTML IDs should be `all-lower-case-and-hyphenated`. -* Unless you are explicitly showing pretty UI, you don't have to do the popup notification except for one or two samples. It's a lot of HTML & JS code, and also not strictly Fabric-y (there is a more "correct" way of doing this with components). -* Strings should be in double-quotes. -* Don't forget the semicolons. -* `Libraries` in snippets must have a specific version. Eg. `jquery@3.1.1`. +- Use standard TypeScript indentation. +- For each button, define a corresponding `async` function to be run when the button is clicked. The `async` function can be called "run" if there is only one button on the page -- otherwise, name it as you will. +- Each button-click handler should invoke the `tryCatch` function, passing in the name of the `async` function to be executed when the button is clicked. +- All HTML IDs should be `all-lower-case-and-hyphenated`. +- Unless you are explicitly showing pretty UI, you don't have to do the popup notification except for one or two samples. It's a lot of HTML & JS code, and also not strictly Fabric-y (there is a more "correct" way of doing this with components). +- Strings should be in double-quotes. +- Don't forget the semicolons. +- `Libraries` in snippets must have a specific version. Eg. `jquery@3.1.1`. + +## Size restrictions + +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. ## Debugging the build script -* The scripts for building/validating the snippets are under the `config` folder -- in particular, under `build.ts`. +- The scripts for building/validating the snippets are under the `config` folder -- in particular, under `build.ts`. > **Note**: If debugging in Visual Studio Code, you can use "F5" to attach the debugger, but be sure to run `npm run tsc` before you do (and after any code change!). `F5` is not set to recompile! ## Join the Microsoft 365 Developer Program -Get a free sandbox, tools, and other resources you need to build solutions for the Microsoft 365 platform. -- [Free developer sandbox](https://developer.microsoft.com/microsoft-365/dev-program#Subscription) Get a free, renewable 90-day Microsoft 365 E5 developer subscription. -- [Sample data packs](https://developer.microsoft.com/microsoft-365/dev-program#Sample) Automatically configure your sandbox by installing user data and content to help you build your solutions. -- [Access to experts](https://developer.microsoft.com/microsoft-365/dev-program#Experts) Access community events to learn from Microsoft 365 experts. -- [Personalized recommendations](https://developer.microsoft.com/microsoft-365/dev-program#Recommendations) Find developer resources quickly from your personalized dashboard. + +Join the [Microsoft 365 Developer Program](https://aka.ms/m365devprogram) to get resources and information to help you build solutions for the Microsoft 365 platform, including recommendations tailored to your areas of interest. + +You might also qualify for a free developer subscription that's renewable for 90 days and comes configured with sample data; for details, see the [FAQ](https://learn.microsoft.com/office/developer-program/microsoft-365-developer-program-faq#who-qualifies-for-a-microsoft-365-e5-developer-subscription-). + +--- This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information, see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/SECURITY.md b/SECURITY.md index e138ec5d6..4a0f12f81 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -24,7 +24,7 @@ Please include the requested information listed below (as much as you can provid * Any special configuration required to reproduce the issue * Step-by-step instructions to reproduce the issue * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue + * Impact of the issue, including how a threat actor might exploit the issue This information will help us triage your report more quickly. diff --git a/config/build.documentation.ts b/config/build.documentation.ts index 154bc03c2..ee9d8f653 100644 --- a/config/build.documentation.ts +++ b/config/build.documentation.ts @@ -36,7 +36,7 @@ export async function buildReferenceDocSnippetExtracts( await rmRf('snippet-extractor-output'); await mkDir('snippet-extractor-output'); - const contents = snippetExtractsPerHost.map(extracts => jsyaml.safeDump(extracts)).join(''); + const contents = snippetExtractsPerHost.map(extracts => jsyaml.dump(extracts)).join(''); await writeFile(path.resolve(`snippet-extractor-output/snippets.yaml`), contents); } @@ -119,7 +119,7 @@ function getExtractedDataFromSnippet( const filename = snippetIdsToFilenames[row.snippetId]; if (filename) { try { - const script = (jsyaml.safeLoad(fs.readFileSync(filename).toString()) as ISnippet).script.content; + const script = (jsyaml.load(fs.readFileSync(filename).toString()) as ISnippet).script.content; const fullSnippetTextArray = script.split('\n') .map(line => line.replace(/\r/, '')); @@ -161,13 +161,13 @@ function getExtractedDataFromSnippet( const whitespaceCountOnFirstLine = spaceFollowedByWordsRegex.exec(fullSnippetTextArray[0])[1].length; // Place snippet location as comment. - const editedFilename = filename.substr(filename.lastIndexOf('samples')).replace(/\\/g, '/'); - text = '// Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/' + editedFilename + '\n'; + const editedFilename = filename.substring(filename.lastIndexOf('samples')).replace(/\\/g, '/'); + text = '// Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/' + editedFilename + '\n\n'; text += indented .map(line => { - if (line.substr(0, whitespaceCountOnFirstLine).trim().length === 0) { - return line.substr(whitespaceCountOnFirstLine); + if (line.substring(0, whitespaceCountOnFirstLine).trim().length === 0) { + return line.substring(whitespaceCountOnFirstLine); } else { return line; } diff --git a/config/build.ts b/config/build.ts index 43cbe3392..fcd9e231c 100644 --- a/config/build.ts +++ b/config/build.ts @@ -2,7 +2,8 @@ import * as path from 'path'; import { isNil, isString, isArray, isEmpty, sortBy, cloneDeep } from 'lodash'; -import * as chalk from 'chalk'; +import chalk from 'chalk'; +import escapeStringRegexp from 'escape-string-regexp'; import { status } from './status'; import { SnippetFileInput, SnippetProcessedData, @@ -14,7 +15,6 @@ import { getShareableYaml } from './snippet.helpers'; import { processLibraries } from './libraries.processor'; import { startCase, groupBy, map } from 'lodash'; import * as jsyaml from 'js-yaml'; -import escapeStringRegexp = require('escape-string-regexp'); import * as fsx from 'fs-extra'; @@ -84,7 +84,7 @@ async function processSnippets(processedSnippets: Dictionary{}; additionalFields.id = snippet.id; additionalFields.api_set = snippet.api_set; - additionalFields.author = snippet.author; + + // Only set author field if it has a value + if (snippet.author) { + additionalFields.author = snippet.author; + } if ((typeof (snippet as any).order) !== 'undefined') { // # for ordering, if present (used for samples only) @@ -130,11 +134,12 @@ async function processSnippets(processedSnippets: Dictionary dictionary[item] || item); return parts.join(' '); } @@ -170,8 +184,8 @@ async function processSnippets(processedSnippets: Dictionary reference.trim()); - if (libs.indexOf('office-ui-fabric-js@1.4.0/dist/css/fabric.min.css') >= 0) { - if (libs.indexOf('office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css') <= 0) { + if (libs.indexOf('office-ui-fabric-core@11.1.0/dist/css/fabric.min.css') >= 0) { + if (libs.indexOf('office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css') <= 0) { throw new Error('Fabric reference is specified, without a reference to a corresponding "fabric.components.min.css". Please add this second Fabric reference as well.'); } } @@ -363,11 +377,12 @@ async function processSnippets(processedSnippets: Dictionary { +export const banner = (title: string, message: string = null, chalkFn: any = null) => { if (!chalkFn) { chalkFn = chalk.bold; } @@ -55,7 +54,7 @@ export const banner = (title: string, message: string = null, chalkFn: chalk.Cha }; export function getPrintableDetails(item: any, indent: number) { - const details = jsyaml.safeDump(item, { + const details = jsyaml.dump(item, { indent: 4, lineWidth: -1, skipInvalid: true @@ -83,16 +82,11 @@ export const mkDir = (dir: string) => * Deletes a folder. * @param dir An absolute path to the directory. */ -export const rmRf = (dir: string) => - new Promise((resolve, reject) => { - const location = path.resolve(dir); - rimraf(location, (err) => { - if (err) { - return reject(err); - } - return resolve(location); - }); - }); +export const rmRf = async (dir: string): Promise => { + const location = path.resolve(dir); + await rimraf(location); + return location; +}; /** * Load all the files and folders in a given directory. diff --git a/config/snippet.helpers.ts b/config/snippet.helpers.ts index f2574957d..449e40d59 100644 --- a/config/snippet.helpers.ts +++ b/config/snippet.helpers.ts @@ -91,7 +91,7 @@ function scrubCarriageReturns(snippet: ISnippet) { export function getScrubbedSnippet(snippet: ISnippet, keep: SnippetFieldType): ISnippet { let copy = {}; forIn(snippetFields, (fieldType, fieldName) => { - if (fieldType & keep) { + if (fieldType & keep && snippet[fieldName] !== undefined) { copy[fieldName] = snippet[fieldName]; } }); @@ -103,7 +103,7 @@ export function getShareableYaml(rawSnippet: ISnippet, additionalFields: ISnippe const snippet = { ...getScrubbedSnippet(rawSnippet, SnippetFieldType.PUBLIC), ...additionalFields }; scrubCarriageReturns(snippet); - return jsyaml.safeDump(snippet, { + return jsyaml.dump(snippet, { indent: 4, lineWidth: -1, sortKeys: ((a, b) => snippetFieldSortingOrder[a] - snippetFieldSortingOrder[b]), diff --git a/config/status.ts b/config/status.ts index 44003309c..2f953ee73 100644 --- a/config/status.ts +++ b/config/status.ts @@ -1,6 +1,5 @@ -import * as nodeStatus from 'node-status'; -import * as chalk from 'chalk'; -import { isString, find, isNil, isArray } from 'lodash'; +import chalk from 'chalk'; +import { isString, isNil, isArray } from 'lodash'; interface IStage { steps: any[]; @@ -13,16 +12,29 @@ export class Status { steps: { [step: string]: boolean } = {}; get console() { - return nodeStatus.console(); + // Return the global console object methods + return { + log: global.console.log.bind(global.console), + error: global.console.error.bind(global.console), + warn: global.console.warn.bind(global.console), + info: global.console.info.bind(global.console) + }; } constructor() { - /* Initialize the status library */ - this.stages = nodeStatus.addItem('stages', { - steps: [] - }); + /* Initialize the simple status system */ + this.stages = { + steps: [], + count: 0, + doneStep: this.doneStep.bind(this) + }; + } - nodeStatus.start(); + private doneStep(completed: boolean, message?: string): void { + const symbol = completed ? chalk.green('✓') : chalk.red('✗'); + if (message) { + global.console.log(`${symbol} ${message}`); + } } /** @@ -37,22 +49,18 @@ export class Status { success = success && additionalDetails.findIndex(item => item instanceof Error) < 0; const messageArray = getDetailsArray(); + const symbol = success ? chalk.green('✓') : chalk.red('✗'); - if (messageArray.length === 0) { - this.stages.doneStep(success); - } else { - // Add a newline before - messageArray.splice(0, 0, ''); - this.stages.doneStep(success, messageArray.join('\n * ') + '\n'); - //FIXME `${chalk.bold.red('WARNING: one of the messages above was an error')}`) - } - - this.steps[stage] = false; + // Log the completion with symbol + global.console.log(`${symbol} ${stage}`); - if (!find(this.steps as any, (item) => item === true)) { - nodeStatus.stop(); + if (messageArray.length > 0) { + messageArray.forEach(msg => { + global.console.log(` * ${msg}`); + }); } + this.steps[stage] = false; // Helper: function getDetailsArray() { @@ -82,12 +90,13 @@ export class Status { } /** - * Add a new stage and complete the previous stage. + * Add a new stage and mark it as started. * @param stage Name of the stage. */ add(stage: string) { this.stages.steps.push(stage); this.steps[stage] = true; + global.console.log(chalk.cyan(`○ ${stage}`)); } } diff --git a/package.json b/package.json index 6628cb3e3..457b9471d 100644 --- a/package.json +++ b/package.json @@ -23,25 +23,22 @@ }, "homepage": "https://github.com/OfficeDev/office-js-snippets#readme", "dependencies": { - "chalk": "1.1.3", - "escape-string-regexp": "^2.0.0", - "exceljs": "^4.3.0", - "fs-extra": "3.0.1", - "js-yaml": "^3.13.1", + "chalk": "^4.1.2", + "escape-string-regexp": "^4.0.0", + "exceljs": "^4.4.0", + "fs-extra": "11.3.2", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "node-status": "^1.0.0", - "rimraf": "^3.0.0", - "shelljs": "^0.8.5", - "yarn": "^1.22.19" + "rimraf": "^6.0.1", + "shelljs": "^0.10.0" }, "devDependencies": { - "@types/chalk": "0.4.31", - "@types/fs-extra": "3.0.1", - "@types/js-yaml": "^3.12.0", - "@types/lodash": "^4.14.175", - "@types/node": "^11.10.5", - "@types/shelljs": "^0.8.3", - "tslint": "^6.1.0", - "typescript": "^3.3.3333" + "@types/fs-extra": "^11.0.4", + "@types/js-yaml": "^4.0.9", + "@types/lodash": "^4.17.20", + "@types/node": "^24.5.2", + "@types/shelljs": "^0.8.17", + "tslint": "^6.1.3", + "typescript": "^5.9.2" } } diff --git a/playlists-prod/excel.yaml b/playlists-prod/excel.yaml index a0932e91b..059d3893b 100644 --- a/playlists-prod/excel.yaml +++ b/playlists-prod/excel.yaml @@ -30,7 +30,7 @@ - id: excel-chart-axis name: Axis details fileName: chart-axis.yaml - description: 'Gets, sets, and removes axis unit, label, and title in a chart.' + description: Gets, sets, and removes axis unit, label, and title in a chart. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-axis.yaml group: Chart @@ -162,19 +162,37 @@ - id: excel-chart-trendlines name: Trendlines fileName: chart-trendlines.yaml - description: 'Adds, gets, and formats trendlines in a chart.' + description: Adds, gets, and formats trendlines in a chart. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-trendlines.yaml group: Chart api_set: ExcelApi: '1.7' +- id: excel-chart-data-labels + name: Data labels + fileName: chart-data-labels.yaml + description: Add and style data labels for your charts. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-labels.yaml + group: Chart + api_set: + ExcelApi: '1.19' +- id: excel-chart-leader-lines + name: Leader lines + fileName: chart-leader-lines.yaml + description: Show and hide leader lines for chart labels. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml + group: Chart + api_set: + ExcelApi: '1.19' - id: excel-comment-basics name: Comment basics fileName: comment-basics.yaml - description: 'Adds, edits, and removes comments.' + description: Adds, edits, and removes comments. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-basics.yaml - group: Comment + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-basics.yaml + group: Comments And Notes api_set: ExcelApi: '1.10' - id: excel-comment-mentions @@ -182,17 +200,17 @@ fileName: comment-mentions.yaml description: Mentions someone in a comment. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-mentions.yaml - group: Comment + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-mentions.yaml + group: Comments And Notes api_set: ExcelApi: '1.11' - id: excel-comment-replies name: Comment replies fileName: comment-replies.yaml - description: 'Adds, edits, and removes comment replies.' + description: Adds, edits, and removes comment replies. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-replies.yaml - group: Comment + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-replies.yaml + group: Comments And Notes api_set: ExcelApi: '1.10' - id: excel-comment-resolution @@ -200,10 +218,19 @@ fileName: comment-resolution.yaml description: Resolves and reopens a comment thread. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-resolution.yaml - group: Comment + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-resolution.yaml + group: Comments And Notes api_set: ExcelApi: '1.10' +- id: excel-note-basics + name: Notes + fileName: excel-note-basics.yaml + description: Adds, edits, and removes notes. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml + group: Comments And Notes + api_set: + ExcelApi: '1.18' - id: excel-range-conditional-formatting-basic name: Basic conditional formatting fileName: conditional-formatting-basic.yaml @@ -278,10 +305,21 @@ group: Custom Functions api_set: CustomFunctionsRuntime: 1.4 +- id: excel-custom-functions-custom-enum + name: Function with custom enums + fileName: custom-enum.yaml + description: >- + Use custom enums as parameters in a custom function that searches for + flights. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/16-custom-functions/custom-enum.yaml + group: Custom Functions + api_set: + CustomFunctionsRuntime: 1.5 - id: excel-custom-xml-parts-create-set-get-and-delete-custom-xml-parts name: Using custom XML parts fileName: create-set-get-and-delete-custom-xml-parts.yaml - description: 'Creates, sets, gets, and deletes a custom XML part.' + description: Creates, sets, gets, and deletes a custom XML part. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/create-set-get-and-delete-custom-xml-parts.yaml group: Custom XML Parts @@ -296,12 +334,12 @@ group: Custom XML Parts api_set: ExcelApi: '1.5' -- id: excel-data-types-formatted-number +- id: excel-data-types-doubles name: 'Data types: Formatted numbers' fileName: data-types-formatted-number.yaml description: >- - This sample shows how to set and get data types using the formatted number - properties. + This sample shows how to set and get formatted numbers using double data + types. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-formatted-number.yaml group: Data Types @@ -331,9 +369,11 @@ api_set: ExcelApi: '1.16' - id: excel-data-types-error-values - name: 'Data types: Set error values' + name: 'Data types: Set and change error values' fileName: data-types-error-values.yaml - description: This sample shows how to set a cell value to an error data type. + description: >- + This sample shows how to set a cell value to an error data type, and then + update the value of cells that contain an error data type. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-error-values.yaml group: Data Types @@ -372,6 +412,15 @@ group: Data Types api_set: ExcelApi: '1.16' +- id: excel-data-types-basic-types + name: Basic types with metadata + fileName: data-types-basic-types.yaml + description: This sample shows how to work with metadata on basic types. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-basic-types.yaml + group: Data Types + api_set: + ExcelApi: '1.19' - id: excel-data-validation name: Data validation fileName: data-validation.yaml @@ -576,9 +625,9 @@ api_set: ExcelAPI: '1.14' - id: excel-named-item-create-and-remove-named-item - name: 'Create, access, and remove' + name: Create, access, and remove fileName: create-and-remove-named-item.yaml - description: 'Creates, accesses, and removes named items in a worksheet.' + description: Creates, accesses, and removes named items in a worksheet. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/34-named-item/create-and-remove-named-item.yaml group: Named Item @@ -736,16 +785,16 @@ - id: excel-range-hyperlink name: Hyperlinks fileName: range-hyperlink.yaml - description: 'Creates, updates, and clears hyperlinks in a range.' + description: Creates, updates, and clears hyperlinks in a range. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml group: Range api_set: ExcelApi: '1.7' - id: excel-range-insert-delete-and-clear-range - name: 'Insert, delete, and clear' + name: Insert, delete, and clear fileName: insert-delete-clear-range.yaml - description: 'Inserts, deletes, and clears a range.' + description: Inserts, deletes, and clears a range. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/insert-delete-clear-range.yaml group: Range @@ -894,6 +943,15 @@ group: Range api_set: ExcelAPI: '1.15' +- id: excel-cell-controls + name: Checkboxes + fileName: range-cell-control.yaml + description: This sample shows how to add and remove checkboxes from a table. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml + group: Range + api_set: + ExcelApi: '1.18' - id: excel-shape-create-and-delete name: Create and delete geometric shapes fileName: shape-create-and-delete.yaml @@ -950,6 +1008,15 @@ group: Shape api_set: ExcelApi: '1.9' +- id: excel-shape-get-active + name: Get active shape image + fileName: shape-get-active.yaml + description: Get an image of the active shape in your workbook. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-get-active.yaml + group: Shape + api_set: + ExcelApi: '1.19' - id: excel-table-add-rows-and-columns-to-a-table name: Add rows and columns fileName: add-rows-and-columns-to-a-table.yaml @@ -1131,6 +1198,15 @@ group: Workbook api_set: ExcelAPI: '1.13' +- id: excel-workbook-built-in-function + name: Use built-in Excel functions + fileName: workbook-built-in-functions.yaml + description: Use the VLOOKUP and SUM built-in Excel functions. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-built-in-functions.yaml + group: Workbook + api_set: + ExcelAPI: '1.2' - id: excel-worksheet-active-worksheet name: Active worksheet fileName: active-worksheet.yaml @@ -1141,9 +1217,9 @@ api_set: ExcelApi: '1.1' - id: excel-worksheet-add-delete-rename-move-worksheet - name: 'Add, delete, rename, and move worksheet' + name: Add, delete, rename, and move worksheet fileName: add-delete-rename-move-worksheet.yaml - description: 'Adds, deletes, renames, and moves a worksheet.' + description: Adds, deletes, renames, and moves a worksheet. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/add-delete-rename-move-worksheet.yaml group: Worksheet diff --git a/playlists-prod/outlook.yaml b/playlists-prod/outlook.yaml index 9164cfb85..9a1b827bc 100644 --- a/playlists-prod/outlook.yaml +++ b/playlists-prod/outlook.yaml @@ -1,7 +1,7 @@ - id: outlook-roaming-settings-roaming-settings name: Use add-in settings fileName: roaming-settings.yaml - description: 'Gets, sets, and saves add-in roaming settings' + description: Gets, sets, saves, and removes add-in roaming settings. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/10-roaming-settings/roaming-settings.yaml group: Roaming Settings @@ -40,11 +40,11 @@ api_set: Mailbox: '1.1' - id: outlook-item-body-add-inline-base64-image - name: Add inline Base64 image to message or appointment body (Compose) + name: Add inline Base64-encoded image to message or appointment body (Compose) fileName: add-inline-base64-image.yaml description: >- - Add an inline Base64 image to the body of a message or appointment being - composed. + Add an inline Base64-encoded image to the body of a message or appointment + being composed. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/add-inline-base64-image.yaml group: Item Body @@ -97,6 +97,15 @@ group: Item Save And Close api_set: Mailbox: '1.3' +- id: outlook-close-async + name: Close the current message and discard changes (Message Compose) + fileName: close-async.yaml + description: Closes the current message and discards any unsaved changes when specified. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/25-item-save-and-close/close-async.yaml + group: Item Save And Close + api_set: + Mailbox: '1.14' - id: outlook-item-save-and-close-save name: Save the item fileName: save.yaml @@ -247,13 +256,13 @@ name: Work with notification messages fileName: add-getall-remove.yaml description: >- - Adds different kinds of notification messages, gets all, and replaces and - removes an individual notification message. + Adds different kinds of notification messages, gets all notifications, and + replaces and removes an individual notification message. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml group: Notifications api_set: - Mailbox: '1.3' + Mailbox: '1.10' - id: outlook-attachments-attachments-compose name: Manipulate attachments (Item Compose) fileName: attachments-compose.yaml @@ -264,7 +273,7 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml group: Attachments api_set: - Mailbox: '1.1' + Mailbox: '1.8' - id: outlook-attachments-get-attachment-content name: Get attachment content fileName: get-attachment-content.yaml @@ -286,7 +295,7 @@ - id: outlook-categories-work-with-categories name: Work with item categories fileName: work-with-categories.yaml - description: 'Gets, adds, and removes categories assigned to the item.' + description: Gets, adds, and removes categories assigned to the item. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml group: Categories @@ -295,7 +304,7 @@ - id: outlook-categories-work-with-master-categories name: Work with the categories master list fileName: work-with-master-categories.yaml - description: 'Gets, adds, and removes categories in the master list for the mailbox.' + description: Gets, adds, and removes categories in the master list for the mailbox. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml group: Categories @@ -376,9 +385,9 @@ api_set: Mailbox: '1.9' - id: outlook-display-items-display-reply-with-attachments - name: 'Create a reply, with attachments' + name: Create a reply with attachments fileName: display-reply-with-attachments.yaml - description: Opens a reply message forms and adds sample attachments. + description: Opens a reply or reply-all message form and adds sample attachments. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml group: Display Items @@ -407,16 +416,16 @@ api_set: Mailbox: '1.13' - id: outlook-delegates-and-shared-folders-get-shared-properties - name: Perform an operation as delegate + name: Identify a shared folder or shared mailbox context fileName: get-shared-properties.yaml description: >- - Gets shared properties for an item, checks delegate permissions and performs - an operation as delegate. + Identifies whether the current mail item is in a shared folder or shared + mailbox by getting its properties. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml group: Delegates And Shared Folders api_set: - Mailbox: '1.8' + Mailbox: '1.13' - id: outlook-mime-headers-get-internet-headers-message-read name: Get internet headers fileName: get-internet-headers-message-read.yaml @@ -424,134 +433,120 @@ rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/get-internet-headers-message-read.yaml group: Mime Headers - api_set: {} + api_set: + Mailbox: '1.8' - id: outlook-mime-headers-manage-custom-internet-headers-message-compose name: Work with custom internet headers fileName: manage-custom-internet-headers-message-compose.yaml - description: 'Set, get, and remove custom internet headers on a message in Compose mode.' + description: >- + Sets, gets, and removes custom internet headers on a message in Compose + mode. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml group: Mime Headers api_set: Mailbox: '1.8' -- id: outlook-entities-and-regex-matches-basic-entities - name: Entities (Item Read) - fileName: basic-entities.yaml - description: Gets extracted entities. - rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/basic-entities.yaml - group: Entities And Regex Matches - api_set: - Mailbox: '1.1' -- id: outlook-entities-and-regex-matches-contextual - name: 'Entities and Regex matches (Item Read, contextual)' +- id: outlook-regex-matches-contextual + name: Get regex matches (Item Read, contextual) fileName: contextual.yaml - description: >- - Gets extracted entities and regex matches when the add-in is opened as a - contextual add-in. + description: Gets regex matches when the add-in is opened as a contextual add-in. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/contextual.yaml - group: Entities And Regex Matches + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-regex-matches/contextual.yaml + group: Regex Matches api_set: - Mailbox: '1.1' -- id: outlook-entities-and-regex-matches-selected - name: 'Selected entities and Regex matches (Item Read, contextual)' - fileName: selected.yaml - description: Gets selected entities and regex matches. + Mailbox: '1.6' +- id: outlook-events-drag-drop-item + name: Drag and drop an item into the task pane + fileName: drag-drop-item.yaml + description: >- + Handles the drag-and-drop event when a user drags and drops messages and + file attachments into the add-in task pane. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/selected.yaml - group: Entities And Regex Matches + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/80-events/drag-drop-item.yaml + group: Events api_set: - Mailbox: '1.6' + Mailbox: '1.5' - id: outlook-tokens-and-service-calls-ids-and-urls - name: Endpoint URLs and item IDs + name: Endpoint URLs and item IDs in Exchange on-premises environments fileName: ids-and-urls.yaml description: >- - Retrieves and displays REST and EWS endpoint URLs and item IDs, and converts - item IDs for different protocols. + Retrieves the Exchange Web Services (EWS) endpoint URL and item IDs and + converts item IDs for different protocols. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/ids-and-urls.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/ids-and-urls.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.5' - id: outlook-tokens-and-service-calls-user-identity-token - name: Get a user identity token + name: Get a user identity token in Exchange on-premises environments fileName: user-identity-token.yaml - description: Gets a user identity token to use in authentication flows. + description: >- + Gets a user identity token for authentication flows in an Exchange + on-premises environment. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/user-identity-token.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/user-identity-token.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.1' - id: outlook-tokens-and-service-calls-user-callback-token - name: Get a callback token + name: Get a callback token in Exchange on-premises environments fileName: user-callback-token.yaml description: >- - Gets a callback token to use for calling outlook services from add-in's - backend service. + Gets a callback token to call Outlook services from an add-in's backend + service in an Exchange on-premises environment. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/user-callback-token.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/user-callback-token.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.1' -- id: outlook-tokens-and-service-calls-basic-rest-cors - name: Get a message using REST - fileName: basic-rest-cors.yaml - description: Gets a message using REST without any back-end code. - rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/basic-rest-cors.yaml - group: Tokens And Service Calls - api_set: - Mailbox: '1.5' - id: outlook-tokens-and-service-calls-make-ews-request-async - name: Get a message using EWS + name: >- + Get a message using Exchange Web Services (EWS) in Exchange on-premises + environments fileName: make-ews-request-async.yaml - description: Gets a message using EWS without any back-end code. + description: >- + Uses EWS in an Exchange on-premises environment to get a message without any + backend code. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/make-ews-request-async.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/make-ews-request-async.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.1' - id: outlook-tokens-and-service-calls-send-message-using-make-ews-request-async - name: Send a message using EWS + name: >- + Send a message using Exchange Web Services (EWS) in Exchange on-premises + environments fileName: send-message-using-make-ews-request-async.yaml - description: Sends a message using EWS without any back-end code. + description: >- + Uses EWS in an Exchange on-premises environment to send a message without + any backend code. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/send-message-using-make-ews-request-async.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/send-message-using-make-ews-request-async.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.1' - id: outlook-tokens-and-service-calls-get-icaluid-as-organizer - name: Get an appointment's iCalUId as an organizer + name: Get an appointment's iCalUId as the organizer (Exchange on-premises only) fileName: get-icaluid-as-organizer.yaml description: >- - Uses EWS to get an appointment's iCalUId value where the user is the - organizer. + Uses Exchange Web Services (EWS) in an Exchange on-premises environment to + get an appointment's iCalUId value where the user is the organizer. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-organizer.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-organizer.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.3' - id: outlook-tokens-and-service-calls-get-icaluid-as-attendee - name: Get an appointment's iCalUId as an attendee + name: Get an appointment's iCalUId as an attendee (Exchange on-premises only) fileName: get-icaluid-as-attendee.yaml description: >- - Uses EWS to get an appointment's iCalUId value where the user is the - attendee. + Uses Exchange Web Services (EWS) in an Exchange on-premises environment to + get an appointment's iCalUId value where the user is an attendee. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-attendee.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-attendee.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.1' -- id: outlook-tokens-and-service-calls-item-id-compose - name: Get an item ID in compose mode - fileName: item-id-compose.yaml - description: 'Gets an item ID in compose mode, to use in certain delegate scenarios.' - rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/item-id-compose.yaml - group: Tokens And Service Calls - api_set: - Mailbox: '1.8' - id: outlook-other-item-apis-get-subject-read name: Get the subject (Read) fileName: get-subject-read.yaml @@ -663,7 +658,7 @@ - id: outlook-other-item-apis-get-add-remove-enhancedlocation-appointment name: Manage the locations of an appointment fileName: get-add-remove-enhancedlocation-appointment.yaml - description: 'Gets, adds, and removes locations on an appointment (enhancedLocation API).' + description: Gets, adds, and removes locations on an appointment (enhancedLocation API). rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml group: Other Item APIs @@ -728,7 +723,7 @@ - id: outlook-other-item-apis-session-data-apis name: Work with session data APIs (Compose) fileName: session-data-apis.yaml - description: 'Sets, gets, gets all, removes, and clears session data in Compose mode.' + description: Sets, gets, gets all, removes, and clears session data in Compose mode. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml group: Other Item APIs @@ -743,23 +738,95 @@ group: Other Item APIs api_set: Mailbox: '1.13' -- id: outlook-calendar-properties-apis - name: Work with calendar properties APIs (Compose) - fileName: calendar-properties-apis.yaml +- id: outlook-other-item-apis-get-message-properties + name: Get properties of selected messages (Message Compose, Message Read) + fileName: get-message-properties.yaml + description: Gets the properties of multiple selected messages. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-message-properties.yaml + group: Other Item APIs + api_set: + Mailbox: '1.14' +- id: outlook-other-item-apis-get-set-sensitivity-level + name: Get and set the sensitivity level (Appointment Organizer) + fileName: get-set-sensitivity-level.yaml + description: Gets and sets the sensitivity level of an appointment being composed. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-sensitivity-level.yaml + group: Other Item APIs + api_set: + Mailbox: '1.14' +- id: outlook-get-eml-format + name: Get the Base64-encoded EML format of a message (Message Read) + fileName: get-eml-format.yaml + description: Gets the Base64-encoded EML format of a message in read mode. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-eml-format.yaml + group: Other Item APIs + api_set: + Mailbox: '1.14' +- id: outlook-get-in-reply-to + name: Get the ID of the message being replied to (Message Compose) + fileName: get-in-reply-to.yaml + description: Retrieves the ID of the message being replied to by the current message. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-in-reply-to.yaml + group: Other Item APIs + api_set: + Mailbox: '1.14' +- id: outlook-get-conversation-index + name: Get the position of a message in a conversation (Message Compose) + fileName: get-conversation-index.yaml description: >- - Gets and sets isAllDayEvent and sensitivity properties of an appointment in - Compose mode. + Retrieves the Base64-encoded position of the current message in a + conversation thread. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/calendar-properties-apis.yaml - group: Preview APIs + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-conversation-index.yaml + group: Other Item APIs api_set: - Mailbox: preview -- id: outlook-close-async - name: Close the current message and discard changes (Message Compose) - fileName: close-async.yaml - description: Closes the current message and discards any unsaved changes when specified. + Mailbox: '1.14' +- id: outlook-get-item-class-async + name: Get item class (Message Compose) + fileName: get-item-class-async.yaml + description: Retrieves the item class property of the message being composed. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-class-async.yaml + group: Other Item APIs + api_set: + Mailbox: '1.14' +- id: outlook-other-item-apis-item-id-compose + name: Get an item ID in compose mode + fileName: item-id-compose.yaml + description: Gets an item ID in compose mode. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/item-id-compose.yaml + group: Other Item APIs + api_set: + Mailbox: '1.8' +- id: outlook-send-async + name: Send the current message or appointment (Compose) + fileName: send-async.yaml + description: Sends the current message or appointment. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/send-async.yaml + group: Other Item APIs + api_set: + Mailbox: '1.15' +- id: outlook-other-item-apis-get-loaded-message-properties + name: Get properties of a loaded message (Message Compose, Message Read) + fileName: get-loaded-message-properties.yaml + description: Gets the properties of the currently loaded message. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-loaded-message-properties.yaml + group: Other Item APIs + api_set: + Mailbox: '1.15' +- id: outlook-get-set-isalldayevent + name: Get and set the isAllDayEvent property (Appointment Organizer) + fileName: get-set-isalldayevent.yaml + description: Gets and sets the isAllDayEvent property of an appointment being composed. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/close-async.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/get-set-isalldayevent.yaml group: Preview APIs api_set: Mailbox: preview diff --git a/playlists-prod/powerpoint.yaml b/playlists-prod/powerpoint.yaml index ba4058e8e..910edb0af 100644 --- a/playlists-prod/powerpoint.yaml +++ b/playlists-prod/powerpoint.yaml @@ -1,19 +1,21 @@ - id: powerpoint-basics-basic-api-call-ts name: Basic API call (TypeScript) fileName: basic-api-call-ts.yaml - description: Performs a basic PowerPoint API call using TypeScript + description: Performs a basic PowerPoint API call using TypeScript. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/basics/basic-api-call-ts.yaml group: Basics - api_set: PowerPointApi '1.4' + api_set: + PowerPointApi: '1.4' - id: powerpoint-basics-basic-api-call-js name: Basic API call (JavaScript) fileName: basic-api-call-js.yaml - description: Performs a basic PowerPoint API call using JavaScript + description: Performs a basic PowerPoint API call using JavaScript. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/basics/basic-api-call-js.yaml group: Basics - api_set: PowerPointApi '1.4' + api_set: + PowerPointApi: '1.4' - id: powerpoint-basics-basic-common-api-call name: Basic API call (Office 2013) fileName: basic-common-api-call.yaml @@ -24,7 +26,7 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/basics/basic-common-api-call.yaml group: Basics api_set: - Selection: 1.1 + Selection: '1.1' - id: powerpoint-create-presentation name: Create presentation fileName: create-presentation.yaml @@ -35,7 +37,16 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/document/create-presentation.yaml group: Document api_set: - PowerPoint: 1.1 + PowerPointApi: '1.1' +- id: powerpoint-hyperlinks-manage-hyperlinks + name: Get hyperlinks + fileName: manage-hyperlinks.yaml + description: Gets the hyperlinks found in a slide. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/hyperlinks/manage-hyperlinks.yaml + group: Hyperlinks + api_set: + PowerPointApi: '1.6' - id: powerpoint-basics-insert-image name: Insert Image fileName: insert-image.yaml @@ -60,8 +71,17 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/scenarios/searches-wikipedia-api.yaml group: Scenarios api_set: {} +- id: powerpoint-shapes + name: Insert shape, line, and text box + fileName: shapes.yaml + description: Inserts geometric shapes, lines, and text boxes to a slide. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml + group: Shapes + api_set: + PowerPointApi: '1.4' - id: powerpoint-shapes-get-set-shapes - name: 'Get, set, load, and save shapes' + name: Get, set, load, and save shapes fileName: get-set-shapes.yaml description: Get and set one or more selected shapes. Load and save one or more shapes. rawUrl: >- @@ -69,14 +89,42 @@ group: Shapes api_set: PowerPointApi: '1.5' -- id: powerpoint-shapes - name: 'Insert shape, line, and text box' - fileName: shapes.yaml - description: 'Inserts geometric shapes, lines, and text boxes to a slide.' +- id: powerpoint-shapes-get-shapes-by-type + name: Select shapes by type + fileName: get-shapes-by-type.yaml + description: Gets shapes in a slide based on their type, such as GeometricShape or Line. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml group: Shapes - api_set: PowerPointApi '1.4' + api_set: + PowerPointApi: '1.4' +- id: powerpoint-shapes-add-modify-tables + name: Add and modify tables + fileName: add-modify-tables.yaml + description: Shows how to add and modify tables in a presentation. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + group: Shapes + api_set: + PowerPointApi: '1.8' +- id: powerpoint-shapes-binding-to-shapes + name: Binding to shapes + fileName: binding-to-shapes.yaml + description: Shows how to create binding references for images and work with z-order. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml + group: Shapes + api_set: + PowerPointApi: '1.8' +- id: powerpoint-shapes-group-ungroup-shapes + name: Group and ungroup shapes + fileName: group-ungroup-shapes.yaml + description: Shows how to create two shapes then group and ungroup them. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/group-ungroup-shapes.yaml + group: Shapes + api_set: + PowerPointApi: '1.8' - id: powerpoint-add-slides name: Add slides to a presentation fileName: add-slides.yaml @@ -94,17 +142,17 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/insert-slides.yaml group: Slide Management api_set: - PowerPointApi: '1.2' + PowerPointApi: '1.5' - id: powerpoint-basics-get-slide-metadata name: Get slide metadata fileName: get-slide-metadata.yaml - description: 'Gets the title, index, and ID of the selected slide(s).' + description: Gets the title, index, and ID of the selected slides. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-slide-metadata.yaml group: Slide Management api_set: {} - id: powerpoint-slide-management-get-set-slides - name: 'Get, set, load, and save slides' + name: Get, set, load, and save slides fileName: get-set-slides.yaml description: Get and set one or more selected slides. Load and save one or more slides. rawUrl: >- @@ -112,6 +160,15 @@ group: Slide Management api_set: PowerPointApi: '1.5' +- id: powerpoint-slide-management-export-import-slide + name: Export and import slide + fileName: export-import-slide.yaml + description: Shows how to export and import a slide. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/export-import-slide.yaml + group: Slide Management + api_set: + PowerPointApi: '1.8' - id: powerpoint-tags name: Work with tags fileName: tags.yaml @@ -124,7 +181,7 @@ - id: powerpoint-text-get-set-textrange name: Work with text range selections fileName: get-set-textrange.yaml - description: 'Get, set, load, and save text range selections.' + description: Get, set, load, and save text range selections. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml group: Text diff --git a/playlists-prod/word.yaml b/playlists-prod/word.yaml index 7e06a63fd..72fdf9972 100644 --- a/playlists-prod/word.yaml +++ b/playlists-prod/word.yaml @@ -30,7 +30,7 @@ - id: word-content-controls-insert-and-change-content-controls name: Content control basics fileName: insert-and-change-content-controls.yaml - description: 'Inserts, updates, and retrieves content controls.' + description: Inserts, updates, and retrieves content controls. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-content-controls.yaml group: Content Controls @@ -102,6 +102,42 @@ group: Content Controls api_set: WordApi: '1.5' +- id: word-content-controls-insert-and-change-checkbox-content-control + name: Manage checkbox content controls + fileName: insert-and-change-checkbox-content-control.yaml + description: Inserts, updates, retrieves, and deletes checkbox content controls. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml + group: Content Controls + api_set: + WordApi: '1.7' +- id: word-content-controls-insert-and-change-combo-box-content-control + name: Manage combo box content controls + fileName: insert-and-change-combo-box-content-control.yaml + description: Inserts, updates, and deletes combo box content controls. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml + group: Content Controls + api_set: + WordApi: '1.9' +- id: word-content-controls-insert-and-change-dropdown-list-content-control + name: Manage dropdown list content controls + fileName: insert-and-change-dropdown-list-content-control.yaml + description: Inserts, updates, and deletes dropdown list content controls. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml + group: Content Controls + api_set: + WordApi: '1.9' +- id: word-content-controls-get-change-tracking-states + name: Get change tracking states of content controls + fileName: get-change-tracking-states.yaml + description: Gets change tracking states of content controls. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/get-change-tracking-states.yaml + group: Content Controls + api_set: + WordApi: '1.5' - id: word-images-insert-and-get-pictures name: Use inline pictures fileName: insert-and-get-pictures.yaml @@ -110,7 +146,7 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml group: Images api_set: - WordApi: '1.1' + WordApiDesktop: '1.1' - id: word-lists-insert-list name: Create a list fileName: insert-list.yaml @@ -120,6 +156,15 @@ group: Lists api_set: WordApi: '1.3' +- id: word-lists-manage-styles + name: Get list styles + fileName: manage-list-styles.yaml + description: This sample shows how to get the list styles in the current document. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/manage-list-styles.yaml + group: Lists + api_set: + WordApiDesktop: '1.1' - id: word-lists-organize-list name: Organize a list fileName: organize-list.yaml @@ -177,12 +222,12 @@ - id: word-paragraph-paragraph-properties name: Paragraph properties fileName: paragraph-properties.yaml - description: 'Sets indentation, space between paragraphs, and other paragraph properties.' + description: Sets indentation, space between paragraphs, and other paragraph properties. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml group: Paragraph api_set: - WordApi: '1.2' + WordApi: '1.1' - id: word-paragraph-search name: Search fileName: search.yaml @@ -201,6 +246,50 @@ group: Paragraph api_set: WordApi: '1.1' +- id: word-paragraph-get-text + name: Get text + fileName: get-text.yaml + description: >- + Shows how to get paragraph text, including hidden text and text marked for + deletion. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-text.yaml + group: Paragraph + api_set: + WordApi: '1.7' +- id: word-paragraph-onadded-event + name: On adding paragraphs + fileName: onadded-event.yaml + description: >- + Registers, triggers, and deregisters the onParagraphAdded event that tracks + the addition of paragraphs. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onadded-event.yaml + group: Paragraph + api_set: + WordApi: '1.6' +- id: word-paragraph-onchanged-event + name: On changing content in paragraphs + fileName: onchanged-event.yaml + description: >- + Registers, triggers, and deregisters the onParagraphChanged event that + tracks when content is changed in paragraphs. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onchanged-event.yaml + group: Paragraph + api_set: + WordApi: '1.6' +- id: word-paragraph-ondeleted-event + name: On deleting paragraphs + fileName: ondeleted-event.yaml + description: >- + Registers, triggers, and deregisters the onParagraphDeleted event that + tracks the removal of paragraphs. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/ondeleted-event.yaml + group: Paragraph + api_set: + WordApi: '1.6' - id: word-properties-get-built-in-properties name: Built-in document properties fileName: get-built-in-properties.yaml @@ -248,6 +337,15 @@ group: Ranges api_set: WordApi: '1.3' +- id: word-ranges-get-pages + name: Work with pages, panes, and windows + fileName: get-pages.yaml + description: Shows how to work with pages, panes, and windows. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml + group: Ranges + api_set: + WordApiDesktop: '1.2' - id: word-tables-table-cell-access name: Create and access a table fileName: table-cell-access.yaml @@ -268,6 +366,35 @@ group: Tables api_set: WordApi: '1.3' +- id: word-tables-manage-custom-style + name: Manage custom table style + fileName: manage-custom-style.yaml + description: >- + Shows how to manage primarily margins and alignments of a custom table style + in the current document. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-custom-style.yaml + group: Tables + api_set: + WordApiDesktop: '1.1' +- id: word-shapes-manage-shapes-text-boxes + name: Work with shapes and text boxes + fileName: manage-shapes-text-boxes.yaml + description: Shows how to work with shapes and text boxes. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml + group: Shapes + api_set: + WordApiDesktop: '1.2' +- id: word-document-manage-body + name: Manage body + fileName: manage-body.yaml + description: Shows how to manage the document body. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml + group: Document + api_set: + WordApi: '1.2' - id: word-document-insert-section-breaks name: Add a section fileName: insert-section-breaks.yaml @@ -280,12 +407,15 @@ - id: word-document-insert-external-document name: Insert an external document fileName: insert-external-document.yaml - description: Inserts the text of an external document into the current document. + description: >- + Inserts the content (with or without settings) of an external document into + the current document. Settings include formatting, change-tracking mode, + custom properties, and XML parts. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-external-document.yaml group: Document api_set: - WordApi: '1.3' + WordApi: '1.7' - id: word-document-manage-change-tracking name: Track changes fileName: manage-change-tracking.yaml @@ -297,6 +427,17 @@ group: Document api_set: WordApi: '1.4' +- id: word-document-manage-tracked-changes + name: Manage tracked changes + fileName: manage-tracked-changes.yaml + description: >- + This samples shows how to manage tracked changes, including accepting and + rejecting changes. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml + group: Document + api_set: + WordApi: '1.6' - id: word-document-manage-comments name: Manage comments fileName: manage-comments.yaml @@ -318,7 +459,7 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml group: Document api_set: - WordApi: '1.4' + WordApi: '1.5' - id: word-document-manage-fields name: Manage fields fileName: manage-fields.yaml @@ -372,6 +513,15 @@ rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml group: Document + api_set: + WordApiDesktop: '1.1' +- id: word-document-get-external-styles + name: Get styles from external document + fileName: get-external-styles.yaml + description: This sample shows how to get styles from an external document. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/get-external-styles.yaml + group: Document api_set: WordApi: '1.5' - id: word-document-save-close @@ -383,6 +533,26 @@ group: Document api_set: WordApi: '1.5' +- id: word-document-manage-annotations + name: Manage annotations + fileName: manage-annotations.yaml + description: >- + Shows how to leverage the Writing Assistance API to manage annotations and + use annotation events. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml + group: Document + api_set: + WordApi: '1.8' +- id: word-document-compare-documents + name: Compare documents + fileName: compare-documents.yaml + description: Compares two documents (the current one and a specified external one). + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/compare-documents.yaml + group: Document + api_set: + WordApiDesktop: '1.1' - id: word-scenarios-doc-assembly name: Document assembly fileName: doc-assembly.yaml @@ -401,12 +571,41 @@ group: Scenarios api_set: WordApi: '1.3' -- id: word-insert-and-get-pictures - name: Use inline pictures - fileName: insert-and-get-pictures.yaml - description: Inserts and gets inline pictures. +- id: word-scenarios-correlated-objects-pattern + name: Correlated objects pattern + fileName: correlated-objects-pattern.yaml + description: Shows the performance benefits of avoiding `context.sync` calls in a loop. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/correlated-objects-pattern.yaml + group: Scenarios + api_set: + WordApi: '1.4' +- id: word-close-document-window + name: Close document window + fileName: close-document-window.yaml + description: Shows how to close document window. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/close-document-window.yaml + group: Preview APIs + api_set: + WordApi: '1.10' +- id: word-insert-and-change-content-controls + name: Content control basics + fileName: insert-and-change-content-controls.yaml + description: Inserts, updates, and retrieves content controls. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/insert-and-change-content-controls.yaml + group: Preview APIs + api_set: + WordApi: '1.10' +- id: word-manage-comments + name: Manage comments + fileName: manage-comments.yaml + description: >- + This sample shows how to perform operations on comments (including insert, + reply, get, edit, resolve, and delete) and use comment events. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/insert-and-get-pictures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml group: Preview APIs api_set: - WordApi: '1.1' \ No newline at end of file + WordApi: '1.10' \ No newline at end of file diff --git a/playlists/excel.yaml b/playlists/excel.yaml index 1407b7977..5aa863380 100644 --- a/playlists/excel.yaml +++ b/playlists/excel.yaml @@ -30,7 +30,7 @@ - id: excel-chart-axis name: Axis details fileName: chart-axis.yaml - description: 'Gets, sets, and removes axis unit, label, and title in a chart.' + description: Gets, sets, and removes axis unit, label, and title in a chart. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/10-chart/chart-axis.yaml group: Chart @@ -162,19 +162,37 @@ - id: excel-chart-trendlines name: Trendlines fileName: chart-trendlines.yaml - description: 'Adds, gets, and formats trendlines in a chart.' + description: Adds, gets, and formats trendlines in a chart. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/10-chart/chart-trendlines.yaml group: Chart api_set: ExcelApi: '1.7' +- id: excel-chart-data-labels + name: Data labels + fileName: chart-data-labels.yaml + description: Add and style data labels for your charts. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/10-chart/chart-data-labels.yaml + group: Chart + api_set: + ExcelApi: '1.19' +- id: excel-chart-leader-lines + name: Leader lines + fileName: chart-leader-lines.yaml + description: Show and hide leader lines for chart labels. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/10-chart/chart-leader-lines.yaml + group: Chart + api_set: + ExcelApi: '1.19' - id: excel-comment-basics name: Comment basics fileName: comment-basics.yaml - description: 'Adds, edits, and removes comments.' + description: Adds, edits, and removes comments. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comment/comment-basics.yaml - group: Comment + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comments-and-notes/comment-basics.yaml + group: Comments And Notes api_set: ExcelApi: '1.10' - id: excel-comment-mentions @@ -182,17 +200,17 @@ fileName: comment-mentions.yaml description: Mentions someone in a comment. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comment/comment-mentions.yaml - group: Comment + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comments-and-notes/comment-mentions.yaml + group: Comments And Notes api_set: ExcelApi: '1.11' - id: excel-comment-replies name: Comment replies fileName: comment-replies.yaml - description: 'Adds, edits, and removes comment replies.' + description: Adds, edits, and removes comment replies. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comment/comment-replies.yaml - group: Comment + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comments-and-notes/comment-replies.yaml + group: Comments And Notes api_set: ExcelApi: '1.10' - id: excel-comment-resolution @@ -200,10 +218,19 @@ fileName: comment-resolution.yaml description: Resolves and reopens a comment thread. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comment/comment-resolution.yaml - group: Comment + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comments-and-notes/comment-resolution.yaml + group: Comments And Notes api_set: ExcelApi: '1.10' +- id: excel-note-basics + name: Notes + fileName: excel-note-basics.yaml + description: Adds, edits, and removes notes. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comments-and-notes/excel-note-basics.yaml + group: Comments And Notes + api_set: + ExcelApi: '1.18' - id: excel-range-conditional-formatting-basic name: Basic conditional formatting fileName: conditional-formatting-basic.yaml @@ -278,10 +305,21 @@ group: Custom Functions api_set: CustomFunctionsRuntime: 1.4 +- id: excel-custom-functions-custom-enum + name: Function with custom enums + fileName: custom-enum.yaml + description: >- + Use custom enums as parameters in a custom function that searches for + flights. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/16-custom-functions/custom-enum.yaml + group: Custom Functions + api_set: + CustomFunctionsRuntime: 1.5 - id: excel-custom-xml-parts-create-set-get-and-delete-custom-xml-parts name: Using custom XML parts fileName: create-set-get-and-delete-custom-xml-parts.yaml - description: 'Creates, sets, gets, and deletes a custom XML part.' + description: Creates, sets, gets, and deletes a custom XML part. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/18-custom-xml-parts/create-set-get-and-delete-custom-xml-parts.yaml group: Custom XML Parts @@ -296,12 +334,12 @@ group: Custom XML Parts api_set: ExcelApi: '1.5' -- id: excel-data-types-formatted-number +- id: excel-data-types-doubles name: 'Data types: Formatted numbers' fileName: data-types-formatted-number.yaml description: >- - This sample shows how to set and get data types using the formatted number - properties. + This sample shows how to set and get formatted numbers using double data + types. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-formatted-number.yaml group: Data Types @@ -331,9 +369,11 @@ api_set: ExcelApi: '1.16' - id: excel-data-types-error-values - name: 'Data types: Set error values' + name: 'Data types: Set and change error values' fileName: data-types-error-values.yaml - description: This sample shows how to set a cell value to an error data type. + description: >- + This sample shows how to set a cell value to an error data type, and then + update the value of cells that contain an error data type. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-error-values.yaml group: Data Types @@ -372,6 +412,15 @@ group: Data Types api_set: ExcelApi: '1.16' +- id: excel-data-types-basic-types + name: Basic types with metadata + fileName: data-types-basic-types.yaml + description: This sample shows how to work with metadata on basic types. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-basic-types.yaml + group: Data Types + api_set: + ExcelApi: '1.19' - id: excel-data-validation name: Data validation fileName: data-validation.yaml @@ -576,9 +625,9 @@ api_set: ExcelAPI: '1.14' - id: excel-named-item-create-and-remove-named-item - name: 'Create, access, and remove' + name: Create, access, and remove fileName: create-and-remove-named-item.yaml - description: 'Creates, accesses, and removes named items in a worksheet.' + description: Creates, accesses, and removes named items in a worksheet. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/34-named-item/create-and-remove-named-item.yaml group: Named Item @@ -736,16 +785,16 @@ - id: excel-range-hyperlink name: Hyperlinks fileName: range-hyperlink.yaml - description: 'Creates, updates, and clears hyperlinks in a range.' + description: Creates, updates, and clears hyperlinks in a range. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/42-range/range-hyperlink.yaml group: Range api_set: ExcelApi: '1.7' - id: excel-range-insert-delete-and-clear-range - name: 'Insert, delete, and clear' + name: Insert, delete, and clear fileName: insert-delete-clear-range.yaml - description: 'Inserts, deletes, and clears a range.' + description: Inserts, deletes, and clears a range. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/42-range/insert-delete-clear-range.yaml group: Range @@ -894,6 +943,15 @@ group: Range api_set: ExcelAPI: '1.15' +- id: excel-cell-controls + name: Checkboxes + fileName: range-cell-control.yaml + description: This sample shows how to add and remove checkboxes from a table. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/42-range/range-cell-control.yaml + group: Range + api_set: + ExcelApi: '1.18' - id: excel-shape-create-and-delete name: Create and delete geometric shapes fileName: shape-create-and-delete.yaml @@ -950,6 +1008,15 @@ group: Shape api_set: ExcelApi: '1.9' +- id: excel-shape-get-active + name: Get active shape image + fileName: shape-get-active.yaml + description: Get an image of the active shape in your workbook. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/44-shape/shape-get-active.yaml + group: Shape + api_set: + ExcelApi: '1.19' - id: excel-table-add-rows-and-columns-to-a-table name: Add rows and columns fileName: add-rows-and-columns-to-a-table.yaml @@ -1131,6 +1198,15 @@ group: Workbook api_set: ExcelAPI: '1.13' +- id: excel-workbook-built-in-function + name: Use built-in Excel functions + fileName: workbook-built-in-functions.yaml + description: Use the VLOOKUP and SUM built-in Excel functions. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/50-workbook/workbook-built-in-functions.yaml + group: Workbook + api_set: + ExcelAPI: '1.2' - id: excel-worksheet-active-worksheet name: Active worksheet fileName: active-worksheet.yaml @@ -1141,9 +1217,9 @@ api_set: ExcelApi: '1.1' - id: excel-worksheet-add-delete-rename-move-worksheet - name: 'Add, delete, rename, and move worksheet' + name: Add, delete, rename, and move worksheet fileName: add-delete-rename-move-worksheet.yaml - description: 'Adds, deletes, renames, and moves a worksheet.' + description: Adds, deletes, renames, and moves a worksheet. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/54-worksheet/add-delete-rename-move-worksheet.yaml group: Worksheet diff --git a/playlists/outlook.yaml b/playlists/outlook.yaml index 9d85d789b..557b89f9a 100644 --- a/playlists/outlook.yaml +++ b/playlists/outlook.yaml @@ -1,7 +1,7 @@ - id: outlook-roaming-settings-roaming-settings name: Use add-in settings fileName: roaming-settings.yaml - description: 'Gets, sets, and saves add-in roaming settings' + description: Gets, sets, saves, and removes add-in roaming settings. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/10-roaming-settings/roaming-settings.yaml group: Roaming Settings @@ -40,11 +40,11 @@ api_set: Mailbox: '1.1' - id: outlook-item-body-add-inline-base64-image - name: Add inline Base64 image to message or appointment body (Compose) + name: Add inline Base64-encoded image to message or appointment body (Compose) fileName: add-inline-base64-image.yaml description: >- - Add an inline Base64 image to the body of a message or appointment being - composed. + Add an inline Base64-encoded image to the body of a message or appointment + being composed. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/20-item-body/add-inline-base64-image.yaml group: Item Body @@ -97,6 +97,15 @@ group: Item Save And Close api_set: Mailbox: '1.3' +- id: outlook-close-async + name: Close the current message and discard changes (Message Compose) + fileName: close-async.yaml + description: Closes the current message and discards any unsaved changes when specified. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/25-item-save-and-close/close-async.yaml + group: Item Save And Close + api_set: + Mailbox: '1.14' - id: outlook-item-save-and-close-save name: Save the item fileName: save.yaml @@ -247,13 +256,13 @@ name: Work with notification messages fileName: add-getall-remove.yaml description: >- - Adds different kinds of notification messages, gets all, and replaces and - removes an individual notification message. + Adds different kinds of notification messages, gets all notifications, and + replaces and removes an individual notification message. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/35-notifications/add-getall-remove.yaml group: Notifications api_set: - Mailbox: '1.3' + Mailbox: '1.10' - id: outlook-attachments-attachments-compose name: Manipulate attachments (Item Compose) fileName: attachments-compose.yaml @@ -264,7 +273,7 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/40-attachments/attachments-compose.yaml group: Attachments api_set: - Mailbox: '1.1' + Mailbox: '1.8' - id: outlook-attachments-get-attachment-content name: Get attachment content fileName: get-attachment-content.yaml @@ -286,7 +295,7 @@ - id: outlook-categories-work-with-categories name: Work with item categories fileName: work-with-categories.yaml - description: 'Gets, adds, and removes categories assigned to the item.' + description: Gets, adds, and removes categories assigned to the item. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/45-categories/work-with-categories.yaml group: Categories @@ -295,7 +304,7 @@ - id: outlook-categories-work-with-master-categories name: Work with the categories master list fileName: work-with-master-categories.yaml - description: 'Gets, adds, and removes categories in the master list for the mailbox.' + description: Gets, adds, and removes categories in the master list for the mailbox. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/45-categories/work-with-master-categories.yaml group: Categories @@ -376,9 +385,9 @@ api_set: Mailbox: '1.9' - id: outlook-display-items-display-reply-with-attachments - name: 'Create a reply, with attachments' + name: Create a reply with attachments fileName: display-reply-with-attachments.yaml - description: Opens a reply message forms and adds sample attachments. + description: Opens a reply or reply-all message form and adds sample attachments. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/55-display-items/display-reply-with-attachments.yaml group: Display Items @@ -407,16 +416,16 @@ api_set: Mailbox: '1.13' - id: outlook-delegates-and-shared-folders-get-shared-properties - name: Perform an operation as delegate + name: Identify a shared folder or shared mailbox context fileName: get-shared-properties.yaml description: >- - Gets shared properties for an item, checks delegate permissions and performs - an operation as delegate. + Identifies whether the current mail item is in a shared folder or shared + mailbox by getting its properties. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml group: Delegates And Shared Folders api_set: - Mailbox: '1.8' + Mailbox: '1.13' - id: outlook-mime-headers-get-internet-headers-message-read name: Get internet headers fileName: get-internet-headers-message-read.yaml @@ -424,134 +433,120 @@ rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/70-mime-headers/get-internet-headers-message-read.yaml group: Mime Headers - api_set: {} + api_set: + Mailbox: '1.8' - id: outlook-mime-headers-manage-custom-internet-headers-message-compose name: Work with custom internet headers fileName: manage-custom-internet-headers-message-compose.yaml - description: 'Set, get, and remove custom internet headers on a message in Compose mode.' + description: >- + Sets, gets, and removes custom internet headers on a message in Compose + mode. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml group: Mime Headers api_set: Mailbox: '1.8' -- id: outlook-entities-and-regex-matches-basic-entities - name: Entities (Item Read) - fileName: basic-entities.yaml - description: Gets extracted entities. - rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/75-entities-and-regex-matches/basic-entities.yaml - group: Entities And Regex Matches - api_set: - Mailbox: '1.1' -- id: outlook-entities-and-regex-matches-contextual - name: 'Entities and Regex matches (Item Read, contextual)' +- id: outlook-regex-matches-contextual + name: Get regex matches (Item Read, contextual) fileName: contextual.yaml - description: >- - Gets extracted entities and regex matches when the add-in is opened as a - contextual add-in. + description: Gets regex matches when the add-in is opened as a contextual add-in. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/75-entities-and-regex-matches/contextual.yaml - group: Entities And Regex Matches + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/75-regex-matches/contextual.yaml + group: Regex Matches api_set: - Mailbox: '1.1' -- id: outlook-entities-and-regex-matches-selected - name: 'Selected entities and Regex matches (Item Read, contextual)' - fileName: selected.yaml - description: Gets selected entities and regex matches. + Mailbox: '1.6' +- id: outlook-events-drag-drop-item + name: Drag and drop an item into the task pane + fileName: drag-drop-item.yaml + description: >- + Handles the drag-and-drop event when a user drags and drops messages and + file attachments into the add-in task pane. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/75-entities-and-regex-matches/selected.yaml - group: Entities And Regex Matches + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/80-events/drag-drop-item.yaml + group: Events api_set: - Mailbox: '1.6' + Mailbox: '1.5' - id: outlook-tokens-and-service-calls-ids-and-urls - name: Endpoint URLs and item IDs + name: Endpoint URLs and item IDs in Exchange on-premises environments fileName: ids-and-urls.yaml description: >- - Retrieves and displays REST and EWS endpoint URLs and item IDs, and converts - item IDs for different protocols. + Retrieves the Exchange Web Services (EWS) endpoint URL and item IDs and + converts item IDs for different protocols. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/ids-and-urls.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/ids-and-urls.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.5' - id: outlook-tokens-and-service-calls-user-identity-token - name: Get a user identity token + name: Get a user identity token in Exchange on-premises environments fileName: user-identity-token.yaml - description: Gets a user identity token to use in authentication flows. + description: >- + Gets a user identity token for authentication flows in an Exchange + on-premises environment. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/user-identity-token.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/user-identity-token.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.1' - id: outlook-tokens-and-service-calls-user-callback-token - name: Get a callback token + name: Get a callback token in Exchange on-premises environments fileName: user-callback-token.yaml description: >- - Gets a callback token to use for calling outlook services from add-in's - backend service. + Gets a callback token to call Outlook services from an add-in's backend + service in an Exchange on-premises environment. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/user-callback-token.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/user-callback-token.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.1' -- id: outlook-tokens-and-service-calls-basic-rest-cors - name: Get a message using REST - fileName: basic-rest-cors.yaml - description: Gets a message using REST without any back-end code. - rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/basic-rest-cors.yaml - group: Tokens And Service Calls - api_set: - Mailbox: '1.5' - id: outlook-tokens-and-service-calls-make-ews-request-async - name: Get a message using EWS + name: >- + Get a message using Exchange Web Services (EWS) in Exchange on-premises + environments fileName: make-ews-request-async.yaml - description: Gets a message using EWS without any back-end code. + description: >- + Uses EWS in an Exchange on-premises environment to get a message without any + backend code. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/make-ews-request-async.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/make-ews-request-async.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.1' - id: outlook-tokens-and-service-calls-send-message-using-make-ews-request-async - name: Send a message using EWS + name: >- + Send a message using Exchange Web Services (EWS) in Exchange on-premises + environments fileName: send-message-using-make-ews-request-async.yaml - description: Sends a message using EWS without any back-end code. + description: >- + Uses EWS in an Exchange on-premises environment to send a message without + any backend code. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/send-message-using-make-ews-request-async.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/send-message-using-make-ews-request-async.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.1' - id: outlook-tokens-and-service-calls-get-icaluid-as-organizer - name: Get an appointment's iCalUId as an organizer + name: Get an appointment's iCalUId as the organizer (Exchange on-premises only) fileName: get-icaluid-as-organizer.yaml description: >- - Uses EWS to get an appointment's iCalUId value where the user is the - organizer. + Uses Exchange Web Services (EWS) in an Exchange on-premises environment to + get an appointment's iCalUId value where the user is the organizer. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-organizer.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-organizer.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.3' - id: outlook-tokens-and-service-calls-get-icaluid-as-attendee - name: Get an appointment's iCalUId as an attendee + name: Get an appointment's iCalUId as an attendee (Exchange on-premises only) fileName: get-icaluid-as-attendee.yaml description: >- - Uses EWS to get an appointment's iCalUId value where the user is the - attendee. + Uses Exchange Web Services (EWS) in an Exchange on-premises environment to + get an appointment's iCalUId value where the user is an attendee. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-attendee.yaml - group: Tokens And Service Calls + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-attendee.yaml + group: Tokens For Exchange On-Premises api_set: Mailbox: '1.1' -- id: outlook-tokens-and-service-calls-item-id-compose - name: Get an item ID in compose mode - fileName: item-id-compose.yaml - description: 'Gets an item ID in compose mode, to use in certain delegate scenarios.' - rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/item-id-compose.yaml - group: Tokens And Service Calls - api_set: - Mailbox: '1.8' - id: outlook-other-item-apis-get-subject-read name: Get the subject (Read) fileName: get-subject-read.yaml @@ -663,7 +658,7 @@ - id: outlook-other-item-apis-get-add-remove-enhancedlocation-appointment name: Manage the locations of an appointment fileName: get-add-remove-enhancedlocation-appointment.yaml - description: 'Gets, adds, and removes locations on an appointment (enhancedLocation API).' + description: Gets, adds, and removes locations on an appointment (enhancedLocation API). rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml group: Other Item APIs @@ -728,7 +723,7 @@ - id: outlook-other-item-apis-session-data-apis name: Work with session data APIs (Compose) fileName: session-data-apis.yaml - description: 'Sets, gets, gets all, removes, and clears session data in Compose mode.' + description: Sets, gets, gets all, removes, and clears session data in Compose mode. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/session-data-apis.yaml group: Other Item APIs @@ -743,23 +738,95 @@ group: Other Item APIs api_set: Mailbox: '1.13' -- id: outlook-calendar-properties-apis - name: Work with calendar properties APIs (Compose) - fileName: calendar-properties-apis.yaml +- id: outlook-other-item-apis-get-message-properties + name: Get properties of selected messages (Message Compose, Message Read) + fileName: get-message-properties.yaml + description: Gets the properties of multiple selected messages. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-message-properties.yaml + group: Other Item APIs + api_set: + Mailbox: '1.14' +- id: outlook-other-item-apis-get-set-sensitivity-level + name: Get and set the sensitivity level (Appointment Organizer) + fileName: get-set-sensitivity-level.yaml + description: Gets and sets the sensitivity level of an appointment being composed. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-set-sensitivity-level.yaml + group: Other Item APIs + api_set: + Mailbox: '1.14' +- id: outlook-get-eml-format + name: Get the Base64-encoded EML format of a message (Message Read) + fileName: get-eml-format.yaml + description: Gets the Base64-encoded EML format of a message in read mode. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-eml-format.yaml + group: Other Item APIs + api_set: + Mailbox: '1.14' +- id: outlook-get-in-reply-to + name: Get the ID of the message being replied to (Message Compose) + fileName: get-in-reply-to.yaml + description: Retrieves the ID of the message being replied to by the current message. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-in-reply-to.yaml + group: Other Item APIs + api_set: + Mailbox: '1.14' +- id: outlook-get-conversation-index + name: Get the position of a message in a conversation (Message Compose) + fileName: get-conversation-index.yaml description: >- - Gets and sets isAllDayEvent and sensitivity properties of an appointment in - Compose mode. + Retrieves the Base64-encoded position of the current message in a + conversation thread. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/99-preview-apis/calendar-properties-apis.yaml - group: Preview APIs + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-conversation-index.yaml + group: Other Item APIs api_set: - Mailbox: preview -- id: outlook-close-async - name: Close the current message and discard changes (Message Compose) - fileName: close-async.yaml - description: Closes the current message and discards any unsaved changes when specified. + Mailbox: '1.14' +- id: outlook-get-item-class-async + name: Get item class (Message Compose) + fileName: get-item-class-async.yaml + description: Retrieves the item class property of the message being composed. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-item-class-async.yaml + group: Other Item APIs + api_set: + Mailbox: '1.14' +- id: outlook-other-item-apis-item-id-compose + name: Get an item ID in compose mode + fileName: item-id-compose.yaml + description: Gets an item ID in compose mode. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/item-id-compose.yaml + group: Other Item APIs + api_set: + Mailbox: '1.8' +- id: outlook-send-async + name: Send the current message or appointment (Compose) + fileName: send-async.yaml + description: Sends the current message or appointment. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/send-async.yaml + group: Other Item APIs + api_set: + Mailbox: '1.15' +- id: outlook-other-item-apis-get-loaded-message-properties + name: Get properties of a loaded message (Message Compose, Message Read) + fileName: get-loaded-message-properties.yaml + description: Gets the properties of the currently loaded message. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-loaded-message-properties.yaml + group: Other Item APIs + api_set: + Mailbox: '1.15' +- id: outlook-get-set-isalldayevent + name: Get and set the isAllDayEvent property (Appointment Organizer) + fileName: get-set-isalldayevent.yaml + description: Gets and sets the isAllDayEvent property of an appointment being composed. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/99-preview-apis/close-async.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/99-preview-apis/get-set-isalldayevent.yaml group: Preview APIs api_set: Mailbox: preview diff --git a/playlists/powerpoint.yaml b/playlists/powerpoint.yaml index 29e2b87a3..810bc5be0 100644 --- a/playlists/powerpoint.yaml +++ b/playlists/powerpoint.yaml @@ -1,19 +1,21 @@ - id: powerpoint-basics-basic-api-call-ts name: Basic API call (TypeScript) fileName: basic-api-call-ts.yaml - description: Performs a basic PowerPoint API call using TypeScript + description: Performs a basic PowerPoint API call using TypeScript. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/basics/basic-api-call-ts.yaml group: Basics - api_set: PowerPointApi '1.4' + api_set: + PowerPointApi: '1.4' - id: powerpoint-basics-basic-api-call-js name: Basic API call (JavaScript) fileName: basic-api-call-js.yaml - description: Performs a basic PowerPoint API call using JavaScript + description: Performs a basic PowerPoint API call using JavaScript. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/basics/basic-api-call-js.yaml group: Basics - api_set: PowerPointApi '1.4' + api_set: + PowerPointApi: '1.4' - id: powerpoint-basics-basic-common-api-call name: Basic API call (Office 2013) fileName: basic-common-api-call.yaml @@ -24,7 +26,7 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/basics/basic-common-api-call.yaml group: Basics api_set: - Selection: 1.1 + Selection: '1.1' - id: powerpoint-create-presentation name: Create presentation fileName: create-presentation.yaml @@ -35,7 +37,16 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/document/create-presentation.yaml group: Document api_set: - PowerPoint: 1.1 + PowerPointApi: '1.1' +- id: powerpoint-hyperlinks-manage-hyperlinks + name: Get hyperlinks + fileName: manage-hyperlinks.yaml + description: Gets the hyperlinks found in a slide. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/hyperlinks/manage-hyperlinks.yaml + group: Hyperlinks + api_set: + PowerPointApi: '1.6' - id: powerpoint-basics-insert-image name: Insert Image fileName: insert-image.yaml @@ -60,8 +71,17 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/scenarios/searches-wikipedia-api.yaml group: Scenarios api_set: {} +- id: powerpoint-shapes + name: Insert shape, line, and text box + fileName: shapes.yaml + description: Inserts geometric shapes, lines, and text boxes to a slide. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/shapes.yaml + group: Shapes + api_set: + PowerPointApi: '1.4' - id: powerpoint-shapes-get-set-shapes - name: 'Get, set, load, and save shapes' + name: Get, set, load, and save shapes fileName: get-set-shapes.yaml description: Get and set one or more selected shapes. Load and save one or more shapes. rawUrl: >- @@ -69,14 +89,42 @@ group: Shapes api_set: PowerPointApi: '1.5' -- id: powerpoint-shapes - name: 'Insert shape, line, and text box' - fileName: shapes.yaml - description: 'Inserts geometric shapes, lines, and text boxes to a slide.' +- id: powerpoint-shapes-get-shapes-by-type + name: Select shapes by type + fileName: get-shapes-by-type.yaml + description: Gets shapes in a slide based on their type, such as GeometricShape or Line. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/get-shapes-by-type.yaml group: Shapes - api_set: PowerPointApi '1.4' + api_set: + PowerPointApi: '1.4' +- id: powerpoint-shapes-add-modify-tables + name: Add and modify tables + fileName: add-modify-tables.yaml + description: Shows how to add and modify tables in a presentation. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/add-modify-tables.yaml + group: Shapes + api_set: + PowerPointApi: '1.8' +- id: powerpoint-shapes-binding-to-shapes + name: Binding to shapes + fileName: binding-to-shapes.yaml + description: Shows how to create binding references for images and work with z-order. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/binding-to-shapes.yaml + group: Shapes + api_set: + PowerPointApi: '1.8' +- id: powerpoint-shapes-group-ungroup-shapes + name: Group and ungroup shapes + fileName: group-ungroup-shapes.yaml + description: Shows how to create two shapes then group and ungroup them. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/group-ungroup-shapes.yaml + group: Shapes + api_set: + PowerPointApi: '1.8' - id: powerpoint-add-slides name: Add slides to a presentation fileName: add-slides.yaml @@ -94,17 +142,17 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/slide-management/insert-slides.yaml group: Slide Management api_set: - PowerPointApi: '1.2' + PowerPointApi: '1.5' - id: powerpoint-basics-get-slide-metadata name: Get slide metadata fileName: get-slide-metadata.yaml - description: 'Gets the title, index, and ID of the selected slide(s).' + description: Gets the title, index, and ID of the selected slides. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/slide-management/get-slide-metadata.yaml group: Slide Management api_set: {} - id: powerpoint-slide-management-get-set-slides - name: 'Get, set, load, and save slides' + name: Get, set, load, and save slides fileName: get-set-slides.yaml description: Get and set one or more selected slides. Load and save one or more slides. rawUrl: >- @@ -112,6 +160,15 @@ group: Slide Management api_set: PowerPointApi: '1.5' +- id: powerpoint-slide-management-export-import-slide + name: Export and import slide + fileName: export-import-slide.yaml + description: Shows how to export and import a slide. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/slide-management/export-import-slide.yaml + group: Slide Management + api_set: + PowerPointApi: '1.8' - id: powerpoint-tags name: Work with tags fileName: tags.yaml @@ -124,7 +181,7 @@ - id: powerpoint-text-get-set-textrange name: Work with text range selections fileName: get-set-textrange.yaml - description: 'Get, set, load, and save text range selections.' + description: Get, set, load, and save text range selections. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/text/get-set-textrange.yaml group: Text diff --git a/playlists/word.yaml b/playlists/word.yaml index da4f1f61a..1d848fb05 100644 --- a/playlists/word.yaml +++ b/playlists/word.yaml @@ -30,7 +30,7 @@ - id: word-content-controls-insert-and-change-content-controls name: Content control basics fileName: insert-and-change-content-controls.yaml - description: 'Inserts, updates, and retrieves content controls.' + description: Inserts, updates, and retrieves content controls. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/insert-and-change-content-controls.yaml group: Content Controls @@ -102,6 +102,42 @@ group: Content Controls api_set: WordApi: '1.5' +- id: word-content-controls-insert-and-change-checkbox-content-control + name: Manage checkbox content controls + fileName: insert-and-change-checkbox-content-control.yaml + description: Inserts, updates, retrieves, and deletes checkbox content controls. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml + group: Content Controls + api_set: + WordApi: '1.7' +- id: word-content-controls-insert-and-change-combo-box-content-control + name: Manage combo box content controls + fileName: insert-and-change-combo-box-content-control.yaml + description: Inserts, updates, and deletes combo box content controls. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml + group: Content Controls + api_set: + WordApi: '1.9' +- id: word-content-controls-insert-and-change-dropdown-list-content-control + name: Manage dropdown list content controls + fileName: insert-and-change-dropdown-list-content-control.yaml + description: Inserts, updates, and deletes dropdown list content controls. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml + group: Content Controls + api_set: + WordApi: '1.9' +- id: word-content-controls-get-change-tracking-states + name: Get change tracking states of content controls + fileName: get-change-tracking-states.yaml + description: Gets change tracking states of content controls. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/get-change-tracking-states.yaml + group: Content Controls + api_set: + WordApi: '1.5' - id: word-images-insert-and-get-pictures name: Use inline pictures fileName: insert-and-get-pictures.yaml @@ -110,7 +146,7 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/15-images/insert-and-get-pictures.yaml group: Images api_set: - WordApi: '1.1' + WordApiDesktop: '1.1' - id: word-lists-insert-list name: Create a list fileName: insert-list.yaml @@ -120,6 +156,15 @@ group: Lists api_set: WordApi: '1.3' +- id: word-lists-manage-styles + name: Get list styles + fileName: manage-list-styles.yaml + description: This sample shows how to get the list styles in the current document. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/20-lists/manage-list-styles.yaml + group: Lists + api_set: + WordApiDesktop: '1.1' - id: word-lists-organize-list name: Organize a list fileName: organize-list.yaml @@ -177,12 +222,12 @@ - id: word-paragraph-paragraph-properties name: Paragraph properties fileName: paragraph-properties.yaml - description: 'Sets indentation, space between paragraphs, and other paragraph properties.' + description: Sets indentation, space between paragraphs, and other paragraph properties. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/paragraph-properties.yaml group: Paragraph api_set: - WordApi: '1.2' + WordApi: '1.1' - id: word-paragraph-search name: Search fileName: search.yaml @@ -201,6 +246,50 @@ group: Paragraph api_set: WordApi: '1.1' +- id: word-paragraph-get-text + name: Get text + fileName: get-text.yaml + description: >- + Shows how to get paragraph text, including hidden text and text marked for + deletion. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/get-text.yaml + group: Paragraph + api_set: + WordApi: '1.7' +- id: word-paragraph-onadded-event + name: On adding paragraphs + fileName: onadded-event.yaml + description: >- + Registers, triggers, and deregisters the onParagraphAdded event that tracks + the addition of paragraphs. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/onadded-event.yaml + group: Paragraph + api_set: + WordApi: '1.6' +- id: word-paragraph-onchanged-event + name: On changing content in paragraphs + fileName: onchanged-event.yaml + description: >- + Registers, triggers, and deregisters the onParagraphChanged event that + tracks when content is changed in paragraphs. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/onchanged-event.yaml + group: Paragraph + api_set: + WordApi: '1.6' +- id: word-paragraph-ondeleted-event + name: On deleting paragraphs + fileName: ondeleted-event.yaml + description: >- + Registers, triggers, and deregisters the onParagraphDeleted event that + tracks the removal of paragraphs. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/ondeleted-event.yaml + group: Paragraph + api_set: + WordApi: '1.6' - id: word-properties-get-built-in-properties name: Built-in document properties fileName: get-built-in-properties.yaml @@ -248,6 +337,15 @@ group: Ranges api_set: WordApi: '1.3' +- id: word-ranges-get-pages + name: Work with pages, panes, and windows + fileName: get-pages.yaml + description: Shows how to work with pages, panes, and windows. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/35-ranges/get-pages.yaml + group: Ranges + api_set: + WordApiDesktop: '1.2' - id: word-tables-table-cell-access name: Create and access a table fileName: table-cell-access.yaml @@ -268,6 +366,35 @@ group: Tables api_set: WordApi: '1.3' +- id: word-tables-manage-custom-style + name: Manage custom table style + fileName: manage-custom-style.yaml + description: >- + Shows how to manage primarily margins and alignments of a custom table style + in the current document. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/40-tables/manage-custom-style.yaml + group: Tables + api_set: + WordApiDesktop: '1.1' +- id: word-shapes-manage-shapes-text-boxes + name: Work with shapes and text boxes + fileName: manage-shapes-text-boxes.yaml + description: Shows how to work with shapes and text boxes. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/45-shapes/manage-shapes-text-boxes.yaml + group: Shapes + api_set: + WordApiDesktop: '1.2' +- id: word-document-manage-body + name: Manage body + fileName: manage-body.yaml + description: Shows how to manage the document body. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-body.yaml + group: Document + api_set: + WordApi: '1.2' - id: word-document-insert-section-breaks name: Add a section fileName: insert-section-breaks.yaml @@ -280,12 +407,15 @@ - id: word-document-insert-external-document name: Insert an external document fileName: insert-external-document.yaml - description: Inserts the text of an external document into the current document. + description: >- + Inserts the content (with or without settings) of an external document into + the current document. Settings include formatting, change-tracking mode, + custom properties, and XML parts. rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/insert-external-document.yaml group: Document api_set: - WordApi: '1.3' + WordApi: '1.7' - id: word-document-manage-change-tracking name: Track changes fileName: manage-change-tracking.yaml @@ -297,6 +427,17 @@ group: Document api_set: WordApi: '1.4' +- id: word-document-manage-tracked-changes + name: Manage tracked changes + fileName: manage-tracked-changes.yaml + description: >- + This samples shows how to manage tracked changes, including accepting and + rejecting changes. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-tracked-changes.yaml + group: Document + api_set: + WordApi: '1.6' - id: word-document-manage-comments name: Manage comments fileName: manage-comments.yaml @@ -318,7 +459,7 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-footnotes.yaml group: Document api_set: - WordApi: '1.4' + WordApi: '1.5' - id: word-document-manage-fields name: Manage fields fileName: manage-fields.yaml @@ -372,6 +513,15 @@ rawUrl: >- https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-styles.yaml group: Document + api_set: + WordApiDesktop: '1.1' +- id: word-document-get-external-styles + name: Get styles from external document + fileName: get-external-styles.yaml + description: This sample shows how to get styles from an external document. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/get-external-styles.yaml + group: Document api_set: WordApi: '1.5' - id: word-document-save-close @@ -383,6 +533,26 @@ group: Document api_set: WordApi: '1.5' +- id: word-document-manage-annotations + name: Manage annotations + fileName: manage-annotations.yaml + description: >- + Shows how to leverage the Writing Assistance API to manage annotations and + use annotation events. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-annotations.yaml + group: Document + api_set: + WordApi: '1.8' +- id: word-document-compare-documents + name: Compare documents + fileName: compare-documents.yaml + description: Compares two documents (the current one and a specified external one). + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/compare-documents.yaml + group: Document + api_set: + WordApiDesktop: '1.1' - id: word-scenarios-doc-assembly name: Document assembly fileName: doc-assembly.yaml @@ -401,12 +571,41 @@ group: Scenarios api_set: WordApi: '1.3' -- id: word-insert-and-get-pictures - name: Use inline pictures - fileName: insert-and-get-pictures.yaml - description: Inserts and gets inline pictures. +- id: word-scenarios-correlated-objects-pattern + name: Correlated objects pattern + fileName: correlated-objects-pattern.yaml + description: Shows the performance benefits of avoiding `context.sync` calls in a loop. rawUrl: >- - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/99-preview-apis/insert-and-get-pictures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/90-scenarios/correlated-objects-pattern.yaml + group: Scenarios + api_set: + WordApi: '1.4' +- id: word-close-document-window + name: Close document window + fileName: close-document-window.yaml + description: Shows how to close document window. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/99-preview-apis/close-document-window.yaml group: Preview APIs api_set: - WordApi: '1.1' + WordApi: '1.10' +- id: word-insert-and-change-content-controls + name: Content control basics + fileName: insert-and-change-content-controls.yaml + description: Inserts, updates, and retrieves content controls. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/99-preview-apis/insert-and-change-content-controls.yaml + group: Preview APIs + api_set: + WordApi: '1.10' +- id: word-manage-comments + name: Manage comments + fileName: manage-comments.yaml + description: >- + This sample shows how to perform operations on comments (including insert, + reply, get, edit, resolve, and delete) and use comment events. + rawUrl: >- + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/99-preview-apis/manage-comments.yaml + group: Preview APIs + api_set: + WordApi: '1.10' diff --git a/private-samples/excel/20-chart/chart-title-ts.yaml b/private-samples/excel/20-chart/chart-title-ts.yaml index 5c0ab8e2f..40d3be036 100644 --- a/private-samples/excel/20-chart/chart-title-ts.yaml +++ b/private-samples/excel/20-chart/chart-title-ts.yaml @@ -7,10 +7,10 @@ api_set: ExcelApi: 1.1 script: content: | - $("#setup").click(() => tryCatch(setup)); + $("#setup").on("click", () => tryCatch(setup)); - $("#set-title").click(() => tryCatch(setTitle)); - $("#get-title").click(() => tryCatch(getTitle)); + $("#set-title").on("click", () => tryCatch(setTitle)); + $("#get-title").on("click", () => tryCatch(getTitle)); async function setTitle() { await Excel.run(async (ctx) => { @@ -94,18 +94,18 @@ script: language: typescript template: content: |- -
+

This sample shows how to set and get the title of a chart using the Excel JavaScript API.

-
+

Set up

-
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -51,15 +50,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-axis-formatting.yaml b/samples/excel/10-chart/chart-axis-formatting.yaml index 36cadc25a..b6f3b5d56 100644 --- a/samples/excel/10-chart/chart-axis-formatting.yaml +++ b/samples/excel/10-chart/chart-axis-formatting.yaml @@ -6,10 +6,10 @@ host: EXCEL api_set: ExcelApi: '1.8' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#format-horizontal-axis").click(() => tryCatch(formatHorizontalAxis)); - $("#format-vertical-axis").click(() => tryCatch(formatVerticalAxis)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("format-horizontal-axis").addEventListener("click", () => tryCatch(formatHorizontalAxis)); + document.getElementById("format-vertical-axis").addEventListener("click", () => tryCatch(formatVerticalAxis)); async function formatHorizontalAxis() { await Excel.run(async (context) => { @@ -118,33 +118,29 @@ script: language: typescript template: content: |- - -
+

This sample shows how to format the vertical and horizontal axis in a chart.

- -
+

Set up

- -
+

Try it out

- -
+
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -158,13 +154,7 @@ style: language: css libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-axis.yaml b/samples/excel/10-chart/chart-axis.yaml index f37d4ee45..103105274 100644 --- a/samples/excel/10-chart/chart-axis.yaml +++ b/samples/excel/10-chart/chart-axis.yaml @@ -1,18 +1,18 @@ order: 1 id: excel-chart-axis name: Axis details -description: 'Gets, sets, and removes axis unit, label, and title in a chart.' +description: Gets, sets, and removes axis unit, label, and title in a chart. host: EXCEL api_set: ExcelApi: '1.7' script: content: |- - $("#setup").click(() => tryCatch(setup)); - $("#get-axis-unit").click(() => tryCatch(getAxisUnit)); - $("#change-axis-unit").click(() => tryCatch(changeAxisUnit)); - $("#remove-axis-label").click(() => tryCatch(removeAxisLabel)); - $("#show-axis-label").click(() => tryCatch(showAxisLabel)); - $("#set-axis-title").click(() => tryCatch(setAxisTitle)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("get-axis-unit").addEventListener("click", () => tryCatch(getAxisUnit)); + document.getElementById("change-axis-unit").addEventListener("click", () => tryCatch(changeAxisUnit)); + document.getElementById("remove-axis-label").addEventListener("click", () => tryCatch(removeAxisLabel)); + document.getElementById("show-axis-label").addEventListener("click", () => tryCatch(showAxisLabel)); + document.getElementById("set-axis-title").addEventListener("click", () => tryCatch(setAxisTitle)); async function getAxisUnit() { await Excel.run(async (context) => { @@ -170,50 +170,44 @@ script: language: typescript template: content: |- -
+

This sample shows how to get, set, and remove axis unit, label and title in a chart.

- -
+

Set up

- -
+

Try it out

- -
+
- -
+
- -
+
- -
+
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -225,15 +219,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/10-chart/chart-bubble-chart.yaml b/samples/excel/10-chart/chart-bubble-chart.yaml index 108325244..84a38133e 100644 --- a/samples/excel/10-chart/chart-bubble-chart.yaml +++ b/samples/excel/10-chart/chart-bubble-chart.yaml @@ -7,8 +7,11 @@ host: EXCEL api_set: ExcelApi: '1.12' script: - content: | - $("#setup").click(() => tryCatch(setup)); $("#create-bubble-chart").click(() => tryCatch(createBubbleChart)); $("#get-chart-series-dimension-values").click(() => tryCatch(getChartSeriesDimensionValues)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("create-bubble-chart").addEventListener("click", () => tryCatch(createBubbleChart)); + document.getElementById("get-chart-series-dimension-values").addEventListener("click", () => tryCatch(getChartSeriesDimensionValues)); + async function createBubbleChart() { await Excel.run(async (context) => { /* @@ -55,6 +58,7 @@ script: await context.sync(); }); } + async function getChartSeriesDimensionValues() { await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); @@ -115,18 +119,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to create a bubble chart, with each chart series (or bubble) representing a single table row.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -150,15 +152,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-create-several-charts.yaml b/samples/excel/10-chart/chart-create-several-charts.yaml index 53ffff914..078f6b308 100644 --- a/samples/excel/10-chart/chart-create-several-charts.yaml +++ b/samples/excel/10-chart/chart-create-several-charts.yaml @@ -1,23 +1,23 @@ order: 5 id: excel-chart-create-several-charts name: Create charts -description: 'Creates column-clustered, line, XY-scatter, area, radar, pie, 3D, cylinder, and 100% charts.' +description: Creates column-clustered, line, XY-scatter, area, radar, pie, 3D, cylinder, and 100% charts. author: OfficeDev host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#create-column-clustered-chart").click(() => tryCatch(createColumnClusteredChart)); - $("#create-line-chart").click(() => tryCatch(createLineChart)); - $("#create-xy-scatter-chart").click(() => tryCatch(createXYScatterChart)); - $("#create-area-chart").click(() => tryCatch(createAreaStackedChart)); - $("#create-radar-chart").click(() => tryCatch(createRadarFilledChart)); - $("#create-pie-chart").click(() => tryCatch(createPieChart)); - $("#create-3d-chart").click(() => tryCatch(create3DChart)); - $("#create-cylinder-chart").click(() => tryCatch(createCylinderChart)); - $("#create-bar-100-chart").click(() => tryCatch(createBar100Chart)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("create-column-clustered-chart").addEventListener("click", () => tryCatch(createColumnClusteredChart)); + document.getElementById("create-line-chart").addEventListener("click", () => tryCatch(createLineChart)); + document.getElementById("create-xy-scatter-chart").addEventListener("click", () => tryCatch(createXYScatterChart)); + document.getElementById("create-area-chart").addEventListener("click", () => tryCatch(createAreaStackedChart)); + document.getElementById("create-radar-chart").addEventListener("click", () => tryCatch(createRadarFilledChart)); + document.getElementById("create-pie-chart").addEventListener("click", () => tryCatch(createPieChart)); + document.getElementById("create-3d-chart").addEventListener("click", () => tryCatch(create3DChart)); + document.getElementById("create-cylinder-chart").addEventListener("click", () => tryCatch(createCylinderChart)); + document.getElementById("create-bar-100-chart").addEventListener("click", () => tryCatch(createBar100Chart)); async function createColumnClusteredChart() { await Excel.run(async (context) => { @@ -250,66 +250,56 @@ script: language: typescript template: content: |- -
+

This sample shows how to create column-clustered, line, XY-scatter, area, radar, pie, 3D, cylinder, and 100% charts.

- -
+

Set up

- -
+

Try it out

-

-

-

-

-

-

-

-

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -321,15 +311,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/10-chart/chart-data-labels.yaml b/samples/excel/10-chart/chart-data-labels.yaml new file mode 100644 index 000000000..e70e8eac5 --- /dev/null +++ b/samples/excel/10-chart/chart-data-labels.yaml @@ -0,0 +1,278 @@ +order: 16 +id: excel-chart-data-labels +name: Data labels +description: Add and style data labels for your charts. +host: EXCEL +api_set: + ExcelApi: '1.19' +script: + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("add-data-labels").addEventListener("click", () => tryCatch(addDataLabels)); + document.getElementById("style-data-label-substrings").addEventListener("click", () => tryCatch(styleDataLabelSubstrings)); + document.getElementById("change-label-to-round-rectangle").addEventListener("click", () => tryCatch(changeLabelShapesToRoundRectangle)); + document.getElementById("change-label-to-assorted").addEventListener("click", () => tryCatch(changeLabelShapesToAssorted)); + + // Define the worksheet name for the sample. + const sheetName = "Sample"; + + async function addDataLabels() { + // This function adds data labels to specific chart points + // and sets their text and position. + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + await context.sync(); + + const series = chart.series.getItemAt(0); + series.points.load("dataLabel"); + await context.sync(); + + // Define properties for data label positioning and shape. + const labelProperties = [ + { + top: 70, + geometricShapeType: Excel.GeometricShapeType.rectangle + }, + { + top: 200, + geometricShapeType: Excel.GeometricShapeType.rectangle + } + ]; + + // Add data labels to specific chart points and set their text and properties. + for (let i = 0; i < dataLabelInfo.length; i++) { + const point = series.points.getItemAt(dataLabelInfo[i].index); + point.hasDataLabel = true; + + const dataLabel = point.dataLabel; + dataLabel.text = dataLabelInfo[i].news; + dataLabel.set(labelProperties[i]); + } + await context.sync(); + }); + } + + async function styleDataLabelSubstrings() { + // This function styles substrings within data label text using font formatting. + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + await context.sync(); + + const series = chart.series.getItemAt(0); + series.load("points"); + await context.sync(); + + series.points.load("items"); + await context.sync(); + + // Style a substring in the first data label. + let searchString = "sports"; + let dataLabel = series.points.getItemAt(dataLabelInfo[0].index).dataLabel.load("text"); + await context.sync(); + let substringStart = dataLabel.text.indexOf(searchString); + let subLabel = dataLabel.getSubstring(substringStart, searchString.length); + subLabel.font.size = 13; + subLabel.font.bold = true; + + // Style a substring in the second data label. + searchString = "'Titanic'"; + dataLabel = series.points.getItemAt(dataLabelInfo[1].index).dataLabel.load("text"); + await context.sync(); + + substringStart = dataLabel.text.indexOf(searchString); + subLabel = dataLabel.getSubstring(substringStart, searchString.length); + subLabel.font.name = "Calibri"; + subLabel.font.size = 13; + subLabel.font.italic = true; + subLabel.font.color = "blue"; + await context.sync(); + }); + } + + async function changeLabelShapesToRoundRectangle() { + // This function changes the geometric shape of data labels to round rectangles. + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + await context.sync(); + + const series = chart.series.getItemAt(0); + series.load("*"); + await context.sync(); + + series.points.load("*"); + await context.sync(); + + // Set both data labels to round rectangle shape. + let dataLabel = series.points.getItemAt(dataLabelInfo[0].index).dataLabel; + dataLabel.geometricShapeType = Excel.GeometricShapeType.roundRectangle; + + dataLabel = series.points.getItemAt(dataLabelInfo[1].index).dataLabel; + dataLabel.geometricShapeType = Excel.GeometricShapeType.roundRectangle; + await context.sync(); + }); + } + + async function changeLabelShapesToAssorted() { + // This function changes data labels to different geometric shapes with custom formatting. + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + await context.sync(); + + const series = chart.series.getItemAt(0); + + // Set first data label to snip1Rectangle shape. + let dataLabel = series.points.getItemAt(dataLabelInfo[0].index).dataLabel; + dataLabel.geometricShapeType = Excel.GeometricShapeType.snip1Rectangle; + + // Set second data label to snip2DiagonalRectangle shape with light green fill. + dataLabel = series.points.getItemAt(dataLabelInfo[1].index).dataLabel; + dataLabel.geometricShapeType = Excel.GeometricShapeType.snip2DiagonalRectangle; + dataLabel.format.fill.setSolidColor("90EE90"); + await context.sync(); + }); + } + + /** Create sample data and a line chart for the data labels demo. */ + async function setup() { + await Excel.run(async (context) => { + context.workbook.worksheets.getItemOrNullObject(sheetName).delete(); + const sheet = context.workbook.worksheets.add(sheetName); + + // Add sample data to the worksheet. + const dataRange = sheet.getRange("A1:B32"); + dataRange.values = sampleData; + + sheet.activate(); + await context.sync(); + + // Create a line chart with markers. + const chart = sheet.charts.add(Excel.ChartType.lineMarkers, dataRange); + + // Position and format the chart. + chart.setPosition("D4", "Q25"); + chart.legend.visible = false; + chart.title.text = "Product price"; + chart.title.format.font.size = 20; + chart.axes.valueAxis.minimum = 80; + + await context.sync(); + }); + } + + /** Default helper for invoking an action and handling errors. */ + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + + // Save chart data labels as an object for use throughout the sample. + const dataLabelInfo = [ + { + index: 11, + date: "7/12/2023", + news: "The city holds a sports event." + }, + { + index: 20, + date: "7/21/2023", + news: "The movie 'Titanic' returns to the cinema." + } + ]; + + // Sample data for the chart. + const sampleData = [ + ["Date", "Price"], + ["7/1/2023", 100], + ["7/2/2023", 96.71], + ["7/3/2023", 103.24], + ["7/4/2023", 109.09], + ["7/5/2023", 113.68], + ["7/6/2023", 118.68], + ["7/7/2023", 123.2], + ["7/8/2023", 135.05], + ["7/9/2023", 138.68], + ["7/10/2023", 129.63], + ["7/11/2023", 130.85], + ["7/12/2023", 135.71], + ["7/13/2023", 124.83], + ["7/14/2023", 118.94], + ["7/15/2023", 119.63], + ["7/16/2023", 127.2], + ["7/17/2023", 113.98], + ["7/18/2023", 110.32], + ["7/19/2023", 119.3], + ["7/20/2023", 120.36], + ["7/21/2023", 111.88], + ["7/22/2023", 118.88], + ["7/23/2023", 124.37], + ["7/24/2023", 119.53], + ["7/25/2023", 133.42], + ["7/26/2023", 125.67], + ["7/27/2023", 135.82], + ["7/28/2023", 137.87], + ["7/29/2023", 138.9], + ["7/30/2023", 139.36], + ["7/31/2023", 138.75] + ]; + language: typescript +template: + content: |- +
+

This sample shows how to create data labels for charts and adjust the font and appearance of those labels.

+
+
+

Set up

+ +
+
+

Add data labels to the chart

+ +
+
+

Style data labels

+ +
+
+ +
+
+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-data-source.yaml b/samples/excel/10-chart/chart-data-source.yaml index cb0b65ca1..417b3e253 100644 --- a/samples/excel/10-chart/chart-data-source.yaml +++ b/samples/excel/10-chart/chart-data-source.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelApi: '1.15' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#log-chart-series-source").click(() => tryCatch(logChartSeriesSource)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("log-chart-series-source").addEventListener("click", () => tryCatch(logChartSeriesSource)); async function logChartSeriesSource() { // This function retrieves the data source information of a chart series in the Sample worksheet. @@ -81,25 +81,23 @@ script: language: typescript template: content: |- -
+

This sample shows how to get information about the data source of a chart series.

- -
+

Set up

Add a product table and line chart to a sample worksheet.

- -
+

Try it out

Log information to the console about the data source of the chart series Frames.

-
+
language: html style: content: |- @@ -113,15 +111,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-data-table.yaml b/samples/excel/10-chart/chart-data-table.yaml index 9d0c5b04d..8e47b80eb 100644 --- a/samples/excel/10-chart/chart-data-table.yaml +++ b/samples/excel/10-chart/chart-data-table.yaml @@ -6,11 +6,11 @@ host: EXCEL api_set: ExcelApi: '1.14' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#create-column-clustered-chart").click(() => tryCatch(createColumnClusteredChart)); - $("#add-chart-data-table").click(() => tryCatch(addChartDataTable)); - $("#format-chart-data-table").click(() => tryCatch(formatChartDataTable)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("create-column-clustered-chart").addEventListener("click", () => tryCatch(createColumnClusteredChart)); + document.getElementById("add-chart-data-table").addEventListener("click", () => tryCatch(addChartDataTable)); + document.getElementById("format-chart-data-table").addEventListener("click", () => tryCatch(formatChartDataTable)); async function createColumnClusteredChart() { // This function creates a clustered column chart based on data from a table on @@ -114,11 +114,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to add a data table to a chart and then format that data table.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -152,12 +150,8 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - core-js@2.4.1/client/core.min.js - @types/core-js - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-formatting.yaml b/samples/excel/10-chart/chart-formatting.yaml index 319878a32..6a6f00563 100644 --- a/samples/excel/10-chart/chart-formatting.yaml +++ b/samples/excel/10-chart/chart-formatting.yaml @@ -6,12 +6,12 @@ host: EXCEL api_set: ExcelApi: '1.8' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#format-chart").click(() => tryCatch(formatChart)); - $("#show-datalabels").click(() => tryCatch(dataLabels)); - $("#change-color").click(() => tryCatch(changeColor)); - $("#clear").click(() => tryCatch(clearChart)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("format-chart").addEventListener("click", () => tryCatch(formatChart)); + document.getElementById("show-datalabels").addEventListener("click", () => tryCatch(dataLabels)); + document.getElementById("change-color").addEventListener("click", () => tryCatch(changeColor)); + document.getElementById("clear").addEventListener("click", () => tryCatch(clearChart)); async function formatChart() { await Excel.run(async (context) => { @@ -171,18 +171,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to format different aspects of a chart.

- -
+

Set up

- -
+

Try it out

+
+
+

Try it out

+ +
+
+ +
+
+ +
+
+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-legend.yaml b/samples/excel/10-chart/chart-legend.yaml index 9275934e9..b62f39f8a 100644 --- a/samples/excel/10-chart/chart-legend.yaml +++ b/samples/excel/10-chart/chart-legend.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#format-legend-font").click(() => tryCatch(formatLegendFont)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("format-legend-font").addEventListener("click", () => tryCatch(formatLegendFont)); async function formatLegendFont() { await Excel.run(async (context) => { @@ -100,18 +100,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to format the legend font in a chart.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -131,15 +129,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-point.yaml b/samples/excel/10-chart/chart-point.yaml index 582fecda5..5eaef4fd7 100644 --- a/samples/excel/10-chart/chart-point.yaml +++ b/samples/excel/10-chart/chart-point.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: |+ - $("#setup").click(() => tryCatch(setup)); - $("#set-chart-point-color").click(() => tryCatch(setChartPointColor)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("set-chart-point-color").addEventListener("click", () => tryCatch(setChartPointColor)); async function setChartPointColor() { await Excel.run(async (context) => { @@ -79,33 +79,27 @@ script: console.error(error); } } - - - language: typescript template: - content: |+ -
+ content: |- +

This sample shows how to set chart point color.

- -
+

Set up

- -
+

Try it out

- language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -117,15 +111,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-series-markers.yaml b/samples/excel/10-chart/chart-series-markers.yaml index 307aa18c0..5ad48cfad 100644 --- a/samples/excel/10-chart/chart-series-markers.yaml +++ b/samples/excel/10-chart/chart-series-markers.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#set-markers").click(() => tryCatch(setMarkers)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("set-markers").addEventListener("click", () => tryCatch(setMarkers)); async function setMarkers() { await Excel.run(async (context) => { @@ -81,18 +81,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to set chart series marker properties.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -114,13 +112,7 @@ style: language: css libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-series-plotorder.yaml b/samples/excel/10-chart/chart-series-plotorder.yaml index 2d1db67a8..5aac92606 100644 --- a/samples/excel/10-chart/chart-series-plotorder.yaml +++ b/samples/excel/10-chart/chart-series-plotorder.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#order-series-plot").click(() => tryCatch(addSeries)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("order-series-plot").addEventListener("click", () => tryCatch(addSeries)); async function addSeries() { await Excel.run(async (context) => { @@ -91,19 +91,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to change the plot order of series in a chart.

- -
+

Set up

- -
+

Try it out

- -
+

Try it out

- -
+
@@ -140,15 +137,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-title-format.yaml b/samples/excel/10-chart/chart-title-format.yaml index 85d6674c3..31090e70c 100644 --- a/samples/excel/10-chart/chart-title-format.yaml +++ b/samples/excel/10-chart/chart-title-format.yaml @@ -6,12 +6,12 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#change-title-format").click(() => tryCatch(changeTitleFormat)); - $("#change-title-substring").click(() => tryCatch(changeTitleSubstring)); - $("#change-title-orientation").click(() => tryCatch(changeTitleOrientation)); - $("#add-title-shadow").click(() => tryCatch(addTitleShadow)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("change-title-format").addEventListener("click", () => tryCatch(changeTitleFormat)); + document.getElementById("change-title-substring").addEventListener("click", () => tryCatch(changeTitleSubstring)); + document.getElementById("change-title-orientation").addEventListener("click", () => tryCatch(changeTitleOrientation)); + document.getElementById("add-title-shadow").addEventListener("click", () => tryCatch(addTitleShadow)); async function changeTitleFormat() { await Excel.run(async (context) => { @@ -106,19 +106,17 @@ script: } language: typescript template: - content: |+ -
+ content: |- +

This sample shows how to adjust format a chart's title.

- -
+

Set up

- -
+

Try it out

- language: html style: content: |- @@ -148,15 +145,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/10-chart/chart-trendlines.yaml b/samples/excel/10-chart/chart-trendlines.yaml index 4772af54c..c8755bb33 100644 --- a/samples/excel/10-chart/chart-trendlines.yaml +++ b/samples/excel/10-chart/chart-trendlines.yaml @@ -1,17 +1,17 @@ order: 14 id: excel-chart-trendlines name: Trendlines -description: 'Adds, gets, and formats trendlines in a chart.' +description: Adds, gets, and formats trendlines in a chart. host: EXCEL api_set: ExcelApi: '1.7' script: - content: |+ - $("#setup").click(() => tryCatch(setup)); - $("#add-trendline").click(() => tryCatch(addTrendline)); - $("#get-trendline").click(() => tryCatch(getTrendline)); - $("#get-trendline-color").click(() => tryCatch(getTrendlineColor)); - $("#set-trendline-color").click(() => tryCatch(setTrendlineColor)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("add-trendline").addEventListener("click", () => tryCatch(addTrendline)); + document.getElementById("get-trendline").addEventListener("click", () => tryCatch(getTrendline)); + document.getElementById("get-trendline-color").addEventListener("click", () => tryCatch(getTrendlineColor)); + document.getElementById("set-trendline-color").addEventListener("click", () => tryCatch(setTrendlineColor)); async function addTrendline() { await Excel.run(async (context) => { @@ -134,42 +134,35 @@ script: console.error(error); } } - - - language: typescript template: content: |- -
+

This sample shows how to add, get, and format trendlines in a chart.

- -
+

Set up

- -
+

Try it out

- -
+
- -
+
-
+
@@ -188,15 +181,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/10-chart/create-doughnut-chart.yaml b/samples/excel/10-chart/create-doughnut-chart.yaml index c618f49fb..2728bf4fe 100644 --- a/samples/excel/10-chart/create-doughnut-chart.yaml +++ b/samples/excel/10-chart/create-doughnut-chart.yaml @@ -7,10 +7,10 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#create-doughnut-chart").click(() => tryCatch(createChart)); - $("#add-series").click(() => tryCatch(addSeries)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("create-doughnut-chart").addEventListener("click", () => tryCatch(createChart)); + document.getElementById("add-series").addEventListener("click", () => tryCatch(addSeries)); async function createChart() { Excel.run(async (context) => { @@ -103,18 +103,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to create a doughnut chart.

- -
+

Set up

- -
+

Try it out

-
+

Try it out

To better view the comment changes, open the Comments pane by selecting Show Comments from the Review tab.

-
+

Try it out

To better view the comment changes, open the Comments pane by selecting Show Comments from the Review tab.

@@ -88,15 +88,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/12-comment/comment-replies.yaml b/samples/excel/12-comments-and-notes/comment-replies.yaml similarity index 82% rename from samples/excel/12-comment/comment-replies.yaml rename to samples/excel/12-comments-and-notes/comment-replies.yaml index acade0f0a..e3f10b0b7 100644 --- a/samples/excel/12-comment/comment-replies.yaml +++ b/samples/excel/12-comments-and-notes/comment-replies.yaml @@ -1,18 +1,18 @@ order: 3 id: excel-comment-replies name: Comment replies -description: 'Adds, edits, and removes comment replies.' +description: Adds, edits, and removes comment replies. host: EXCEL api_set: ExcelApi: '1.10' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#add-first-comment-reply").click(() => tryCatch(addFirstCommentReply)); - $("#add-second-comment-reply").click(() => tryCatch(addSecondCommentReply)); - $("#get-comment-reply-metadata").click(() => tryCatch(getCommentReplyMetadata)); - $("#edit-comment-reply").click(() => tryCatch(editCommentReply)); - $("#delete-comment-reply").click(() => tryCatch(deleteCommentReply)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("add-first-comment-reply").addEventListener("click", () => tryCatch(addFirstCommentReply)); + document.getElementById("add-second-comment-reply").addEventListener("click", () => tryCatch(addSecondCommentReply)); + document.getElementById("get-comment-reply-metadata").addEventListener("click", () => tryCatch(getCommentReplyMetadata)); + document.getElementById("edit-comment-reply").addEventListener("click", () => tryCatch(editCommentReply)); + document.getElementById("delete-comment-reply").addEventListener("click", () => tryCatch(deleteCommentReply)); async function addFirstCommentReply() { await Excel.run(async (context) => { @@ -103,16 +103,16 @@ script: language: typescript template: content: |- -

+

This sample shows how to add, edit, and remove comment replies.

-
+

Setup

-
+

Try it out

To better view the comment changes, open the Comments pane by selecting Show Comments from the Review tab.

-
+

Try it out

To better view the comment changes, open the Comments pane by selecting Show Comments from the Review tab.

@@ -99,15 +99,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/12-comments-and-notes/excel-note-basics.yaml b/samples/excel/12-comments-and-notes/excel-note-basics.yaml new file mode 100644 index 000000000..fc74c8521 --- /dev/null +++ b/samples/excel/12-comments-and-notes/excel-note-basics.yaml @@ -0,0 +1,162 @@ +order: 5 +id: excel-note-basics +name: Notes +description: Adds, edits, and removes notes. +host: EXCEL +api_set: + ExcelApi: '1.18' +script: + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("add-note-to-selected-cell").addEventListener("click", () => tryCatch(addNoteToSelectedCell)); + document.getElementById("add-note-to-cell").addEventListener("click", () => tryCatch(addNoteToCell)); + document.getElementById("change-note-visibility").addEventListener("click", () => tryCatch(changeNoteVisibility)); + document.getElementById("edit-note-content").addEventListener("click", () => tryCatch(editNoteContent)); + document.getElementById("edit-note-size").addEventListener("click", () => tryCatch(editNoteSize)); + document.getElementById("delete-note").addEventListener("click", () => tryCatch(deleteNote)); + + async function addNoteToSelectedCell() { + // This function adds a note to the selected cell. + await Excel.run(async (context) => { + 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(); + }); + } + + async function addNoteToCell() { + // This function adds a note to cell A2. + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + + // Note that an InvalidArgument error is thrown if multiple cells are passed to `notes.add`. + sheet.notes.add("A2", "The second note."); + await context.sync(); + }); + } + + async function changeNoteVisibility() { + // This function sets the note on cell A1 to visible. + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const firstNote = sheet.notes.getItem("A1"); + + firstNote.load(); + await context.sync(); + + firstNote.visible = true; + }); + } + + async function editNoteContent() { + // This function changes the content in the first note. + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const note = sheet.notes.getItemAt(0); + note.content = "Changing the content of the first note."; + await context.sync(); + }); + } + + async function editNoteSize() { + // This function changes the height and width of the first note. + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const note = sheet.notes.getItemAt(0); + note.height = 200; + note.width = 400; + await context.sync(); + }); + } + + async function deleteNote() { + // This function deletes the note from cell A2. + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const note = sheet.notes.getItem("A2"); + note.delete(); + + await context.sync(); + }); + } + + /** Set up Sample worksheet. */ + async function setup() { + await Excel.run(async (context) => { + context.workbook.worksheets.getItemOrNullObject("Notes").delete(); + const sheet = context.workbook.worksheets.add("Notes"); + + sheet.activate(); + await context.sync(); + }); + } + + /** Default helper for invoking an action and handling errors. */ + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +

+

This sample shows how to work with notes: Add notes, edit content, size, and visibility, and remove notes.

+
+
+

Setup

+ +
+
+

Try it out

+ +

+ +

+ +

+ +

+ +

+ +

+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/14-conditional-formatting/conditional-formatting-advanced.yaml b/samples/excel/14-conditional-formatting/conditional-formatting-advanced.yaml index 07bcbf4c2..bae922ff7 100644 --- a/samples/excel/14-conditional-formatting/conditional-formatting-advanced.yaml +++ b/samples/excel/14-conditional-formatting/conditional-formatting-advanced.yaml @@ -6,12 +6,12 @@ host: EXCEL api_set: ExcelApi: '1.6' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#apply-conditional-formats-default-priority").click(() => tryCatch(applyConditionalFormatsWithDefaultPriority)); - $("#apply-conditional-formats-explicit-priority").click(() => tryCatch(applyPrioritizedConditionalFormats)); - $("#apply-conditional-formats-stop-if-true").click(() => tryCatch(applyPrioritizedConditionalFormatsWithStopOnTrue)); - $("#remove-conditional-format").click(() => tryCatch(removeConditionalFormat)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("apply-conditional-formats-default-priority").addEventListener("click", () => tryCatch(applyConditionalFormatsWithDefaultPriority)); + document.getElementById("apply-conditional-formats-explicit-priority").addEventListener("click", () => tryCatch(applyPrioritizedConditionalFormats)); + document.getElementById("apply-conditional-formats-stop-if-true").addEventListener("click", () => tryCatch(applyPrioritizedConditionalFormatsWithStopOnTrue)); + document.getElementById("remove-conditional-format").addEventListener("click", () => tryCatch(removeConditionalFormat)); async function applyConditionalFormatsWithDefaultPriority() { @@ -178,20 +178,18 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to use priorities to work with conditional formatting of ranges when more than one conditional format applies to some cells.

- -
+

Set up

- -
+

Try it out

- -
+

Try it out

- -
+

XML part display

- language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -145,15 +142,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/18-custom-xml-parts/test-xml-for-unique-namespace.yaml b/samples/excel/18-custom-xml-parts/test-xml-for-unique-namespace.yaml index c42b996bd..9df023ebf 100644 --- a/samples/excel/18-custom-xml-parts/test-xml-for-unique-namespace.yaml +++ b/samples/excel/18-custom-xml-parts/test-xml-for-unique-namespace.yaml @@ -7,14 +7,14 @@ host: EXCEL api_set: ExcelApi: '1.5' script: - content: | - $("#create-custom-xml-part").click(() => tryCatch(createCustomXmlPart)); - $("#test-for-unique-namespace").click(() => tryCatch(testForUniqueNamespace)); - $("#delete-all-custom-xml-parts").click(() => tryCatch(deleteAllCustomXmlParts)); + content: |- + document.getElementById("create-custom-xml-part").addEventListener("click", () => tryCatch(createCustomXmlPart)); + document.getElementById("test-for-unique-namespace").addEventListener("click", () => tryCatch(testForUniqueNamespace)); + document.getElementById("delete-all-custom-xml-parts").addEventListener("click", () => tryCatch(deleteAllCustomXmlParts)); async function createCustomXmlPart() { await Excel.run(async (context) => { - $("#display-xml").text(""); + document.getElementById("display-xml").textContent = ""; // You must have the xmlns attribute to populate the // CustomXml.namespaceUri property. @@ -26,7 +26,7 @@ script: // Make it a bit more readable. const readableXml = xmlBlob.value.replace(/>\n<"); - $("#display-xml").text(readableXml); + document.getElementById("display-xml").textContent = readableXml; await context.sync(); }); @@ -34,7 +34,7 @@ script: async function testForUniqueNamespace() { await Excel.run(async (context) => { - $("#display-xml").text(""); + document.getElementById("display-xml").textContent = ""; const contosoNamespace = "http://schemas.contoso.com/review/1.0"; const customXmlParts = context.workbook.customXmlParts; const filteredXmlParts = customXmlParts.getByNamespace(contosoNamespace); @@ -51,8 +51,8 @@ script: // Make it a bit more readable. const readableXml = xmlBlob.value.replace(/>\n<"); - $("#display-xml").text(`The only XML part in the namespace ${contosoNamespace} is: - ${readableXml}`); + document.getElementById("display-xml").textContent = `The only XML part in the namespace ${contosoNamespace} is: + ${readableXml}`; } else { console.log(`There are ${numberOfPartsInNamespace.value} XML parts with namespace ${contosoNamespace}. There should be exactly 1.`); @@ -64,7 +64,7 @@ script: async function deleteAllCustomXmlParts() { await Excel.run(async (context) => { - $("#display-xml").text(""); + document.getElementById("display-xml").textContent = ""; const customXmlParts = context.workbook.customXmlParts; customXmlParts.load("items"); @@ -90,12 +90,11 @@ script: } language: typescript template: - content: |+ -
+ content: |- +

This sample shows how to determine if there is just one XML part for a specified namespace.

- -
+

Try it out

Press the "Create XML part" button to create and display Contoso's Reviewer metadata. Press it more than once if you want to set up an error situation.

- -
+

XML part display

- language: html style: content: |- @@ -131,15 +128,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/20-data-types/data-types-basic-types.yaml b/samples/excel/20-data-types/data-types-basic-types.yaml new file mode 100644 index 000000000..b72203a60 --- /dev/null +++ b/samples/excel/20-data-types/data-types-basic-types.yaml @@ -0,0 +1,362 @@ +order: 8 +id: excel-data-types-basic-types +name: Basic types with metadata +description: This sample shows how to work with metadata on basic types. +host: EXCEL +api_set: + ExcelApi: '1.19' +script: + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("set-basic-types-with-metadata").addEventListener("click", () => tryCatch(setBasicTypesWithMetadata)); + document.getElementById("set-referenced-values").addEventListener("click", () => tryCatch(setReferencedValues)); + document.getElementById("set-circular-reference-values").addEventListener("click", () => tryCatch(setCircularReferenceValues)); + document.getElementById("print-to-console").addEventListener("click", () => tryCatch(printToConsole)); + + const sheetName = "Sample"; + + /** Add basic types with metadata to the worksheet. */ + async function setBasicTypesWithMetadata() { + await Excel.run(async (context) => { + // Get the worksheet and target range. + const sheet = context.workbook.worksheets.getItem(sheetName); + const dataRange = sheet.getRange("A1:A4"); + + // Write a variety of basic types with metadata to the range. + dataRange.valuesAsJson = [ + [doubleWithFormatAndMetadata], + [doubleWithMetadata], + [stringWithMetadata], + [booleanWithMetadata] + ]; + + dataRange.format.autofitColumns(); + await context.sync(); + }); + } + + /** Set basic types with metadata that reference other basic types in the worksheet. */ + async function setReferencedValues() { + await Excel.run(async (context) => { + // Get the worksheet and target range. + const sheet = context.workbook.worksheets.getItem(sheetName); + const targetRange = sheet.getRange("A5"); + + // Write a string with metadata that references other values. + targetRange.valuesAsJson = [ + [stringWithReferencedValues] + ]; + targetRange.format.autofitColumns(); + + await context.sync(); + }); + } + + /** Set basic types with metadata that contain circular references. */ + async function setCircularReferenceValues() { + await Excel.run(async (context) => { + // Get the worksheet and target range. + const sheet = context.workbook.worksheets.getItem(sheetName); + const targetRange = sheet.getRange("A6"); + + // Write a string with metadata that contains circular references. + targetRange.valuesAsJson = [ + [stringWithCircularReferences] + ]; + targetRange.format.autofitColumns(); + + await context.sync(); + }); + } + + /** Get and log information about the basic types in the worksheet. */ + async function printToConsole() { + await Excel.run(async (context) => { + // Get the worksheet and target range. + const sheet = context.workbook.worksheets.getItem(sheetName); + const dataRange = sheet.getRange("A1:A6"); + + // Load the data type property of the range. + dataRange.load("valuesAsJson"); + await context.sync(); + + const dataValues = dataRange.valuesAsJson; + + // Print information about the data types to the console. + console.log("Basic types as an array:", dataValues); + }); + } + + /** Set up Sample worksheet. */ + async function setup() { + await Excel.run(async (context) => { + // Create a new worksheet and activate it. + context.workbook.worksheets.getItemOrNullObject(sheetName).delete(); + const sheet = context.workbook.worksheets.add(sheetName); + sheet.activate(); + + await context.sync(); + }); + } + + /** Default helper for invoking an action and handling errors. */ + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + + /** Basic string value with metadata. */ + const basicStringValue: Excel.StringCellValue = { + type: Excel.CellValueType.string, + basicType: Excel.CellValueType.string, + basicValue: "This is a basic string value" + }; + + /** Basic double value with metadata. */ + const basicDoubleValue: Excel.DoubleCellValue = { + type: Excel.CellValueType.double, + basicType: Excel.CellValueType.double, + basicValue: 10 + }; + + /** Basic boolean value with metadata. */ + const basicBooleanValue: Excel.BooleanCellValue = { + type: Excel.CellValueType.boolean, + basicType: Excel.CellValueType.boolean, + basicValue: true + }; + + /** Web image cell value. */ + const imageCellValue: Excel.WebImageCellValue = { + type: "WebImage", + basicType: "Error", + basicValue: "#VALUE!", + address: "https://github.com/OfficeDev/office-js-snippets/blob/main/.github/images/microsoft-logo.png?raw=true", + }; + + /** Basic view layout with icon for card and compact views. */ + const basicViewLayoutWithIcon: Excel.BasicViewLayouts = { + card: { + title: "This is the title", + sections: [ + { + layout: "List", + properties: ["stringProperty", "booleanProperty", "doubleProperty"], + collapsed: false, + collapsible: true + } + ], + subTitle: { + property: "stringProperty" + }, + mainImage: { + property: "imageProperty" + } + }, + compact: { + icon: Excel.EntityCompactLayoutIcons.animalDog + } + }; + + /** Simple view layout without icon. */ + const basicViewLayoutSimple: Excel.BasicViewLayouts = { + card: { + title: "This is the title", + subTitle: { + property: "stringProperty" + } + } + }; + + /** Cell value provider attributes for data source attribution. */ + const cellValueProvider: Excel.CellValueProviderAttributes = { + description: "Microsoft Bing", + logoSourceAddress: "https://github.com/OfficeDev/office-js-snippets/blob/main/.github/images/microsoft-logo.png?raw=true", + logoTargetAddress: "http://microsoft.com" + }; + + /** Double value with formatting and metadata. */ + const doubleWithFormatAndMetadata: Excel.DoubleCellValue = { + type: Excel.CellValueType.double, + basicType: Excel.CellValueType.double, + basicValue: 300, + numberFormat: "$0.00", + properties: { + stringProperty: basicStringValue, + booleanProperty: basicBooleanValue, + doubleProperty: basicDoubleValue, + imageProperty: imageCellValue + }, + layouts: basicViewLayoutWithIcon, + provider: cellValueProvider + }; + + /** Double value with metadata but no special formatting. */ + const doubleWithMetadata: Excel.DoubleCellValue = { + type: Excel.CellValueType.double, + basicType: Excel.CellValueType.double, + basicValue: 123.45, + properties: { + stringProperty: basicStringValue, + booleanProperty: basicBooleanValue, + doubleProperty: basicDoubleValue, + imageProperty: imageCellValue + }, + layouts: basicViewLayoutSimple, + provider: cellValueProvider + }; + + /** String value with metadata. */ + const stringWithMetadata: Excel.StringCellValue = { + type: Excel.CellValueType.string, + basicType: Excel.CellValueType.string, + basicValue: "String with metadata", + properties: { + stringProperty: basicStringValue, + booleanProperty: basicBooleanValue, + doubleProperty: basicDoubleValue, + imageProperty: imageCellValue + }, + layouts: basicViewLayoutWithIcon, + provider: cellValueProvider + }; + + /** Boolean value with metadata. */ + const booleanWithMetadata: Excel.BooleanCellValue = { + type: Excel.CellValueType.boolean, + basicType: Excel.CellValueType.boolean, + basicValue: true, + properties: { + stringProperty: basicStringValue, + booleanProperty: basicBooleanValue, + doubleProperty: basicDoubleValue, + imageProperty: imageCellValue + }, + layouts: basicViewLayoutSimple, + provider: cellValueProvider + }; + + /** String with metadata that references other values. */ + const stringWithReferencedValues = { + type: Excel.CellValueType.string, + basicType: Excel.CellValueType.string, + basicValue: "String with referenced values", + properties: { + stringProperty: { + type: Excel.CellValueType.reference, + reference: 0 + }, + booleanProperty: { + type: Excel.CellValueType.reference, + reference: 1 + }, + doubleWithFormatProperty: { + type: Excel.CellValueType.reference, + reference: 2 + }, + doubleProperty: { + type: Excel.CellValueType.reference, + reference: 3 + } + }, + referencedValues: [stringWithMetadata, booleanWithMetadata, doubleWithFormatAndMetadata, doubleWithMetadata], + layouts: { + compact: { + icon: Excel.EntityCompactLayoutIcons.apple + } + } + }; + + /** String with metadata that contains circular references. */ + const stringWithCircularReferences = { + type: Excel.CellValueType.string, + basicType: Excel.CellValueType.string, + basicValue: "String with circular references", + properties: { + doubleProperty: { + type: Excel.CellValueType.double, + basicType: Excel.CellValueType.double, + basicValue: 10, + properties: { + stringProperty: basicStringValue, + doubleProperty: basicDoubleValue, + booleanProperty: basicBooleanValue, + rootProperty: { + type: Excel.CellValueType.reference, + reference: 0 + } + }, + referencedValues: [ + { + type: Excel.ReferenceValueType.root + } + ] + } + }, + layouts: { + compact: { + icon: Excel.EntityCompactLayoutIcons.animalTurtle + } + } + }; + language: typescript +template: + content: |- +
+

This sample shows how to create basic types with metadata and then work with those basic types.

+
+
+

Set up

+ +
+
+

Try it out

+

Add basic types to the worksheet. Select the icon in each cell to see a data type card with metadata.

+ +
+
+

Add a basic type with referenced values. Open the data type card to see other values in the worksheet that this basic type references—it references cells A1, A2, A3, and A4.

+ +
+
+

Add a basic type with circular references. Open the data type card and select the doubleProperty to see the circular references.

+ +
+
+

Print information about each of your basic types to the console.

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/20-data-types/data-types-entity-attribution.yaml b/samples/excel/20-data-types/data-types-entity-attribution.yaml index 953eaee8f..984bb7ab7 100644 --- a/samples/excel/20-data-types/data-types-entity-attribution.yaml +++ b/samples/excel/20-data-types/data-types-entity-attribution.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelApi: '1.16' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#add-entities-to-table").click(() => tryCatch(addEntitiesToTable)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("add-entities-to-table").addEventListener("click", () => tryCatch(addEntitiesToTable)); async function addEntitiesToTable() { // This function retrieves data for each of the existing products in the table, @@ -50,7 +50,7 @@ script: const entity: Excel.EntityCellValue = { type: Excel.CellValueType.entity, text: productName, - properties: { + properties: { /* Excel.EntityPropertyType */ "Product ID": { type: Excel.CellValueType.string, basicValue: productID.toString() || "" @@ -70,10 +70,10 @@ script: numberFormat: "$* #,##0.00" } }, - layouts: { - card: { + layouts: { /* Excel.EntityViewLayouts */ + card: { /* Excel.EntityCardLayout */ title: { property: "Product Name" }, - sections: [ + sections: [ /* Excel.CardLayoutSection */ { layout: "List", properties: ["Product ID"] @@ -189,26 +189,26 @@ script: language: typescript template: content: |- -
+

This sample shows how to set data provider attributions on entity values in the card layout. The data is aggregated from three different data providers, and three attributions are displayed.

-
+

Set up

-
+

Try it out

To see the entity value's data attribution, click the icon to the left of the title in the Product column after selecting Add entity values.

The data attribution appears as a logo in the bottom left corner of the entity card. Hover over the logo to see the name of the data provider. Click on the logo to visit the data provider's URL.

-
+
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -220,15 +220,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/20-data-types/data-types-entity-icons.yaml b/samples/excel/20-data-types/data-types-entity-icons.yaml index 335f1e75d..704894f33 100644 --- a/samples/excel/20-data-types/data-types-entity-icons.yaml +++ b/samples/excel/20-data-types/data-types-entity-icons.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelApi: '1.16' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#create-icons").click(() => tryCatch(createIcons)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("create-icons").addEventListener("click", () => tryCatch(createIcons)); // Retrieve the entity card icons enum. const iconNames = Excel.EntityCompactLayoutIcons; @@ -76,17 +76,17 @@ script: language: typescript template: content: |- -
+

This sample shows how to display all the icons available for entity data types, along with the name of each icon.

After creating the icons, select an icon to open the entity card for that data type. The entity cards in this sample display only the icon names.

-
+

Set up

-
+

Run sample

-
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -600,15 +593,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/20-data-types/data-types-error-values.yaml b/samples/excel/20-data-types/data-types-error-values.yaml index 898a52073..c5dfce56c 100644 --- a/samples/excel/20-data-types/data-types-error-values.yaml +++ b/samples/excel/20-data-types/data-types-error-values.yaml @@ -1,14 +1,15 @@ order: 4 id: excel-data-types-error-values -name: 'Data types: Set error values' -description: This sample shows how to set a cell value to an error data type. +name: 'Data types: Set and change error values' +description: This sample shows how to set a cell value to an error data type, and then update the value of cells that contain an error data type. host: EXCEL api_set: ExcelApi: '1.16' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#setBusyError").click(() => tryCatch(setBusyError)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("set-busy-error").addEventListener("click", () => tryCatch(setBusyError)); + document.getElementById("change-busy-error").addEventListener("click", () => tryCatch(changeBusyError)); async function setBusyError() { // This function sets the value of cell A1 to a #BUSY! error using data types. @@ -17,7 +18,7 @@ script: const sheet = context.workbook.worksheets.getItemOrNullObject("Sample"); const range = sheet.getRange("A1"); - // Get the error data type and set its type to `busy`. + // Get the error data type and set its type to `busy`. const error: Excel.ErrorCellValue = { type: Excel.CellValueType.error, errorType: Excel.ErrorCellValueType.busy @@ -29,13 +30,35 @@ script: }); } + async function changeBusyError() { + // This function checks if the used range contains a #BUSY! error, and then updates all the cells in the range that contain the error. + await Excel.run(async (context) => { + // Retrieve the Sample worksheet and the used range on that sheet. + const sheet = context.workbook.worksheets.getItemOrNullObject("Sample"); + const usedRange = sheet.getUsedRange(); + + // Load the `valuesAsJson` property for comparison. + usedRange.load("valuesAsJson"); + await context.sync(); + + // Check if the used range contains a #BUSY! error. + if (usedRange.valuesAsJson[0][0]["errorType"] == Excel.ErrorCellValueType.busy) { + // If the used range contains a #BUSY! error, load and change those values. + usedRange.load("values"); + await context.sync(); + usedRange.values = [["Process unavailable."]]; + } + + await context.sync(); + }); + } + async function setup() { await Excel.run(async (context) => { // Create a new worksheet called "Sample" and activate it. context.workbook.worksheets.getItemOrNullObject("Sample").delete(); const sheet = context.workbook.worksheets.add("Sample"); sheet.activate(); - await context.sync(); }); } @@ -52,17 +75,20 @@ script: language: typescript template: content: |- -
-

This sample shows how to set the value of cell A1 to the #BUSY! error data type.

+
+

This sample shows how to set the value of cell A1 to the #BUSY! error data type. The sample then checks to see if the worksheet contains a #BUSY! error, and then updates all cells that contain a #BUSY! error.

-
+

Set up

Try it out

- +
language: html @@ -79,15 +105,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/20-data-types/data-types-formatted-number.yaml b/samples/excel/20-data-types/data-types-formatted-number.yaml index e534b3226..9c5e243aa 100644 --- a/samples/excel/20-data-types/data-types-formatted-number.yaml +++ b/samples/excel/20-data-types/data-types-formatted-number.yaml @@ -1,19 +1,19 @@ order: 1 -id: excel-data-types-formatted-number +id: excel-data-types-doubles name: 'Data types: Formatted numbers' -description: This sample shows how to set and get data types using the formatted number properties. +description: This sample shows how to set and get formatted numbers using double data types. host: EXCEL api_set: ExcelApi: '1.16' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#set-formatted-number-date").click(() => tryCatch(setFormattedNumberDate)); - $("#set-formatted-number-currency").click(() => tryCatch(setFormattedNumberCurrency)); - $("#get-formatted-number").click(() => tryCatch(getFormattedNumber)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("set-double-as-date").addEventListener("click", () => tryCatch(setDoubleAsDate)); + document.getElementById("set-double-as-currency").addEventListener("click", () => tryCatch(setDoubleAsCurrency)); + document.getElementById("get-double").addEventListener("click", () => tryCatch(getDouble)); - async function setFormattedNumberDate() { - // This function creates a formatted number data type, + async function setDoubleAsDate() { + // This function creates a double data type, // and sets the format of this data type as a date. await Excel.run(async (context) => { // Get the Sample worksheet and a range on that sheet. @@ -24,7 +24,7 @@ script: dateRange.valuesAsJson = [ [ { - type: Excel.CellValueType.formattedNumber, + type: Excel.CellValueType.double, basicValue: 32889.0, numberFormat: "m/d/yyyy" } @@ -34,8 +34,8 @@ script: }); } - async function setFormattedNumberCurrency() { - // This function creates a formatted number data type, + async function setDoubleAsCurrency() { + // This function creates a double data type, // and sets the format of this data type as a currency. await Excel.run(async (context) => { // Get the Sample worksheet and a range on that sheet. @@ -46,7 +46,7 @@ script: currencyRange.valuesAsJson = [ [ { - type: Excel.CellValueType.formattedNumber, + type: Excel.CellValueType.double, basicValue: 12.34, numberFormat: "$* #,##0.00" } @@ -57,7 +57,7 @@ script: }); } - async function getFormattedNumber() { + async function getDouble() { // This function prints information about data types // in cells A1 and A2 to the console. await Excel.run(async (context) => { @@ -79,13 +79,13 @@ script: console.log(" Type: " + dateValues.type); console.log(" Basic value: " + dateValues.basicValue); console.log(" Basic type: " + dateValues.basicType); - console.log(" Number format: " + (dateValues as Excel.FormattedNumberCellValue).numberFormat); + console.log(" Number format: " + (dateValues as Excel.DoubleCellValue).numberFormat); console.log("Currency"); console.log(" Type: " + currencyValues.type); console.log(" Basic value: " + currencyValues.basicValue); console.log(" Basic type: " + currencyValues.basicType); - console.log(" Number format: " + (currencyValues as Excel.FormattedNumberCellValue).numberFormat); + console.log(" Number format: " + (currencyValues as Excel.DoubleCellValue).numberFormat); }); } @@ -110,22 +110,22 @@ script: language: typescript template: content: |- -
-

This sample shows how to work with the formatted number data type.

+
+

This sample shows how to work with double data types to create formatted numbers.

-
+

Set up

Try it out

- - -
@@ -143,15 +143,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/20-data-types/data-types-references.yaml b/samples/excel/20-data-types/data-types-references.yaml index af9070c87..266750743 100644 --- a/samples/excel/20-data-types/data-types-references.yaml +++ b/samples/excel/20-data-types/data-types-references.yaml @@ -1,14 +1,14 @@ order: 7 id: excel-data-types-references name: 'Data types: Entity values with references' -description: 'This sample shows how to create entity values with references to other entity values. An entity value is a container for data, and this container can reference (or contain) other entities within the original entity. One entity can contain multiple additional entities.' +description: This sample shows how to create entity values with references to other entity values. An entity value is a container for data, and this container can reference (or contain) other entities within the original entity. One entity can contain multiple additional entities. host: EXCEL api_set: ExcelApi: '1.16' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#add-entities-to-table").click(() => tryCatch(addEntitiesToTable)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("add-entities-to-table").addEventListener("click", () => tryCatch(addEntitiesToTable)); async function addEntitiesToTable() { // This function creates entity values with references to other entity values. @@ -292,17 +292,17 @@ script: ]; language: typescript template: - content: | -
+ content: |- +

This sample shows how to create entity values with references to other entity values. An entity value is a container for data, and this container can reference (or contain) other entities within the original entity. One entity can contain multiple additional entities.

-
+

Set up

-
+

Try it out

To see referenced entities within an entity, take the following steps.

    @@ -316,10 +316,10 @@ template:
  1. To navigate back to the original Andrew Fuller entity, select the Back arrow in the top left corner of the entity card.

You can also use the Extract to grid button in the card modal window, to the right of the Manager or Direct Reports fields, to add the referenced entities to the table in new columns.

-
+
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -331,15 +331,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/20-data-types/data-types-web-image.yaml b/samples/excel/20-data-types/data-types-web-image.yaml index 5cdf97001..fb64e6d37 100644 --- a/samples/excel/20-data-types/data-types-web-image.yaml +++ b/samples/excel/20-data-types/data-types-web-image.yaml @@ -6,19 +6,19 @@ host: EXCEL api_set: ExcelApi: '1.16' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#insert-image").click(() => tryCatch(insertImage)); - $("#retrieve-image-info").click(() => tryCatch(retrieveImageInfo)); - $("#open-image").click(() => tryCatch(openImage)); - $("#clear-form").click(() => tryCatch(clearForm)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("insert-image").addEventListener("click", () => tryCatch(insertImage)); + document.getElementById("retrieve-image-info").addEventListener("click", () => tryCatch(retrieveImageInfo)); + document.getElementById("open-image").addEventListener("click", () => tryCatch(openImage)); + document.getElementById("clear-form").addEventListener("click", () => tryCatch(clearForm)); async function insertImage() { // This function inserts a web image into the currently selected cell. await Excel.run(async (context) => { // Retrieve image data from the task pane and then clear the input fields. - const imageUrl = $("#url").val() as string; - const imageAltText = $("#alt-text").val() as string; + const imageUrl = (document.getElementById("url") as HTMLInputElement).value; + const imageAltText = (document.getElementById("alt-text") as HTMLInputElement).value; clearForm(); // Load the active cell. @@ -65,8 +65,8 @@ script: } // Assign image data to corresponding input fields in the task pane. - $("#url").val(webImageUrl); - $("#alt-text").val(webImageAltText); + (document.getElementById("url") as HTMLInputElement).value = webImageUrl; + (document.getElementById("alt-text") as HTMLInputElement).value = webImageAltText; }); } @@ -95,8 +95,8 @@ script: async function clearForm() { // Clear the input fields in the task pane. - $("#url").val(""); - $("#alt-text").val(""); + (document.getElementById("url") as HTMLInputElement).value = ""; + (document.getElementById("alt-text") as HTMLInputElement).value = ""; } async function setup() { @@ -121,12 +121,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to work with the web image data type. Insert an image into the selected cell and then retrieve information about that image.

- -
+

Set up

Add a new worksheet and then enter the URL and alt text for an image of your choice.

- -
+

Try it out

Select the cell you want to insert the web image into, and then select the Insert image button.

-

Select the cell containing the web image that you want to view the details of, and then select the Retrieve image details button. The image details will display here in the task pane, in the preceding Image URL and Alt text fields.

-

Select the cell with the image you want to view and then select the Open image in browser button. The image will open in a new web browser tab.

-

Clear the Image URL and Alt text fields in the task pane.

- -
+

Try it out

Press Require approved name and then click on a cell in the Baby Name column and use the drop down to enter an approved value.

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -127,15 +128,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/26-document/get-file-in-slices-async.yaml b/samples/excel/26-document/get-file-in-slices-async.yaml index 514a925c5..defcd7050 100644 --- a/samples/excel/26-document/get-file-in-slices-async.yaml +++ b/samples/excel/26-document/get-file-in-slices-async.yaml @@ -7,9 +7,9 @@ api_set: ExcelApi: '1.4' script: content: |- - $("#setup").click(() => tryCatch(setup)); - $("#get-file").click(() => tryCatch(getCurrentFile)); - $("#new-workbook-from-file").click(() => tryCatch(newWorkbookFromFile)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("get-file").addEventListener("click", () => tryCatch(getCurrentFile)); + document.getElementById("new-workbook-from-file").addEventListener("click", () => tryCatch(newWorkbookFromFile)); function getCurrentFile() { const sliceSize = 4096; /*Bytes*/ @@ -35,7 +35,9 @@ script: console.log("Received the full contents of the file."); let base64string = base64js.fromByteArray(byteArray); - $('#file-contents').val(base64string).show(); + const fileContentsElement = document.getElementById("file-contents") as HTMLTextAreaElement; + fileContentsElement.value = base64string; + fileContentsElement.style.display = "block"; console.log("The Base64-encoded string that represents the current document has been written to the text box. To validate the string, use the \"Create workbook from string\" button."); } @@ -82,7 +84,9 @@ script: } async function newWorkbookFromFile() { - await Excel.createWorkbook($('#file-contents').text()).catch(function (error) { + const fileContentsElement = document.getElementById("file-contents"); + const fileContentsText = fileContentsElement.textContent; + await Excel.createWorkbook(fileContentsText).catch(function (error) { console.error(error); }); } @@ -153,29 +157,26 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to get the Base64-encoded string that represents the current document. It uses the getFileAsync() method to read the file in slices and then joins all slices back together to form the complete file.

- -
+

Set up

- -
+

Try it out


- +
- -
+

Create a new workbook

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -204,15 +205,10 @@ style: language: css libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - core-js@2.4.1/client/core.min.js - @types/core-js + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css - jquery@3.1.1 - @types/jquery@3.3.1 https://unpkg.com/base64-js@1.2.1/base64js.min.js diff --git a/samples/excel/26-document/properties.yaml b/samples/excel/26-document/properties.yaml index 3e34550fb..da1c1a4f3 100644 --- a/samples/excel/26-document/properties.yaml +++ b/samples/excel/26-document/properties.yaml @@ -6,12 +6,12 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#set-doc-properties").click(() => tryCatch(setDocProperties)); - $("#get-doc-properties").click(() => tryCatch(getDocProperties)); - $("#set-custom-doc-properties").click(() => tryCatch(setCustomDocProperties)); - $("#get-custom-doc-properties").click(() => tryCatch(getCustomDocProperties)); - $("#get-count-custom-doc-properties").click(() => tryCatch(getCountCustomDocProperties)); + content: |- + document.getElementById("set-doc-properties").addEventListener("click", () => tryCatch(setDocProperties)); + document.getElementById("get-doc-properties").addEventListener("click", () => tryCatch(getDocProperties)); + document.getElementById("set-custom-doc-properties").addEventListener("click", () => tryCatch(setCustomDocProperties)); + document.getElementById("get-custom-doc-properties").addEventListener("click", () => tryCatch(getCustomDocProperties)); + document.getElementById("get-count-custom-doc-properties").addEventListener("click", () => tryCatch(getCountCustomDocProperties)); async function setDocProperties() { await Excel.run(async (context) => { @@ -52,7 +52,7 @@ script: // Write the document properties to the console. // To learn how to view document properties in the UI, - // see https://support.office.com/article/View-or-change-the-properties-for-an-Office-file-21D604C2-481E-4379-8E54-1DD4622C6B75 + // see https://support.microsoft.com/office/21D604C2-481E-4379-8E54-1DD4622C6B75 console.log("Author: " + docProperties.author); console.log("Last author : " + docProperties.lastAuthor); console.log("Revision number: " + docProperties.revisionNumber); @@ -91,7 +91,7 @@ script: // Write the custom document properties to the console. // To learn how to view document properties in the UI, - // see https://support.office.com/article/View-or-change-the-properties-for-an-Office-file-21D604C2-481E-4379-8E54-1DD4622C6B75 + // see https://support.microsoft.com/office/21D604C2-481E-4379-8E54-1DD4622C6B75 console.log("Custom key : " + customProperty.key); console.log("Custom value : " + customProperty.value); @@ -123,45 +123,39 @@ script: } language: typescript template: - content: |+ -
+ content: |- +

This sample shows how to set and get document properties.

- -
+

Try it out

- -
+
- -
+
- -
+
- -
+
- language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -173,15 +167,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/30-events/data-change-event-details.yaml b/samples/excel/30-events/data-change-event-details.yaml index b85591d2d..931b58c9b 100644 --- a/samples/excel/30-events/data-change-event-details.yaml +++ b/samples/excel/30-events/data-change-event-details.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelApi: '1.9' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#register-handler").click(() => tryCatch(registerChangeEventHandler)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("register-handler").addEventListener("click", () => tryCatch(registerChangeEventHandler)); async function registerChangeEventHandler() { await Excel.run(async (context) => { @@ -70,17 +70,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to use table changed events.

- -
+

Setup

-
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -102,15 +101,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/30-events/data-changed.yaml b/samples/excel/30-events/data-changed.yaml index f70d88e7a..468506f12 100644 --- a/samples/excel/30-events/data-changed.yaml +++ b/samples/excel/30-events/data-changed.yaml @@ -7,9 +7,9 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#register-data-changed-handler").click(() => tryCatch(registerDataChangedHandler)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("register-data-changed-handler").addEventListener("click", () => tryCatch(registerDataChangedHandler)); async function registerDataChangedHandler() { await Excel.run(async (context) => { @@ -75,18 +75,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to register and use a handler for the data-changed event.

- -
+

Set up

- -
+

Try it out

- -
+

Try it out

- -
+

Try it out

Click the button to register handlers for the pie chart's activated and deactivated events. Then click the chart to activate it. Watch the console. Finally, click the cylinder chart to deactivate the pie chart.

- -
+

Try it out

Click the button to register and use handlers for the worksheet's ChartCollection events.

-
+

Try it out

In addition to hovering over a cell, you can view comment changes in the Comments pane by selecting Show Comments from the Review tab.

-
+
language: html style: content: |- @@ -167,15 +167,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/30-events/events-disable-events.yaml b/samples/excel/30-events/events-disable-events.yaml index b97d09ca1..681294088 100644 --- a/samples/excel/30-events/events-disable-events.yaml +++ b/samples/excel/30-events/events-disable-events.yaml @@ -6,11 +6,11 @@ host: EXCEL api_set: ExcelApi: '1.8' script: - content: | - $("#toggleEvents").click(() => tryCatch(toggleEvents)); - $("#setup").click(() => tryCatch(setup)); - $("#refreshData").click(() => tryCatch(addOrRefreshData)); - $("#registerSumChangedHandlers").click(() => tryCatch(registerSumChangedHandlers)); + content: |- + document.getElementById("toggleEvents").addEventListener("click", () => tryCatch(toggleEvents)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("refreshData").addEventListener("click", () => tryCatch(addOrRefreshData)); + document.getElementById("registerSumChangedHandlers").addEventListener("click", () => tryCatch(registerSumChangedHandlers)); async function toggleEvents() { await Excel.run(async (context) => { @@ -136,10 +136,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to turn events on and off.

-
+

Setup

-
+

Try it out

The handlers update the "Grand Total" cell when events are fired (and enabled). Try editing the cells or refreshing the data with events enabled and disabled.

- -
+

Try it out

- -
+

Changing data in a table triggers the data changed event. You can change the data manually or programmatically.

- -
+
- -
+

Changing a range selection in a table triggers the table onSelectionChanged event. You can change selection manually or programmatically.

- - language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -163,15 +153,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/30-events/events-tablecollection-changed.yaml b/samples/excel/30-events/events-tablecollection-changed.yaml index e0662c26e..786274970 100644 --- a/samples/excel/30-events/events-tablecollection-changed.yaml +++ b/samples/excel/30-events/events-tablecollection-changed.yaml @@ -6,10 +6,10 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: |+ - $("#setup").click(() => tryCatch(setup)); - $("#register-on-changed-handler").click(() => tryCatch(registerOnChangedHandler)); - $("#change-data").click(() => tryCatch(changeData)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("register-on-changed-handler").addEventListener("click", () => tryCatch(registerOnChangedHandler)); + document.getElementById("change-data").addEventListener("click", () => tryCatch(changeData)); async function registerOnChangedHandler() { await Excel.run(async (context) => { @@ -111,40 +111,33 @@ script: console.error(error); } } - - - language: typescript template: - content: |+ -
+ content: |- +

This sample shows how to register and use an event handler for table collection onChanged event.

- -
+

Set up

- -
+

Try it out

- -
+

Changing data in tables triggers the data changed event. You can change the data manually or programmatically.

- language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -156,15 +149,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/30-events/events-workbook-activated.yaml b/samples/excel/30-events/events-workbook-activated.yaml index 94979e2c8..8f1f6ea6a 100644 --- a/samples/excel/30-events/events-workbook-activated.yaml +++ b/samples/excel/30-events/events-workbook-activated.yaml @@ -6,8 +6,8 @@ host: EXCEL api_set: ExcelAPI: '1.13' script: - content: | - $("#register-event-handler").click(() => tryCatch(registerEventHandler)); + content: |- + document.getElementById("register-event-handler").addEventListener("click", () => tryCatch(registerEventHandler)); async function workbookActivated(event: Excel.WorkbookActivatedEventArgs) { await Excel.run(async (context) => { @@ -40,13 +40,12 @@ script: language: typescript template: content: |- -
+

This sample shows how to register a workbook activated event handler.

Once the event handler is registered, a notification prints to the console when the workbook is activated. Try switching to another application and then switching back to Excel to see the console notification.

- -
+

Try it out

@@ -187,7 +185,6 @@ template: Add worksheet
-

Activated/Deactivated

-

Settings

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -224,15 +220,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/30-events/events-worksheet-protection.yaml b/samples/excel/30-events/events-worksheet-protection.yaml index 509e0a554..636bc2b52 100644 --- a/samples/excel/30-events/events-worksheet-protection.yaml +++ b/samples/excel/30-events/events-worksheet-protection.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelAPI: '1.14' script: - content: | - $("#register-event").click(() => tryCatch(registerEvent)); - $("#change-protection").click(() => tryCatch(changeProtection)); + content: |- + document.getElementById("register-event").addEventListener("click", () => tryCatch(registerEvent)); + document.getElementById("change-protection").addEventListener("click", () => tryCatch(changeProtection)); async function registerEvent() { // This function registers an event handler for the onProtectionChanged event of a worksheet. @@ -69,10 +69,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to register a worksheet protection change event handler. Once the event handler is registered, you can enable and disable worksheet protection for the current worksheet. When worksheet protection is enabled, the current worksheet can't be edited.

-
+

Try it out

-
+
language: html style: content: |- @@ -97,15 +97,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/30-events/events-worksheet.yaml b/samples/excel/30-events/events-worksheet.yaml index 682015fe7..ed4c09408 100644 --- a/samples/excel/30-events/events-worksheet.yaml +++ b/samples/excel/30-events/events-worksheet.yaml @@ -1,23 +1,23 @@ order: 15 id: excel-events-worksheet name: Worksheet events -description: 'Registers event handlers that run when data is changed in worksheet, the selected range changes in a worksheet, or the worksheet is recalculated.' +description: Registers event handlers that run when data is changed in worksheet, the selected range changes in a worksheet, or the worksheet is recalculated. author: OfficeDev host: EXCEL api_set: ExcelApi: '1.7' script: content: |- - $("#setup").click(() => tryCatch(setup)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); - $("#register-on-selection-changed-handler").click(() => tryCatch(registerSelectionChangedHandler)); - $("#select-range").click(() => tryCatch(selectRange)); + document.getElementById("register-on-selection-changed-handler").addEventListener("click", () => tryCatch(registerSelectionChangedHandler)); + document.getElementById("select-range").addEventListener("click", () => tryCatch(selectRange)); - $("#register-on-changed-handler").click(() => tryCatch(registerOnChangedHandler)); - $("#register-onCalculated-handler").click(() => tryCatch(registerOnCalculatedHandler)); - $("#recalculate").click(() => tryCatch(recalculate)); + document.getElementById("register-on-changed-handler").addEventListener("click", () => tryCatch(registerOnChangedHandler)); + document.getElementById("register-onCalculated-handler").addEventListener("click", () => tryCatch(registerOnCalculatedHandler)); + document.getElementById("recalculate").addEventListener("click", () => tryCatch(recalculate)); - $("#delete-data").click(() => tryCatch(deleteData)); + document.getElementById("delete-data").addEventListener("click", () => tryCatch(deleteData)); async function registerSelectionChangedHandler() { await Excel.run(async (context) => { @@ -169,21 +169,18 @@ script: language: typescript template: content: |- -
+

This sample shows how to register and use an event handler for the worksheet onSelectionChanged event.

- -
+

Set up

- -
+

Try it out

- -

Selection Changed

+

Selection Changed

@@ -208,7 +205,7 @@ template:
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -220,15 +217,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/30-events/selection-changed-events.yaml b/samples/excel/30-events/selection-changed-events.yaml index 285379ebd..ab7203010 100644 --- a/samples/excel/30-events/selection-changed-events.yaml +++ b/samples/excel/30-events/selection-changed-events.yaml @@ -7,9 +7,9 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#register-event-handlers").click(() => tryCatch(registerEventHandlers)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("register-event-handlers").addEventListener("click", () => tryCatch(registerEventHandlers)); async function registerEventHandlers() { await Excel.run(async (context) => { @@ -101,12 +101,11 @@ script: } language: typescript template: - content: |+ -
+ content: |- +

This sample shows how to register and use event handlers for table onChanged and onSelectionChanged events.

- -
+

Set up

- -
+

Try it out

- -
+

The console will log the addresses reported by the different onSelectionChanged events. Change the cell or cells selected in the worksheet to see the results. Try selecting single cells, multiple cells, and multiple discontiguous cells.

- - language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -146,15 +141,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/34-named-item/create-and-remove-named-item.yaml b/samples/excel/34-named-item/create-and-remove-named-item.yaml index c152eb15d..eadc487fa 100644 --- a/samples/excel/34-named-item/create-and-remove-named-item.yaml +++ b/samples/excel/34-named-item/create-and-remove-named-item.yaml @@ -1,19 +1,19 @@ order: 1 id: excel-named-item-create-and-remove-named-item -name: 'Create, access, and remove' -description: 'Creates, accesses, and removes named items in a worksheet.' +name: Create, access, and remove +description: Creates, accesses, and removes named items in a worksheet. host: EXCEL api_set: ExcelApi: '1.4' script: content: |- - $("#setup").click(() => tryCatch(setup)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); - $("#add-name-to-total").click(() => tryCatch(addNameToTotal)); - $("#add-name-to-header").click(() => tryCatch(addNameToHeader)); - $("#format-named-range").click(() => tryCatch(formatRangeByName)); - $("#remove-name").click(() => tryCatch(removeName)); - $("#list-named-items").click(() => tryCatch(listNamedItems)); + document.getElementById("add-name-to-total").addEventListener("click", () => tryCatch(addNameToTotal)); + document.getElementById("add-name-to-header").addEventListener("click", () => tryCatch(addNameToHeader)); + document.getElementById("format-named-range").addEventListener("click", () => tryCatch(formatRangeByName)); + document.getElementById("remove-name").addEventListener("click", () => tryCatch(removeName)); + document.getElementById("list-named-items").addEventListener("click", () => tryCatch(listNamedItems)); async function addNameToTotal() { await Excel.run(async (context) => { @@ -78,13 +78,15 @@ script: async function listNamedItems() { await Excel.run(async (context) => { + // Log all the named items in the active worksheet. const namedItems = context.workbook.worksheets.getActiveWorksheet().names.load(); await context.sync(); console.log("This worksheet contains " + namedItems.items.length + " named items."); for (let i = 0; i < namedItems.items.length; i++) { - console.log(JSON.stringify(namedItems.items[i])) + "\n"; + const namedItem : Excel.NamedItem = namedItems.items[i]; + console.log(JSON.stringify(namedItem)) + "\n"; } await context.sync(); @@ -180,12 +182,11 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to create, access, and delete named items.

- -
+

Setup

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -124,13 +123,7 @@ style: language: css libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/38-pivottable/pivottable-calculations.yaml b/samples/excel/38-pivottable/pivottable-calculations.yaml index ba8886dd7..d66f74eb9 100644 --- a/samples/excel/38-pivottable/pivottable-calculations.yaml +++ b/samples/excel/38-pivottable/pivottable-calculations.yaml @@ -8,11 +8,11 @@ api_set: ExcelApi: '1.8' script: content: |- - $("#setup").click(() => tryCatch(setup)); - $("#deletePivot").click(() => tryCatch(deletePivot)); - $("#showPercentages").click(() => tryCatch(showPercentages)); - $("#showDifferenceFrom").click(() => tryCatch(showDifferenceFrom)); - $("#showSums").click(() => tryCatch(showSums)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("deletePivot").addEventListener("click", () => tryCatch(deletePivot)); + document.getElementById("showPercentages").addEventListener("click", () => tryCatch(showPercentages)); + document.getElementById("showDifferenceFrom").addEventListener("click", () => tryCatch(showDifferenceFrom)); + document.getElementById("showSums").addEventListener("click", () => tryCatch(showSums)); async function showPercentages() { await Excel.run(async (context) => { @@ -152,22 +152,20 @@ script: // Note: In a production add-in, you'd want to notify the user through your add-in's UI. console.error(error); } - } + } language: typescript template: content: |- -
+

This sample shows how to change the calculations of PivotTable data hierarchies.

- -
+

Set up

- -
+

Try it out

- -
+

Clean up

-
+

Try it out

-
+

Create the PivotTable

- -
+

Adjust the PivotTable

- -
+

Adjust formatting

- -
+

Delete the PivotTable

- -
+

Try it out

- -
+

Change functions

- -
+

Filtering

After pressing the "Enable filter" button, manually select the classification filter for the PivotTable - -

+

Data Manipulation

- -
+

Clean up

- -
+

Try it out

- -
+
@@ -185,15 +182,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/38-pivottable/pivottable-pivotfilters.yaml b/samples/excel/38-pivottable/pivottable-pivotfilters.yaml index d07c74f5e..bb857275b 100644 --- a/samples/excel/38-pivottable/pivottable-pivotfilters.yaml +++ b/samples/excel/38-pivottable/pivottable-pivotfilters.yaml @@ -6,15 +6,15 @@ host: EXCEL api_set: ExcelAPI: '1.12' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#manual-filter").click(() => tryCatch(manualFilter)); - $("#date-filter").click(() => tryCatch(dateFilter)); - $("#value-filter").click(() => tryCatch(valueFilter)); - $("#label-filter").click(() => tryCatch(labelFilter)); - $("#clear-filters").click(() => tryCatch(clearFilters)); - $("#log-filters").click(() => tryCatch(logFilters)); - $("#get-crate-total").click(() => tryCatch(getCrateTotal)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("manual-filter").addEventListener("click", () => tryCatch(manualFilter)); + document.getElementById("date-filter").addEventListener("click", () => tryCatch(dateFilter)); + document.getElementById("value-filter").addEventListener("click", () => tryCatch(valueFilter)); + document.getElementById("label-filter").addEventListener("click", () => tryCatch(labelFilter)); + document.getElementById("clear-filters").addEventListener("click", () => tryCatch(clearFilters)); + document.getElementById("log-filters").addEventListener("click", () => tryCatch(logFilters)); + document.getElementById("get-crate-total").addEventListener("click", () => tryCatch(getCrateTotal)); async function manualFilter() { await Excel.run(async (context) => { @@ -253,22 +253,19 @@ script: language: typescript template: content: |- -
+

This sample shows how to filter PivotTables with the different PivotFilters.

- -
+

Set up

- -
+

Try it out

- -
+

Filters

Manual filter

-

PivotTable Status

-
+

Try it out

-
+

Try it out

Add a row to the table, then refresh the PivotTable. Note that the PivotTable doesn't automatically refresh.

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -126,15 +125,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/38-pivottable/pivottable-slicer.yaml b/samples/excel/38-pivottable/pivottable-slicer.yaml index 96c967688..1b057f748 100644 --- a/samples/excel/38-pivottable/pivottable-slicer.yaml +++ b/samples/excel/38-pivottable/pivottable-slicer.yaml @@ -6,15 +6,15 @@ host: EXCEL api_set: ExcelApi: '1.10' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#add-pivot-table").click(() => tryCatch(addPivotTable)); - $("#add-slicer").click(() => tryCatch(addSlicer)); - $("#format-slicer").click(() => tryCatch(formatSlicer)); - $("#apply-style").click(() => tryCatch(applyStyle)); - $("#add-filters").click(() => tryCatch(addFilters)); - $("#remove-filters").click(() => tryCatch(removeFilters)); - $("#remove-slicer").click(() => tryCatch(removeSlicer)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("add-pivot-table").addEventListener("click", () => tryCatch(addPivotTable)); + document.getElementById("add-slicer").addEventListener("click", () => tryCatch(addSlicer)); + document.getElementById("format-slicer").addEventListener("click", () => tryCatch(formatSlicer)); + document.getElementById("apply-style").addEventListener("click", () => tryCatch(applyStyle)); + document.getElementById("add-filters").addEventListener("click", () => tryCatch(addFilters)); + document.getElementById("remove-filters").addEventListener("click", () => tryCatch(removeFilters)); + document.getElementById("remove-slicer").addEventListener("click", () => tryCatch(removeSlicer)); async function addSlicer() { await Excel.run(async (context) => { @@ -142,11 +142,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to work with a slicer on a PivotTable.

- -
+

Setup

-
+

Try it out

Add the slicer, then try out the formatting and filtering options.

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -200,15 +199,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/38-pivottable/pivottable-source-data.yaml b/samples/excel/38-pivottable/pivottable-source-data.yaml index e0ceb5821..238b79392 100644 --- a/samples/excel/38-pivottable/pivottable-source-data.yaml +++ b/samples/excel/38-pivottable/pivottable-source-data.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelApi: '1.15' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#get-pivottable-data-source").click(() => tryCatch(getPivotTableDataSource)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("get-pivottable-data-source").addEventListener("click", () => tryCatch(getPivotTableDataSource)); async function getPivotTableDataSource() { // This function logs information about the data source of a PivotTable. @@ -89,24 +89,22 @@ script: language: typescript template: content: |- -
+

This sample shows how to get information about the data source of a PivotTable. It returns the type and string representation of the data source.

Note: This sample works in Excel on Windows and Excel on the web. It doesn't work in Excel on Mac; this is a known issue.

- -
+

Set up

- -
+

Try it out

-
+
language: html style: content: |- @@ -121,15 +119,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/42-range/cell-properties.yaml b/samples/excel/42-range/cell-properties.yaml index e923d3f2d..bdf6baafb 100644 --- a/samples/excel/42-range/cell-properties.yaml +++ b/samples/excel/42-range/cell-properties.yaml @@ -7,10 +7,10 @@ host: EXCEL api_set: ExcelApi: '1.9' script: - content: | - $("#set-cell-properties").click(() => tryCatch(setCellProperties)); - $("#get-cell-properties").click(() => tryCatch(getCellProperties)); - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("set-cell-properties").addEventListener("click", () => tryCatch(setCellProperties)); + document.getElementById("get-cell-properties").addEventListener("click", () => tryCatch(getCellProperties)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); async function setCellProperties() { await Excel.run(async (context) => { @@ -145,18 +145,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to format a range.

- -
+

Set up

- -
+

Try it out

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -171,15 +169,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/42-range/formatting.yaml b/samples/excel/42-range/formatting.yaml index a8abfa954..f4f5a4a91 100644 --- a/samples/excel/42-range/formatting.yaml +++ b/samples/excel/42-range/formatting.yaml @@ -7,11 +7,11 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); - $("#set-font-and-fill-color").click(() => tryCatch(setFontAndFillColor)); - $("#set-number-format").click(() => tryCatch(setNumberFormat)); + document.getElementById("set-font-and-fill-color").addEventListener("click", () => tryCatch(setFontAndFillColor)); + document.getElementById("set-number-format").addEventListener("click", () => tryCatch(setNumberFormat)); async function setFontAndFillColor() { await Excel.run(async (context) => { @@ -75,19 +75,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to format a range.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -110,15 +108,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/42-range/insert-delete-clear-range.yaml b/samples/excel/42-range/insert-delete-clear-range.yaml index cd6db23fd..2507db642 100644 --- a/samples/excel/42-range/insert-delete-clear-range.yaml +++ b/samples/excel/42-range/insert-delete-clear-range.yaml @@ -1,18 +1,18 @@ order: 8 id: excel-range-insert-delete-and-clear-range -name: 'Insert, delete, and clear' -description: 'Inserts, deletes, and clears a range.' +name: Insert, delete, and clear +description: Inserts, deletes, and clears a range. author: OfficeDev host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); - $("#insert-range").click(() => tryCatch(insertRange)); - $("#delete-range").click(() => tryCatch(deleteRange)); - $("#clear-range").click(() => tryCatch(clearRange)); + document.getElementById("insert-range").addEventListener("click", () => tryCatch(insertRange)); + document.getElementById("delete-range").addEventListener("click", () => tryCatch(deleteRange)); + document.getElementById("clear-range").addEventListener("click", () => tryCatch(clearRange)); async function insertRange() { await Excel.run(async (context) => { @@ -85,19 +85,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to insert, delete and clear the contents of a range.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -123,15 +121,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/42-range/outline.yaml b/samples/excel/42-range/outline.yaml index 02f043b4a..e4d261065 100644 --- a/samples/excel/42-range/outline.yaml +++ b/samples/excel/42-range/outline.yaml @@ -6,14 +6,14 @@ host: EXCEL api_set: ExcelApi: '1.10' script: - content: | - $("#setup-data").click(() => tryCatch(setupData)); - $("#setup-totals").click(() => tryCatch(setupTotals)); - $("#group-rows").click(() => tryCatch(groupRows)); - $("#group-columns").click(() => tryCatch(groupColumns)); - $("#collapse-outline").click(() => tryCatch(collapseOutline)); - $("#expand-outline").click(() => tryCatch(expandOutline)); - $("#ungroup").click(() => tryCatch(ungroup)); + content: |- + document.getElementById("setup-data").addEventListener("click", () => tryCatch(setupData)); + document.getElementById("setup-totals").addEventListener("click", () => tryCatch(setupTotals)); + document.getElementById("group-rows").addEventListener("click", () => tryCatch(groupRows)); + document.getElementById("group-columns").addEventListener("click", () => tryCatch(groupColumns)); + document.getElementById("collapse-outline").addEventListener("click", () => tryCatch(collapseOutline)); + document.getElementById("expand-outline").addEventListener("click", () => tryCatch(expandOutline)); + document.getElementById("ungroup").addEventListener("click", () => tryCatch(ungroup)); async function groupRows() { Excel.run(async (context) => { @@ -171,11 +171,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to group and ungroup rows and columns for an outline.

- -
+

Set up

- -
+

Try it out

-
+

Try it out

-
+
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -201,15 +201,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/42-range/range-areas.yaml b/samples/excel/42-range/range-areas.yaml index cfbff6ec9..1b3297ce9 100644 --- a/samples/excel/42-range/range-areas.yaml +++ b/samples/excel/42-range/range-areas.yaml @@ -1,18 +1,18 @@ order: 3 id: excel-range-areas name: Discontiguous ranges (RangeAreas) and special cells -description: 'Creates and uses RangeAreas, which are sets of ranges that need not be contiguous, through user selection and programmatic selection of special cells.' +description: Creates and uses RangeAreas, which are sets of ranges that need not be contiguous, through user selection and programmatic selection of special cells. host: EXCEL api_set: ExcelApi: '1.9' script: - content: | - $("#reset").click(() => tryCatch(reset)); - $("#color-selected-ranges").click(() => tryCatch(colorSelectedRanges)); - $("#color-specified-ranges").click(() => tryCatch(colorSpecifiedRanges)); - $("#color-all-formula-ranges").click(() => tryCatch(colorAllFormulaRanges)); - $("#color-all-logical-text-ranges").click(() => tryCatch(colorAllLogicalAndTextRanges)); - $("#read-properties-specified-ranges").click(() => tryCatch(readPropertiesOfSpecifiedRanges)); + content: |- + document.getElementById("reset").addEventListener("click", () => tryCatch(reset)); + document.getElementById("color-selected-ranges").addEventListener("click", () => tryCatch(colorSelectedRanges)); + document.getElementById("color-specified-ranges").addEventListener("click", () => tryCatch(colorSpecifiedRanges)); + document.getElementById("color-all-formula-ranges").addEventListener("click", () => tryCatch(colorAllFormulaRanges)); + document.getElementById("color-all-logical-text-ranges").addEventListener("click", () => tryCatch(colorAllLogicalAndTextRanges)); + document.getElementById("read-properties-specified-ranges").addEventListener("click", () => tryCatch(readPropertiesOfSpecifiedRanges)); async function colorSelectedRanges() { await Excel.run(async (context) => { @@ -123,12 +123,11 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to apply actions simultaneously to multiple, discontiguous ranges. Some of these ranges are found using the Range object's getSpecialCells method.

- -
+

Set up

- -
+

Try it out

+
+
+

Try it out

+ +
+ +
+ +
+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/42-range/range-copyfrom.yaml b/samples/excel/42-range/range-copyfrom.yaml index 0db6cc1ac..391b6ef7a 100644 --- a/samples/excel/42-range/range-copyfrom.yaml +++ b/samples/excel/42-range/range-copyfrom.yaml @@ -6,16 +6,16 @@ host: EXCEL api_set: ExcelApi: '1.10' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#copyAll").click(() => tryCatch(copyAll)); - $("#copyFormula").click(() => tryCatch(copyFormula)); - $("#copyFormulaResult").click(() => tryCatch(copyFormulaResult)); - $("#copySingleAcrossRange").click(() => tryCatch(copySingleAcrossRange)); - $("#copyOnlyFormat").click(() => tryCatch(copyOnlyFormat)); - $("#skipBlanks").click(() => tryCatch(skipBlanks)); - $("#transpose").click(() => tryCatch(transpose)); - $("#move").click(() => tryCatch(move)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("copyAll").addEventListener("click", () => tryCatch(copyAll)); + document.getElementById("copyFormula").addEventListener("click", () => tryCatch(copyFormula)); + document.getElementById("copyFormulaResult").addEventListener("click", () => tryCatch(copyFormulaResult)); + document.getElementById("copySingleAcrossRange").addEventListener("click", () => tryCatch(copySingleAcrossRange)); + document.getElementById("copyOnlyFormat").addEventListener("click", () => tryCatch(copyOnlyFormat)); + document.getElementById("skipBlanks").addEventListener("click", () => tryCatch(skipBlanks)); + document.getElementById("transpose").addEventListener("click", () => tryCatch(transpose)); + document.getElementById("move").addEventListener("click", () => tryCatch(move)); async function copyAll() { await Excel.run(async (context) => { @@ -154,16 +154,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to copy data and formatting from one range (A1:E1) to another.

-
+

Setup

-
+

Try it out

-
+

Try it out

Cell D3 has dependents across worksheets.

-
+
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -160,15 +160,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/42-range/range-direct-dependents.yaml b/samples/excel/42-range/range-direct-dependents.yaml index 27f0ce290..8942430fe 100644 --- a/samples/excel/42-range/range-direct-dependents.yaml +++ b/samples/excel/42-range/range-direct-dependents.yaml @@ -6,11 +6,11 @@ host: EXCEL api_set: ExcelAPI: '1.13' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#select-D3").click(() => tryCatch(selectD3)); - $("#select-E4").click(() => tryCatch(selectE4)); - $("#get-direct-dependents").click(() => tryCatch(getDirectDependents)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("select-D3").addEventListener("click", () => tryCatch(selectD3)); + document.getElementById("select-E4").addEventListener("click", () => tryCatch(selectE4)); + document.getElementById("get-direct-dependents").addEventListener("click", () => tryCatch(getDirectDependents)); /** Select a cell with direct dependents on the same worksheet. */ async function selectD3() { @@ -116,18 +116,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to find and highlight the dependents of the currently selected cell. Dependent cells contain formulas that refer to other cells.

- -
+

Set up

- -
+

Try it out

Cells in the 'E' column have direct dependents on the same worksheet. Cells in the 'F' column have direct dependents on another worksheet.

-
+

Try it out

Enter text to search for in the box below and press Find text or Find text with null check to display the found text's address in the console.

@@ -159,13 +161,7 @@ style: language: css libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/42-range/range-get-range-edge.yaml b/samples/excel/42-range/range-get-range-edge.yaml index a16b965c3..d4f020020 100644 --- a/samples/excel/42-range/range-get-range-edge.yaml +++ b/samples/excel/42-range/range-get-range-edge.yaml @@ -1,19 +1,19 @@ order: 20 id: excel-range-get-range-edge name: Select used range edge -description: 'This sample shows how to select the edges of the used range, based on the currently selected range.' +description: This sample shows how to select the edges of the used range, based on the currently selected range. host: EXCEL api_set: ExcelAPI: '1.13' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#select-E9").click(() => tryCatch(selectE9)); - $("#select-D8-E9").click(() => tryCatch(selectD8E9)); - $("#get-range-edge-left").click(() => tryCatch(getRangeEdgeLeft)); - $("#get-range-edge-up").click(() => tryCatch(getRangeEdgeUp)); - $("#get-extended-range-right").click(() => tryCatch(getExtendedRangeRight)); - $("#get-extended-range-down").click(() => tryCatch(getExtendedRangeDown)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("select-E9").addEventListener("click", () => tryCatch(selectE9)); + document.getElementById("select-D8-E9").addEventListener("click", () => tryCatch(selectD8E9)); + document.getElementById("get-range-edge-left").addEventListener("click", () => tryCatch(getRangeEdgeLeft)); + document.getElementById("get-range-edge-up").addEventListener("click", () => tryCatch(getRangeEdgeUp)); + document.getElementById("get-extended-range-right").addEventListener("click", () => tryCatch(getExtendedRangeRight)); + document.getElementById("get-extended-range-down").addEventListener("click", () => tryCatch(getExtendedRangeDown)); async function getRangeEdgeLeft() { await Excel.run(async (context) => { @@ -170,17 +170,16 @@ script: language: typescript template: content: |- -

+

This sample shows how to select the edges of the used range, based on the currently selected range.

-
+

Set up

- -
+

Try it out


-

The first type of range edge selection selects the cell at the furthest edge of the current used range, in the directions up or left. This action matches the result of using the Ctrl+Arrow key keyboard shortcut while a range is selected.

+

The first type of range edge selection selects the cell at the furthest edge of the current used range, in the directions up or left. This action matches the result of using the Ctrl+Arrow key keyboard shortcut while a range is selected.

@@ -197,7 +196,7 @@ template: Go to top edge of used range
-

The second type of range edge selection selects all the cells from the currently selected range to the furthest edge of the used range, in the directions right or down. This action matches the result of using the Ctrl+Shift+Arrow key keyboard shortcut while a range is selected.

+

The second type of range edge selection selects all the cells from the currently selected range to the furthest edge of the used range, in the directions right or down. This action matches the result of using the Ctrl+Shift+Arrow key keyboard shortcut while a range is selected.

@@ -218,15 +217,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/42-range/range-hyperlink.yaml b/samples/excel/42-range/range-hyperlink.yaml index 1f7f91207..035a8cb50 100644 --- a/samples/excel/42-range/range-hyperlink.yaml +++ b/samples/excel/42-range/range-hyperlink.yaml @@ -1,19 +1,19 @@ order: 7 id: excel-range-hyperlink name: Hyperlinks -description: 'Creates, updates, and clears hyperlinks in a range.' +description: Creates, updates, and clears hyperlinks in a range. author: OfficeDev host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); - $("#create-url-hyperlinks").click(() => tryCatch(createUrlHyperlinks)); - $("#create-document-hyperlinks").click(() => tryCatch(createDocumentHyperlinks)); - $("#update-hyperlinks").click(() => tryCatch(updateHyperlinks)); - $("#clear-hyperlinks").click(() => tryCatch(clearHyperlinks)); + document.getElementById("create-url-hyperlinks").addEventListener("click", () => tryCatch(createUrlHyperlinks)); + document.getElementById("create-document-hyperlinks").addEventListener("click", () => tryCatch(createDocumentHyperlinks)); + document.getElementById("update-hyperlinks").addEventListener("click", () => tryCatch(updateHyperlinks)); + document.getElementById("clear-hyperlinks").addEventListener("click", () => tryCatch(clearHyperlinks)); async function createUrlHyperlinks() { await Excel.run(async (context) => { @@ -112,7 +112,7 @@ script: let cellRange = productsRange.getCell(i, 0); // Clear the hyperlink. - // This eliminates the hyperlink but does not update text format. + // This removes the hyperlink but does not update text format. cellRange.clear(Excel.ClearApplyTo.hyperlinks); // Update text format. @@ -273,18 +273,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to create, update, and clear a hyperlink for a range.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -313,15 +311,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/42-range/range-merged-ranges.yaml b/samples/excel/42-range/range-merged-ranges.yaml index 0961a0015..62db7860f 100644 --- a/samples/excel/42-range/range-merged-ranges.yaml +++ b/samples/excel/42-range/range-merged-ranges.yaml @@ -6,10 +6,10 @@ host: EXCEL api_set: ExcelAPI: '1.13' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#create-merged-range").click(() => tryCatch(createMergedRange)); - $("#get-merged-range").click(() => tryCatch(getMergedRange)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("create-merged-range").addEventListener("click", () => tryCatch(createMergedRange)); + document.getElementById("get-merged-range").addEventListener("click", () => tryCatch(getMergedRange)); async function createMergedRange() { await Excel.run(async (context) => { @@ -92,18 +92,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to create and find merged ranges in a worksheet.

- -
+

Set up

- -
+

Try it out

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -248,15 +246,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/42-range/range-remove-duplicates.yaml b/samples/excel/42-range/range-remove-duplicates.yaml index 1d61d4180..c6fd18196 100644 --- a/samples/excel/42-range/range-remove-duplicates.yaml +++ b/samples/excel/42-range/range-remove-duplicates.yaml @@ -6,11 +6,11 @@ host: EXCEL api_set: ExcelApi: '1.9' script: - content: | - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); - $("#delete-name").click(() => tryCatch(deleteName)); - $("#delete-distributor").click(() => tryCatch(deleteDistributor)); + document.getElementById("delete-name").addEventListener("click", () => tryCatch(deleteName)); + document.getElementById("delete-distributor").addEventListener("click", () => tryCatch(deleteDistributor)); async function deleteName() { await Excel.run(async (context) => { @@ -83,19 +83,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to remove rows with duplicate column values from a range.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -119,15 +117,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/42-range/range-text-orientation.yaml b/samples/excel/42-range/range-text-orientation.yaml index 7211ee30b..a24409415 100644 --- a/samples/excel/42-range/range-text-orientation.yaml +++ b/samples/excel/42-range/range-text-orientation.yaml @@ -7,10 +7,10 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#set-text-orientation").click(() => tryCatch(setTextOrientation)); - $("#get-text-orientation").click(() => tryCatch(getTextOrientation)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("set-text-orientation").addEventListener("click", () => tryCatch(setTextOrientation)); + document.getElementById("get-text-orientation").addEventListener("click", () => tryCatch(getTextOrientation)); async function setTextOrientation() { await Excel.run(async (context) => { @@ -75,19 +75,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to set and get the text orientation within a range.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -113,15 +111,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/42-range/selected-range.yaml b/samples/excel/42-range/selected-range.yaml index 4c14a5798..5b3dda01b 100644 --- a/samples/excel/42-range/selected-range.yaml +++ b/samples/excel/42-range/selected-range.yaml @@ -7,9 +7,9 @@ host: EXCEL api_set: ExcelApi: '1.1' script: - content: | - $("#get-selection").click(() => tryCatch(getSelection)); - $("#set-selection").click(() => tryCatch(setSelection)); + content: |- + document.getElementById("get-selection").addEventListener("click", () => tryCatch(getSelection)); + document.getElementById("set-selection").addEventListener("click", () => tryCatch(setSelection)); async function getSelection() { await Excel.run(async (context) => { @@ -45,12 +45,11 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to get and set the currently selected range.

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -73,15 +72,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/42-range/set-get-values.yaml b/samples/excel/42-range/set-get-values.yaml index b9c1d91fc..78c79eefd 100644 --- a/samples/excel/42-range/set-get-values.yaml +++ b/samples/excel/42-range/set-get-values.yaml @@ -7,17 +7,17 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(() => tryCatch(setup)); - - $("#set-value").click(() => tryCatch(setValue)); - $("#set-values").click(() => tryCatch(setValues)); - $("#set-formula").click(() => tryCatch(setFormula)); - $("#set-formulas").click(() => tryCatch(setFormulas)); - $("#set-formulas-r1c1").click(() => tryCatch(setFormulasR1C1)); - $("#get-values").click(() => tryCatch(getValues)); - $("#get-texts").click(() => tryCatch(getTexts)); - $("#get-formulas").click(() => tryCatch(getFormulas)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + document.getElementById("set-value").addEventListener("click", () => tryCatch(setValue)); + document.getElementById("set-values").addEventListener("click", () => tryCatch(setValues)); + document.getElementById("set-formula").addEventListener("click", () => tryCatch(setFormula)); + document.getElementById("set-formulas").addEventListener("click", () => tryCatch(setFormulas)); + document.getElementById("set-formulas-r1c1").addEventListener("click", () => tryCatch(setFormulasR1C1)); + document.getElementById("get-values").addEventListener("click", () => tryCatch(getValues)); + document.getElementById("get-texts").addEventListener("click", () => tryCatch(getTexts)); + document.getElementById("get-formulas").addEventListener("click", () => tryCatch(getFormulas)); async function setValue() { await Excel.run(async (context) => { @@ -173,21 +173,18 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to set and get values and formulas for a range.

- -
+

Set up

- -
+

Try it out

- @@ -203,9 +200,7 @@ template: -
- @@ -218,7 +213,7 @@ template:
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -230,15 +225,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/42-range/style.yaml b/samples/excel/42-range/style.yaml index 2ad8bcd6c..3254d3bb1 100644 --- a/samples/excel/42-range/style.yaml +++ b/samples/excel/42-range/style.yaml @@ -1,20 +1,20 @@ order: 14 id: excel-range-style name: Style -description: 'Creates a custom style, applies a custom and built-in styles to a range, gets style properties, and deletes the custom style.' +description: Creates a custom style, applies a custom and built-in styles to a range, gets style properties, and deletes the custom style. author: siewmoi host: EXCEL api_set: ExcelApi: '1.7' script: - content: |+ - $("#setup").click(() => tryCatch(setup)); - $("#add-new-style").click(() => tryCatch(addNewStyle)); - $("#apply-new-style").click(() => tryCatch(applyNewStyle)); - $("#apply-built-in-style").click(() => tryCatch(applyBuiltInStyle)); - $("#get-style-font").click(() => tryCatch(getStyleFontProperties)); - $("#get-style-alignment").click(() => tryCatch(getStyleAlignmentProperties)); - $("#delete-new-style").click(() => tryCatch(deleteNewStyle)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("add-new-style").addEventListener("click", () => tryCatch(addNewStyle)); + document.getElementById("apply-new-style").addEventListener("click", () => tryCatch(applyNewStyle)); + document.getElementById("apply-built-in-style").addEventListener("click", () => tryCatch(applyBuiltInStyle)); + document.getElementById("get-style-font").addEventListener("click", () => tryCatch(getStyleFontProperties)); + document.getElementById("get-style-alignment").addEventListener("click", () => tryCatch(getStyleAlignmentProperties)); + document.getElementById("delete-new-style").addEventListener("click", () => tryCatch(deleteNewStyle)); async function addNewStyle() { await Excel.run(async (context) => { @@ -151,56 +151,46 @@ script: console.error(error); } } - - - language: typescript template: - content: | -
+ content: |- +

This sample shows how to add, apply, get and delete styles.

- -
+

Set up

- -
+

Try it out

Add new style will throw an error if the style has already been added.

- -
+
- -
+
- -
+
- -
+
- -
+

Clean up

Delete new style throws an error if the style doesn't exist (that is, hasn't been added). Deleting the style also causes the other buttons using the style to fail.

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -135,15 +133,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/44-shape/shape-create-and-delete.yaml b/samples/excel/44-shape/shape-create-and-delete.yaml index 3469e9ea7..13f4500fb 100644 --- a/samples/excel/44-shape/shape-create-and-delete.yaml +++ b/samples/excel/44-shape/shape-create-and-delete.yaml @@ -6,12 +6,12 @@ host: EXCEL api_set: ExcelApi: '1.9' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#createHexagon").click(() => tryCatch(createHexagon)); - $("#createTriangle").click(() => tryCatch(createTriangle)); - $("#createSmileyFace").click(() => tryCatch(createSmileyFace)); - $("#removeAll").click(() => tryCatch(removeAll)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("createHexagon").addEventListener("click", () => tryCatch(createHexagon)); + document.getElementById("createTriangle").addEventListener("click", () => tryCatch(createTriangle)); + document.getElementById("createSmileyFace").addEventListener("click", () => tryCatch(createSmileyFace)); + document.getElementById("removeAll").addEventListener("click", () => tryCatch(removeAll)); async function createHexagon() { await Excel.run(async (context) => { @@ -90,16 +90,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to create different shapes, then delele them.

-
+

Setup

-
+

Try it out

+
+
+

Try it out

+

Add a shape to the workbook. This button adds a shape that covers the existing chart title with a new shape that contains text.

+ +
+
+

Group the new chart title together with the existing chart.

+ +
+
+

Get the active shape and display it as an image in this task pane. Make sure the chart is selected.

+ +
+
+

Image of the active shape:

+
+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/44-shape/shape-groups.yaml b/samples/excel/44-shape/shape-groups.yaml index b6d60f218..6fd30d1ad 100644 --- a/samples/excel/44-shape/shape-groups.yaml +++ b/samples/excel/44-shape/shape-groups.yaml @@ -6,12 +6,12 @@ host: EXCEL api_set: ExcelApi: '1.9' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#createShapes").click(() => tryCatch(createShapes)); - $("#groupShapes").click(() => tryCatch(groupShapes)); - $("#moveGroup").click(() => tryCatch(moveGroup)); - $("#ungroupShapes").click(() => tryCatch(ungroupShapes)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("createShapes").addEventListener("click", () => tryCatch(createShapes)); + document.getElementById("groupShapes").addEventListener("click", () => tryCatch(groupShapes)); + document.getElementById("moveGroup").addEventListener("click", () => tryCatch(moveGroup)); + document.getElementById("ungroupShapes").addEventListener("click", () => tryCatch(ungroupShapes)); async function groupShapes() { await Excel.run(async (context) => { @@ -105,10 +105,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to group and upgroup shapes in a worksheet.

-
+

Setup

-
+

Try it out

-
+

Try it out

Select an image file (JPEG or PNG).

@@ -127,15 +127,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/44-shape/shape-lines.yaml b/samples/excel/44-shape/shape-lines.yaml index 8fd8207fe..58577bab0 100644 --- a/samples/excel/44-shape/shape-lines.yaml +++ b/samples/excel/44-shape/shape-lines.yaml @@ -7,17 +7,17 @@ api_set: ExcelApi: '1.9' script: content: |- - $("#setup").click(() => tryCatch(setup)); - $("#createShapes").click(() => tryCatch(createShapes)); - $("#addStraightLine").click(() => tryCatch(addStraightLine)); - $("#addCurvedLine").click(() => tryCatch(addCurvedLine)); - $("#arrowLine").click(() => tryCatch(arrowLine)); - $("#diamondLine").click(() => tryCatch(diamondLine)); - $("#connectStraightLine").click(() => tryCatch(connectStraightLine)); - $("#disconnectStraightLine").click(() => tryCatch(disconnectStraightLine)); - $("#connectCurvedLine").click(() => tryCatch(connectCurvedLine)); - $("#disconnectCurvedLine").click(() => tryCatch(disconnectCurvedLine)); - $("#deleteLines").click(() => tryCatch(deleteLines)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("createShapes").addEventListener("click", () => tryCatch(createShapes)); + document.getElementById("addStraightLine").addEventListener("click", () => tryCatch(addStraightLine)); + document.getElementById("addCurvedLine").addEventListener("click", () => tryCatch(addCurvedLine)); + document.getElementById("arrowLine").addEventListener("click", () => tryCatch(arrowLine)); + document.getElementById("diamondLine").addEventListener("click", () => tryCatch(diamondLine)); + document.getElementById("connectStraightLine").addEventListener("click", () => tryCatch(connectStraightLine)); + document.getElementById("disconnectStraightLine").addEventListener("click", () => tryCatch(disconnectStraightLine)); + document.getElementById("connectCurvedLine").addEventListener("click", () => tryCatch(connectCurvedLine)); + document.getElementById("disconnectCurvedLine").addEventListener("click", () => tryCatch(disconnectCurvedLine)); + document.getElementById("deleteLines").addEventListener("click", () => tryCatch(deleteLines)); async function addStraightLine() { await Excel.run(async (context) => { @@ -161,10 +161,10 @@ script: language: typescript template: content: |- -

+

This sample shows how to create and modify line shapes.

-
+

Setup

-
+

Try it out

-
+

Try it out

-
+

Try it out

- -
+

Try it out

Press the following buttons in order, so rows and columns of appropriate sizes are added.

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -165,15 +163,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/46-table/convert-range-to-table.yaml b/samples/excel/46-table/convert-range-to-table.yaml index 1e7924e1b..2476e7886 100644 --- a/samples/excel/46-table/convert-range-to-table.yaml +++ b/samples/excel/46-table/convert-range-to-table.yaml @@ -7,9 +7,9 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#convert-range-to-table").click(() => tryCatch(convertRangeToTable)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("convert-range-to-table").addEventListener("click", () => tryCatch(convertRangeToTable)); async function convertRangeToTable() { await Excel.run(async (context) => { @@ -59,19 +59,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to convert a range to a table.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -91,15 +89,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/46-table/create-table.yaml b/samples/excel/46-table/create-table.yaml index ab0340392..bca2b65b2 100644 --- a/samples/excel/46-table/create-table.yaml +++ b/samples/excel/46-table/create-table.yaml @@ -7,8 +7,8 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#create-table").click(() => tryCatch(createTable)); + content: |- + document.getElementById("create-table").addEventListener("click", () => tryCatch(createTable)); async function createTable() { await Excel.run(async (context) => { @@ -51,12 +51,11 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to create a table.

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -76,15 +75,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/46-table/filter-data.yaml b/samples/excel/46-table/filter-data.yaml index 229a37783..d0efc48ee 100644 --- a/samples/excel/46-table/filter-data.yaml +++ b/samples/excel/46-table/filter-data.yaml @@ -7,10 +7,10 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#filter-table").click(() => tryCatch(filterTable)); - $("#clear-filters").click(() => tryCatch(clearFilters)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("filter-table").addEventListener("click", () => tryCatch(filterTable)); + document.getElementById("clear-filters").addEventListener("click", () => tryCatch(clearFilters)); async function filterTable() { await Excel.run(async (context) => { @@ -87,19 +87,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to filter the data in a table using different filter types.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -122,15 +120,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/46-table/formatting.yaml b/samples/excel/46-table/formatting.yaml index a40833fc5..1e40a5350 100644 --- a/samples/excel/46-table/formatting.yaml +++ b/samples/excel/46-table/formatting.yaml @@ -7,9 +7,9 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#format-table").click(() => tryCatch(formatTable)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("format-table").addEventListener("click", () => tryCatch(formatTable)); async function formatTable() { await Excel.run(async (context) => { @@ -66,19 +66,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to format the different components of a table.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -98,15 +96,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/46-table/get-data-from-table.yaml b/samples/excel/46-table/get-data-from-table.yaml index 3b48ea6df..591ba0d07 100644 --- a/samples/excel/46-table/get-data-from-table.yaml +++ b/samples/excel/46-table/get-data-from-table.yaml @@ -7,9 +7,9 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#get-data-from-table").click(() => tryCatch(getData)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("get-data-from-table").addEventListener("click", () => tryCatch(getData)); async function getData() { await Excel.run(async (context) => { @@ -79,29 +79,25 @@ script: } language: typescript template: - content: |+ -
+ content: |- +

This sample shows how to get data from a table and write it to the sheet.

- -
+

Set up

- -
+

Try it out

- - language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -113,15 +109,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/46-table/get-visible-range-of-a-filtered-table.yaml b/samples/excel/46-table/get-visible-range-of-a-filtered-table.yaml index c719c7902..23eb4f02c 100644 --- a/samples/excel/46-table/get-visible-range-of-a-filtered-table.yaml +++ b/samples/excel/46-table/get-visible-range-of-a-filtered-table.yaml @@ -7,11 +7,11 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: |+ - $("#create-table").click(() => tryCatch(createTable)); - $("#filter-table").click(() => tryCatch(filterTable)); - $("#get-range").click(() => tryCatch(getRange)); - $("#get-visible-range").click(() => tryCatch(getVisibleRange)); + content: |- + document.getElementById("create-table").addEventListener("click", () => tryCatch(createTable)); + document.getElementById("filter-table").addEventListener("click", () => tryCatch(filterTable)); + document.getElementById("get-range").addEventListener("click", () => tryCatch(getRange)); + document.getElementById("get-visible-range").addEventListener("click", () => tryCatch(getVisibleRange)); async function getVisibleRange() { await Excel.run(async (context) => { @@ -94,15 +94,13 @@ script: console.error(error); } } - language: typescript template: - content: |+ -
+ content: |- +

This sample shows how to filter the data in a table using different filter types.

- -
+

Set up

- -
+

Try it out

- language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -136,15 +132,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/46-table/import-json-data.yaml b/samples/excel/46-table/import-json-data.yaml index 937fa71bb..70d69c39f 100644 --- a/samples/excel/46-table/import-json-data.yaml +++ b/samples/excel/46-table/import-json-data.yaml @@ -7,8 +7,8 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#import-json-data").click(() => tryCatch(importJsonData)); + content: |- + document.getElementById("import-json-data").addEventListener("click", () => tryCatch(importJsonData)); async function importJsonData() { await Excel.run(async (context) => { @@ -113,21 +113,19 @@ script: } language: typescript template: - content: |+ -
+ content: |- +

This sample shows how to import json data into a new table.

- -
+

Try it out

- language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -139,15 +137,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/46-table/resize-table.yaml b/samples/excel/46-table/resize-table.yaml index 999354183..2b15b90cd 100644 --- a/samples/excel/46-table/resize-table.yaml +++ b/samples/excel/46-table/resize-table.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelAPI: '1.13' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#resize-table").click(() => tryCatch(resizeTable)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("resize-table").addEventListener("click", () => tryCatch(resizeTable)); async function resizeTable() { await Excel.run(async (context) => { @@ -64,18 +64,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to resize a table.

- -
+

Set up

- -
+

Try it out

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -105,15 +103,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/50-workbook/create-get-change-delete-settings.yaml b/samples/excel/50-workbook/create-get-change-delete-settings.yaml index 6c20d2a05..3797bcda7 100644 --- a/samples/excel/50-workbook/create-get-change-delete-settings.yaml +++ b/samples/excel/50-workbook/create-get-change-delete-settings.yaml @@ -1,16 +1,16 @@ order: 2 id: excel-settings-create-get-change-delete-settings name: Add-in settings -description: 'Creates, gets, changes, and deletes settings that are unique to the specific workbook and add-in combination.' +description: Creates, gets, changes, and deletes settings that are unique to the specific workbook and add-in combination. author: OfficeDev host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#create-setting").click(() => tryCatch(createSetting)); - $("#change-setting").click(() => tryCatch(changeSetting)); - $("#delete-setting").click(() => tryCatch(deleteSetting)); + content: |- + document.getElementById("create-setting").addEventListener("click", () => tryCatch(createSetting)); + document.getElementById("change-setting").addEventListener("click", () => tryCatch(changeSetting)); + document.getElementById("delete-setting").addEventListener("click", () => tryCatch(deleteSetting)); async function createSetting() { await Excel.run(async (context) => { @@ -74,11 +74,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to create, get, change, and delete settings in the workbook.

- -
+

Try it out

Press the button to create and display a setting.

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -107,15 +106,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/50-workbook/create-workbook.yaml b/samples/excel/50-workbook/create-workbook.yaml index 01840918a..bd56088c4 100644 --- a/samples/excel/50-workbook/create-workbook.yaml +++ b/samples/excel/50-workbook/create-workbook.yaml @@ -1,15 +1,15 @@ order: 4 id: excel-workbook-create-workbook name: Create workbook -description: 'Creates a new, empty workbook and creates a new workbook by copying an existing one.' +description: Creates a new, empty workbook and creates a new workbook by copying an existing one. author: OfficeDev host: EXCEL api_set: ExcelApi: '1.8' script: - content: | - $("#create-new-blank-workbook").click(() => tryCatch(createBlankWorkbook)); - $("#file").change(() => tryCatch(createWorkbookFromExisting)); + content: |- + document.getElementById("create-new-blank-workbook").addEventListener("click", () => tryCatch(createBlankWorkbook)); + document.getElementById("file").addEventListener("change", () => tryCatch(createWorkbookFromExisting)); async function createBlankWorkbook() { await Excel.run(async (context) => { @@ -18,7 +18,7 @@ script: } async function createWorkbookFromExisting() { - const myFile = document.getElementById("file"); + const myFile = document.getElementById("file") as HTMLInputElement; const reader = new FileReader(); reader.onload = ((event) => { @@ -48,11 +48,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to create a new, empty workbook and how to create a new workbook by copying an existing one.

- -
+

Try it out

Create empty workbook

-
+

Try it out

-
+
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -131,15 +131,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/50-workbook/culture-info.yaml b/samples/excel/50-workbook/culture-info.yaml index b7aaaa803..1ba143d4a 100644 --- a/samples/excel/50-workbook/culture-info.yaml +++ b/samples/excel/50-workbook/culture-info.yaml @@ -6,11 +6,11 @@ host: EXCEL api_set: ExcelApi: '1.11' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#display-culture-info").click(() => tryCatch(displayCultureInfo)); - $("#write-decimal").click(() => tryCatch(writeDecimal)); - $("#write-big-number").click(() => tryCatch(writeBigNumber)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("display-culture-info").addEventListener("click", () => tryCatch(displayCultureInfo)); + document.getElementById("write-decimal").addEventListener("click", () => tryCatch(writeDecimal)); + document.getElementById("write-big-number").addEventListener("click", () => tryCatch(writeBigNumber)); async function displayCultureInfo() { await Excel.run(async (context) => { @@ -108,18 +108,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to apply the cultural settings APIs to help normalize data.

- -
+

Setup

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -145,15 +143,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/50-workbook/data-protection.yaml b/samples/excel/50-workbook/data-protection.yaml index 07123e44a..a87a43384 100644 --- a/samples/excel/50-workbook/data-protection.yaml +++ b/samples/excel/50-workbook/data-protection.yaml @@ -6,16 +6,16 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#protect-data-in-worksheet").click(() => tryCatch(protectDataInWorksheet)); - $("#unprotect-data-in-worksheet").click(() => tryCatch(unprotectDataInWorksheet)); - $("#protect-workbook-structure").click(() => tryCatch(protectWorkbookStructure)); - $("#unprotect-workbook-structure").click(() => tryCatch(unprotectWorkbookStructure)); - $("#password-protect-data-in-worksheet").click(() => tryCatch(passwordProtectDataInWorksheet)); - $("#password-unprotect-data-in-worksheet").click(() => tryCatch(passwordUnprotectDataInWorksheet)); - $("#password-protect-workbook-structure").click(() => tryCatch(passwordProtectWorkbookStructure)); - $("#password-unprotect-workbook-structure").click(() => tryCatch(passwordUnprotectWorkbookStructure)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("protect-data-in-worksheet").addEventListener("click", () => tryCatch(protectDataInWorksheet)); + document.getElementById("unprotect-data-in-worksheet").addEventListener("click", () => tryCatch(unprotectDataInWorksheet)); + document.getElementById("protect-workbook-structure").addEventListener("click", () => tryCatch(protectWorkbookStructure)); + document.getElementById("unprotect-workbook-structure").addEventListener("click", () => tryCatch(unprotectWorkbookStructure)); + document.getElementById("password-protect-data-in-worksheet").addEventListener("click", () => tryCatch(passwordProtectDataInWorksheet)); + document.getElementById("password-unprotect-data-in-worksheet").addEventListener("click", () => tryCatch(passwordUnprotectDataInWorksheet)); + document.getElementById("password-protect-workbook-structure").addEventListener("click", () => tryCatch(passwordProtectWorkbookStructure)); + document.getElementById("password-unprotect-workbook-structure").addEventListener("click", () => tryCatch(passwordUnprotectWorkbookStructure)); async function protectDataInWorksheet() { await Excel.run(async (context) => { @@ -175,18 +175,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to protect a worksheet's data and the workbook's structure.

- -
+

Set up

- -
+

Try it out

Protect without password

@@ -251,15 +249,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/50-workbook/workbook-built-in-functions.yaml b/samples/excel/50-workbook/workbook-built-in-functions.yaml new file mode 100644 index 000000000..48e46b992 --- /dev/null +++ b/samples/excel/50-workbook/workbook-built-in-functions.yaml @@ -0,0 +1,120 @@ +order: 10 +id: excel-workbook-built-in-function +name: Use built-in Excel functions +description: Use the VLOOKUP and SUM built-in Excel functions. +host: EXCEL +api_set: + ExcelAPI: '1.2' +script: + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("call-vlookup").addEventListener("click", () => tryCatch(callVlookup)); + document.getElementById("nest-functions").addEventListener("click", () => tryCatch(nestFunctions)); + + async function callVlookup() { + await Excel.run(async (context) => { + // This function uses VLOOKUP to find data in the "Wrench" row on the worksheet. + let range = context.workbook.worksheets.getItem("Sample").getRange("A1:D4"); + + // Get the value in the second column in the "Wrench" row. + let unitSoldInNov = context.workbook.functions.vlookup("Wrench", range, 2, false); + unitSoldInNov.load("value"); + + await context.sync(); + console.log(" Number of wrenches sold in November = " + unitSoldInNov.value); + }); + } + + async function nestFunctions() { + await Excel.run(async (context) => { + // This function uses VLOOKUP to find data in the "Wrench" row + // on the worksheet, and then it uses SUM to combine the values. + let range = context.workbook.worksheets.getItem("Sample").getRange("A1:D4"); + + // Get the values in the second, third, and fourth columns in the "Wrench" row, + // and combine those values with SUM. + let sumOfTwoLookups = context.workbook.functions.sum( + context.workbook.functions.vlookup("Wrench", range, 2, false), + context.workbook.functions.vlookup("Wrench", range, 3, false), + context.workbook.functions.vlookup("Wrench", range, 4, false) + ); + sumOfTwoLookups.load("value"); + + await context.sync(); + console.log(" Number of wrenches sold in November, December, and January = " + sumOfTwoLookups.value); + }); + } + + async function setup() { + await Excel.run(async (context) => { + context.workbook.worksheets.getItemOrNullObject("Sample").delete(); + const sheet = context.workbook.worksheets.add("Sample"); + + const expensesTable = sheet.tables.add("A1:D1", true /*hasHeaders*/); + expensesTable.getHeaderRowRange().values = [["Product", "November", "December", "January"]]; + + expensesTable.rows.add(null /*add at the end*/, [ + ["Hammer", "23", "18", "17"], + ["Wrench", "12", "11", "14"], + ["Saw", "5", "15", "19"] + ]); + + sheet.getUsedRange().format.autofitColumns(); + sheet.getUsedRange().format.autofitRows(); + sheet.getRange("A1").select(); + sheet.activate(); + + await context.sync(); + }); + } + + /** Default helper for invoking an action and handling errors. */ + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +

+

This sample shows how to use and nest the built-in Excel functions VLOOKUP and SUM. The sample uses VLOOKUP to return data, and then it uses SUM to combine data returned by VLOOKUP.

+
+
+

Setup

+ +

Try it out

+

Use VLOOKUP to return the number of wrenches sold in November.

+ +

Use VLOOKUP to find the number of wrenches sold in November, December, and January, and then use SUM to combine the three values.

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/50-workbook/workbook-calculation.yaml b/samples/excel/50-workbook/workbook-calculation.yaml index 8a5c101cc..02235ae2e 100644 --- a/samples/excel/50-workbook/workbook-calculation.yaml +++ b/samples/excel/50-workbook/workbook-calculation.yaml @@ -6,8 +6,14 @@ host: EXCEL api_set: ExcelApi: '1.11' script: - content: | - $("#setup").click(() => tryCatch(setup)); $("#register-onCalculated-handler").click(() => tryCatch(registerOnCalculatedHandler)); $("#recalculate-single").click(() => tryCatch(recalculateSingle)); $("#recalculate-column").click(() => tryCatch(recalculateColumn)); $("#manual-calculations").click(() => tryCatch(switchToManualCalculations)); $("#automatic-calculations").click(() => tryCatch(switchToAutomaticCalculations)); $("#force-calculation").click(() => tryCatch(forceCalculation)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("register-onCalculated-handler").addEventListener("click", () => tryCatch(registerOnCalculatedHandler)); + document.getElementById("recalculate-single").addEventListener("click", () => tryCatch(recalculateSingle)); + document.getElementById("recalculate-column").addEventListener("click", () => tryCatch(recalculateColumn)); + document.getElementById("manual-calculations").addEventListener("click", () => tryCatch(switchToManualCalculations)); + document.getElementById("automatic-calculations").addEventListener("click", () => tryCatch(switchToAutomaticCalculations)); + document.getElementById("force-calculation").addEventListener("click", () => tryCatch(forceCalculation)); async function registerOnCalculatedHandler() { await Excel.run(async (context) => { let sheet = context.workbook.worksheets.getItem("Sample"); @@ -128,20 +134,18 @@ script: language: typescript template: content: |- -
+

This sample shows how to use the calculation APIs.

- -
+

Set up

-
+

Try it out

-

Calculation events

-

Manual calculations

Try switching to manual calculation, then editing the workbook.

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -180,15 +183,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/50-workbook/workbook-get-active-cell.yaml b/samples/excel/50-workbook/workbook-get-active-cell.yaml index 6b56e6c76..10e5df770 100644 --- a/samples/excel/50-workbook/workbook-get-active-cell.yaml +++ b/samples/excel/50-workbook/workbook-get-active-cell.yaml @@ -6,8 +6,8 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#get-active-cell").click(() => tryCatch(run)); + content: |- + document.getElementById("get-active-cell").addEventListener("click", () => tryCatch(run)); async function run() { await Excel.run(async (context) => { @@ -34,12 +34,11 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to get the active cell of the entire workbook.

- -
+

Try it out

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -118,15 +116,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/54-worksheet/add-delete-rename-move-worksheet.yaml b/samples/excel/54-worksheet/add-delete-rename-move-worksheet.yaml index 904c01b51..1425fe93d 100644 --- a/samples/excel/54-worksheet/add-delete-rename-move-worksheet.yaml +++ b/samples/excel/54-worksheet/add-delete-rename-move-worksheet.yaml @@ -1,17 +1,17 @@ order: 2 id: excel-worksheet-add-delete-rename-move-worksheet -name: 'Add, delete, rename, and move worksheet' -description: 'Adds, deletes, renames, and moves a worksheet.' +name: Add, delete, rename, and move worksheet +description: Adds, deletes, renames, and moves a worksheet. author: OfficeDev host: EXCEL api_set: ExcelApi: '1.1' script: - content: | - $("#add-worksheet").click(() => tryCatch(addWorksheet)); - $("#delete-worksheet").click(() => tryCatch(deleteWorksheet)); - $("#rename-worksheet").click(() => tryCatch(renameWorksheet)); - $("#move-worksheet").click(() => tryCatch(moveWorksheet)); + content: |- + document.getElementById("add-worksheet").addEventListener("click", () => tryCatch(addWorksheet)); + document.getElementById("delete-worksheet").addEventListener("click", () => tryCatch(deleteWorksheet)); + document.getElementById("rename-worksheet").addEventListener("click", () => tryCatch(renameWorksheet)); + document.getElementById("move-worksheet").addEventListener("click", () => tryCatch(moveWorksheet)); async function addWorksheet() { await Excel.run(async (context) => { @@ -103,12 +103,11 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to add, delete, rename and change the position of a worksheet.

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -137,15 +136,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/54-worksheet/gridlines.yaml b/samples/excel/54-worksheet/gridlines.yaml index ed691a166..7a25135b1 100644 --- a/samples/excel/54-worksheet/gridlines.yaml +++ b/samples/excel/54-worksheet/gridlines.yaml @@ -7,9 +7,9 @@ host: EXCEL api_set: ExcelApi: '1.8' script: - content: | - $("#hide-gridlines").click(() => tryCatch(hideGridlines)); - $("#show-gridlines").click(() => tryCatch(showGridlines)); + content: |- + document.getElementById("hide-gridlines").addEventListener("click", () => tryCatch(hideGridlines)); + document.getElementById("show-gridlines").addEventListener("click", () => tryCatch(showGridlines)); async function hideGridlines() { await Excel.run(async (context) => { @@ -41,12 +41,11 @@ script: } language: typescript template: - content: |+ -
+ content: |- +

This sample shows how to hide and show gridlines within a worksheet.

- -
+

Try it out

- language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -72,15 +70,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/54-worksheet/list-worksheets.yaml b/samples/excel/54-worksheet/list-worksheets.yaml index 50e56f674..180475d1d 100644 --- a/samples/excel/54-worksheet/list-worksheets.yaml +++ b/samples/excel/54-worksheet/list-worksheets.yaml @@ -7,8 +7,8 @@ host: EXCEL api_set: ExcelApi: '1.1' script: - content: | - $("#list-worksheets").click(() => tryCatch(listWorksheets)); + content: |- + document.getElementById("list-worksheets").addEventListener("click", () => tryCatch(listWorksheets)); async function listWorksheets() { await Excel.run(async (context) => { @@ -40,12 +40,11 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to list the names of the worksheets in the workbook.

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -65,15 +64,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml b/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml index da01e093a..fc9fca872 100644 --- a/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml +++ b/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml @@ -7,10 +7,10 @@ host: EXCEL api_set: ExcelApi: '1.5' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#compare-current-and-previous-year").click(() => tryCatch(compareCurrentWithPreviousTax)); - $("#compare-first-and-last-year").click(() => tryCatch(compareFirstWithMostRecentTaxRate)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("compare-current-and-previous-year").addEventListener("click", () => tryCatch(compareCurrentWithPreviousTax)); + document.getElementById("compare-first-and-last-year").addEventListener("click", () => tryCatch(compareFirstWithMostRecentTaxRate)); async function setup() { await Excel.run(async (context) => { @@ -119,19 +119,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to get a reference to a sheet using its relative worksheet position.

- -
+

Set up

- -
+

Try it out

Select any of the three worksheets for 2015, 1016, or 2017 and press the button to compare the tax due on the current sheet with the previous sheet.

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -156,15 +154,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/54-worksheet/tab-color.yaml b/samples/excel/54-worksheet/tab-color.yaml index 7e2656a1f..ab336da87 100644 --- a/samples/excel/54-worksheet/tab-color.yaml +++ b/samples/excel/54-worksheet/tab-color.yaml @@ -7,11 +7,11 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#set-tab-color-to-hex-color").click(() => tryCatch(setTabColorToHexColor)); - $("#set-tab-color-to-named-color").click(() => tryCatch(setTabColorToNamedColor)); - $("#set-tab-color-to-default-color").click(() => tryCatch(setTabColorToDefaultColor)); - $("#get-tab-color").click(() => tryCatch(getTabColor)); + content: |- + document.getElementById("set-tab-color-to-hex-color").addEventListener("click", () => tryCatch(setTabColorToHexColor)); + document.getElementById("set-tab-color-to-named-color").addEventListener("click", () => tryCatch(setTabColorToNamedColor)); + document.getElementById("set-tab-color-to-default-color").addEventListener("click", () => tryCatch(setTabColorToDefaultColor)); + document.getElementById("get-tab-color").addEventListener("click", () => tryCatch(getTabColor)); async function setTabColorToHexColor() { await Excel.run(async (context) => { @@ -65,11 +65,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to set and get the tab color of a worksheet.

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -101,15 +100,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/54-worksheet/worksheet-auto-filter.yaml b/samples/excel/54-worksheet/worksheet-auto-filter.yaml index b172d97fe..8434addeb 100644 --- a/samples/excel/54-worksheet/worksheet-auto-filter.yaml +++ b/samples/excel/54-worksheet/worksheet-auto-filter.yaml @@ -6,14 +6,14 @@ host: EXCEL api_set: ExcelApi: '1.9' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#add-percent-auto-filter").click(() => tryCatch(addPercentAutoFilter)); - $("#add-custom-auto-filter").click(() => tryCatch(addCustomAutoFilter)); - $("#randomize-data").click(() => tryCatch(randomizeData)); - $("#refresh-auto-filter").click(() => tryCatch(refreshAutoFilter)); - $("#clear-single-auto-filter").click(() => tryCatch(clearSingleAutoFilter)); - $("#remove-all-auto-filters").click(() => tryCatch(removeAllAutoFilters)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("add-percent-auto-filter").addEventListener("click", () => tryCatch(addPercentAutoFilter)); + document.getElementById("add-custom-auto-filter").addEventListener("click", () => tryCatch(addCustomAutoFilter)); + document.getElementById("randomize-data").addEventListener("click", () => tryCatch(randomizeData)); + document.getElementById("refresh-auto-filter").addEventListener("click", () => tryCatch(refreshAutoFilter)); + document.getElementById("clear-single-auto-filter").addEventListener("click", () => tryCatch(clearSingleAutoFilter)); + document.getElementById("remove-all-auto-filters").addEventListener("click", () => tryCatch(removeAllAutoFilters)); async function addPercentAutoFilter() { // This function adds a percentage AutoFilter to the active worksheet @@ -153,18 +153,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to work with an AutoFilter on a worksheet.

- -
+

Setup

- -
+

Try it out

Add two filters. One shows only the top half of sales and the other shows only fruits that end with the letter 'e'.

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -206,15 +204,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/54-worksheet/worksheet-copy.yaml b/samples/excel/54-worksheet/worksheet-copy.yaml index bd11af31b..7053c450a 100644 --- a/samples/excel/54-worksheet/worksheet-copy.yaml +++ b/samples/excel/54-worksheet/worksheet-copy.yaml @@ -6,9 +6,9 @@ host: EXCEL api_set: ExcelApi: '1.7' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#copy-worksheet").click(() => tryCatch(run)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("copy-worksheet").addEventListener("click", () => tryCatch(run)); async function run() { await Excel.run(async (context) => { @@ -66,18 +66,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to copy a worksheet.

- -
+

Set up

- -
+

Try it out

-
+

Try it out

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -171,15 +169,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/54-worksheet/worksheet-page-layout.yaml b/samples/excel/54-worksheet/worksheet-page-layout.yaml index 64c36ead9..46beed753 100644 --- a/samples/excel/54-worksheet/worksheet-page-layout.yaml +++ b/samples/excel/54-worksheet/worksheet-page-layout.yaml @@ -6,15 +6,15 @@ host: EXCEL api_set: ExcelApi: '1.9' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#setPageBreaks").click(() => tryCatch(setPageBreaks)); - $("#center").click(() => tryCatch(center)); - $("#setBlackAndWhite").click(() => tryCatch(setBlackAndWhite)); - $("#setPrintTitleRow").click(() => tryCatch(setPrintTitleRow)); - $("#setPrintArea").click(() => tryCatch(setPrintArea)); - $("#changeOrientation").click(() => tryCatch(changeOrientation)); - $("#setZoom").click(() => tryCatch(setZoom)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("setPageBreaks").addEventListener("click", () => tryCatch(setPageBreaks)); + document.getElementById("center").addEventListener("click", () => tryCatch(center)); + document.getElementById("setBlackAndWhite").addEventListener("click", () => tryCatch(setBlackAndWhite)); + document.getElementById("setPrintTitleRow").addEventListener("click", () => tryCatch(setPrintTitleRow)); + document.getElementById("setPrintArea").addEventListener("click", () => tryCatch(setPrintArea)); + document.getElementById("changeOrientation").addEventListener("click", () => tryCatch(changeOrientation)); + document.getElementById("setZoom").addEventListener("click", () => tryCatch(setZoom)); async function setPageBreaks() { await Excel.run(async (context) => { @@ -145,16 +145,16 @@ script: language: typescript template: content: |- -
+

This sample shows how to change page layout and other settings for printing a worksheet.

-
+

Setup

-
+

Try it out

In Excel, choose View > Page Layout, then observe the page layout changes as you press the following buttons.

@@ -202,15 +202,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/54-worksheet/worksheet-range-cell.yaml b/samples/excel/54-worksheet/worksheet-range-cell.yaml index 176fe8714..95f7ff500 100644 --- a/samples/excel/54-worksheet/worksheet-range-cell.yaml +++ b/samples/excel/54-worksheet/worksheet-range-cell.yaml @@ -1,19 +1,19 @@ order: 7 id: excel-worksheet-worksheet-range-cell name: Get range or cell -description: 'Gets the used range, the entire range of a worksheet, the specified range, and the specified cell.' +description: Gets the used range, the entire range of a worksheet, the specified range, and the specified cell. author: OfficeDev host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); - $("#get-used-range").click(() => tryCatch(getUsedRange)); - $("#get-entire-range").click(() => tryCatch(getEntireRange)); - $("#get-range").click(() => tryCatch(getRange)); - $("#get-cell").click(() => tryCatch(getCell)); + document.getElementById("get-used-range").addEventListener("click", () => tryCatch(getUsedRange)); + document.getElementById("get-entire-range").addEventListener("click", () => tryCatch(getEntireRange)); + document.getElementById("get-range").addEventListener("click", () => tryCatch(getRange)); + document.getElementById("get-cell").addEventListener("click", () => tryCatch(getCell)); async function getUsedRange() { await Excel.run(async (context) => { @@ -101,19 +101,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to get a range or a cell in a worksheet.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -142,15 +140,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/excel/54-worksheet/worksheet-visibility.yaml b/samples/excel/54-worksheet/worksheet-visibility.yaml index 2dafa0639..aeff5bbe7 100644 --- a/samples/excel/54-worksheet/worksheet-visibility.yaml +++ b/samples/excel/54-worksheet/worksheet-visibility.yaml @@ -7,9 +7,9 @@ host: EXCEL api_set: ExcelApi: '1.1' script: - content: | - $("#hide-worksheet").click(() => tryCatch(hideWorksheet)); - $("#unhide-worksheet").click(() => tryCatch(unhideWorksheet)); + content: |- + document.getElementById("hide-worksheet").addEventListener("click", () => tryCatch(hideWorksheet)); + document.getElementById("unhide-worksheet").addEventListener("click", () => tryCatch(unhideWorksheet)); async function hideWorksheet() { await Excel.run(async (context) => { @@ -82,19 +82,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to change the visbility of a worksheet.

- -
+

Set up

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -117,15 +115,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/90-scenarios/currency-converter.yaml b/samples/excel/90-scenarios/currency-converter.yaml index 7e57e9818..1510dc666 100644 --- a/samples/excel/90-scenarios/currency-converter.yaml +++ b/samples/excel/90-scenarios/currency-converter.yaml @@ -7,7 +7,7 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | + content: |- /* * Copyright (c) Riwut Libinuko. All rights reserved. Licensed under the MIT license. */ @@ -17,8 +17,8 @@ script: let tableSetup: Record = {}; - $("#convert").click(() => tryCatch(convert)); - $("#setup").click(() => tryCatch(setupSample)); + document.getElementById("convert").addEventListener("click", () => tryCatch(convert)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setupSample)); /** Main converting function **/ async function convert() { @@ -141,26 +141,23 @@ script: } language: typescript template: - content: | -
+ content: |- +

Simple Currency Converter

- -
+

Simple currency converter shows how to read data from a transaction table, and uses currency converter API to calculate the amount in base currency.

The code also performs table validation and identify if the table has predefined headers. You can try to to rearrange the the column, and see by yourself!

- -
+

Set up

- -
+

Try it out

The currency conversion is provided by exchangeratesapi.io which uses exchange rate data published by the European Central Bank. Click "Convert"

@@ -183,12 +180,8 @@ style: language: css libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - core-js@2.4.1/client/core.min.js - @types/core-js - jquery@3.1.1 - @types/jquery@3.3.1 - moment@2.18.1 - moment-msdate@0.2.2 \ No newline at end of file + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css + moment@2.18.1 + moment-msdate@0.2.2 diff --git a/samples/excel/90-scenarios/multiple-property-set.yaml b/samples/excel/90-scenarios/multiple-property-set.yaml index fc6a4c6b6..9a48bb487 100644 --- a/samples/excel/90-scenarios/multiple-property-set.yaml +++ b/samples/excel/90-scenarios/multiple-property-set.yaml @@ -7,10 +7,10 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#set-multiple-properties-with-object").click(() => tryCatch(setMultiplePropertiesWithObject)); - $("#copy-properties-from-range").click(() => tryCatch(copyPropertiesFromRange)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("set-multiple-properties-with-object").addEventListener("click", () => tryCatch(setMultiplePropertiesWithObject)); + document.getElementById("copy-properties-from-range").addEventListener("click", () => tryCatch(copyPropertiesFromRange)); async function setMultiplePropertiesWithObject() { await Excel.run(async (context) => { @@ -94,19 +94,17 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to format a range.

- -
+

Set up

- -
+

Try it out

- -
+

Performance settings

-
+

Try it out

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -129,18 +127,13 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - core-js@2.4.1/client/core.min.js - @types/core-js + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css - jquery@3.1.1 - @types/jquery@3.3.1 - moment@2.18.1 - moment-msdate@0.2.2 \ No newline at end of file + moment@2.18.1 + moment-msdate@0.2.2 diff --git a/samples/excel/99-just-for-fun/color-wheel.yaml b/samples/excel/99-just-for-fun/color-wheel.yaml index 2bc0828c5..f4a2d1692 100644 --- a/samples/excel/99-just-for-fun/color-wheel.yaml +++ b/samples/excel/99-just-for-fun/color-wheel.yaml @@ -7,9 +7,9 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#wheel").click(wheelGo); - $("#stop").click(wheelStop); + content: |- + document.getElementById("wheel").addEventListener("click", wheelGo); + document.getElementById("stop").addEventListener("click", wheelStop); let isStopped: boolean @@ -111,8 +111,10 @@ script: } language: typescript template: - content: |+ -

Spin the rainbow wheel

+ content: |- +
+

Spin the rainbow wheel

+

- language: html style: - content: | + content: |- h2:not(:first-child) { margin-top: 35px; } @@ -142,15 +143,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/99-just-for-fun/gradient.yaml b/samples/excel/99-just-for-fun/gradient.yaml index d4720d92e..cf94c9c6d 100644 --- a/samples/excel/99-just-for-fun/gradient.yaml +++ b/samples/excel/99-just-for-fun/gradient.yaml @@ -8,15 +8,14 @@ api_set: ExcelApi: '1.4' script: content: |- - initializeColorPickers(); + // Set up the click handler. + document.getElementById("draw-gradient").addEventListener("click", drawGradient); + document.getElementById("random").addEventListener("click", randomizeColors); - // Set up the click handler: - const $drawButton = $("#draw-gradient").click(drawGradient); - $("#random").click(randomizeColors); - - /** Click-handler for drawing the gradient */ + /** Click-handler for drawing the gradient. */ async function drawGradient() { - $drawButton.prop("disabled", true); + const drawButton = document.getElementById("draw-gradient") as HTMLButtonElement; + drawButton.disabled = true; try { await Excel.run(drawGradientHelper); @@ -24,10 +23,10 @@ script: console.log(error); } - $drawButton.prop("disabled", false); + drawButton.disabled = false; } - /** Helper function to do the actual gradient-drawing */ + /** Helper function to do the actual gradient-drawing. */ async function drawGradientHelper(context: Excel.RequestContext) { context.workbook.worksheets.getItemOrNullObject("Gradient").delete(); const sheet = context.workbook.worksheets.add("Gradient"); @@ -40,9 +39,21 @@ script: } }); - let originalSize = parseInt($("#size").val() as string); + let originalSize = parseInt((document.getElementById("size") as HTMLInputElement).value); const colors2D = createColorArray(originalSize); + // Retrieve color values from elements. + const topLeftColor = (document.getElementById("top-left") as HTMLInputElement).value; + const topRightColor = (document.getElementById("top-right") as HTMLInputElement).value; + const bottomLeftColor = (document.getElementById("bottom-left") as HTMLInputElement).value; + const bottomRightColor = (document.getElementById("bottom-right") as HTMLInputElement).value; + + // Convert HEX colors to RGB using TinyColor. + const topLeftRgb = tinycolor(topLeftColor).toRgb(); + const topRightRgb = tinycolor(topRightColor).toRgb(); + const bottomLeftRgb = tinycolor(bottomLeftColor).toRgb(); + const bottomRightRgb = tinycolor(bottomRightColor).toRgb(); + if (Office.context.requirements.isSetSupported("ExcelApi", "1.9")) { // ExcelApi 1.9 introduced the setCellProperties APIs to efficiently set different properties // across a range without needing to iterate cell-by-cell. @@ -73,21 +84,33 @@ script: } function createColorArray(size: number): string[][] { - // Create a 2D in-memory array to hold the colors + // Create a 2D in-memory array to hold the colors. let colors2D = Array(size); for (let row = 0; row < size; row++) { colors2D[row] = Array(size); } + // Get the color values from the color pickers. + const topLeftColor = (document.getElementById("top-left") as HTMLInputElement).value; + const topRightColor = (document.getElementById("top-right") as HTMLInputElement).value; + const bottomLeftColor = (document.getElementById("bottom-left") as HTMLInputElement).value; + const bottomRightColor = (document.getElementById("bottom-right") as HTMLInputElement).value; + + // Convert HEX to RGB using TinyColor. + const topLeftRgb = tinycolor(topLeftColor).toRgb(); + const topRightRgb = tinycolor(topRightColor).toRgb(); + const bottomLeftRgb = tinycolor(bottomLeftColor).toRgb(); + const bottomRightRgb = tinycolor(bottomRightColor).toRgb(); + const topColors = getColorsArray( - $("#top-left").spectrum("get").toRgb(), - $("#top-right").spectrum("get").toRgb(), + topLeftRgb, + topRightRgb, size ); const bottomColors = getColorsArray( - $("#bottom-left").spectrum("get").toRgb(), - $("#bottom-right").spectrum("get").toRgb(), + bottomLeftRgb, + bottomRightRgb, size ); @@ -101,9 +124,9 @@ script: return colors2D; } - /** Helper function to get an array of colors */ - function getColorsArray(color1: ColorFormats.RGB, color2: ColorFormats.RGB, count: number) { - const result = new Array(count); + /** Helper function to get an array of colors. */ + function getColorsArray(color1, color2, count: number) { + const result = new Array(count); for (let i = 0; i < count; i++) { const fraction = i / (count - 1); result[i] = { @@ -115,58 +138,55 @@ script: return result; } - function initializeColorPickers() { - $("#color-table input[type='text']").spectrum({ - preferredFormat: "rgb", - showInput: true - }); - } - function randomizeColors() { - $("#color-table input[type='text']").each((index, element) => { - $(element).spectrum("set", tinycolor.random().toHexString()); + // Select all color input elements. + const colorInputs = document.querySelectorAll("#color-table input[type='color']"); + + // Iterate through each color input and set a random color. + colorInputs.forEach((input) => { + const randomColor = tinycolor.random().toHexString(); + (input as HTMLInputElement).value = randomColor; }); } language: typescript template: content: |- -

Color configuration

- -
-
Top left
- - - - - - - - - -
-
- Bottom right +
+

Color configuration

+
+
+
+
Top left
+ + + + + + + + + +
+
+ Bottom right +
-
- - - -

Size - (width x height) -

- - - - -
-
- Uses the Spectrum color picker, and the TinyColor libraries. + +

Size + (width x height) +

+ + +
+
+ Uses the TinyColor library. +
-
+
language: html style: content: |- @@ -208,19 +228,10 @@ style: language: css libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css - tinycolor2@1.4.1/tinycolor.js + https://unpkg.com/tinycolor2@1.4.1/tinycolor.js @types/tinycolor2 - spectrum-colorpicker@1.8.0/spectrum.js - spectrum-colorpicker@1.8.0/spectrum.css - @types/spectrum diff --git a/samples/excel/99-just-for-fun/path-finder-game.yaml b/samples/excel/99-just-for-fun/path-finder-game.yaml index b63a27b27..3388e0af9 100644 --- a/samples/excel/99-just-for-fun/path-finder-game.yaml +++ b/samples/excel/99-just-for-fun/path-finder-game.yaml @@ -7,12 +7,11 @@ host: EXCEL api_set: ExcelApi: '1.4' script: - content: | - $("#setup").click(setup); - $("#repeat").click(repeat); - - const $pruneTheGrid = $("#step-by-step").click(pruneTheGrid); - const $allAtOnce = $("#all-at-once").click(allAtOnce); + content: |- + document.getElementById("setup").addEventListener("click", setup); + document.getElementById("repeat").addEventListener("click", repeat); + document.getElementById("step-by-step").addEventListener("click", pruneTheGrid); + document.getElementById("all-at-once").addEventListener("click", allAtOnce); const GRID_ROW_COUNT = 25; const GRID_COLUMN_COUNT = 30; @@ -20,7 +19,7 @@ script: let matrixPrevious: string[][] function setup() { - const density = parseInt($("#density").val() as string) / 100; + const density = parseInt((document.getElementById("density") as HTMLInputElement).value) / 100; const symbol = "\u25cf"; const matrix = new Array(GRID_ROW_COUNT); @@ -32,7 +31,7 @@ script: } matrixPrevious = matrix; - $("#repeat").show(); + document.getElementById("repeat").style.display = "block"; setupHelper(matrix); } @@ -71,7 +70,8 @@ script: } async function pruneTheGrid() { - $pruneTheGrid.attr("disabled", "true"); + const pruneTheGrid = document.getElementById("step-by-step") as HTMLButtonElement; + pruneTheGrid.disabled = true; await tryCatch(() => Excel.run(async (context) => { const grid = context.workbook.worksheets @@ -84,11 +84,12 @@ script: await context.sync(); })); - $pruneTheGrid.removeAttr("disabled"); + pruneTheGrid.disabled = false; } async function allAtOnce() { - $allAtOnce.attr("disabled", "true"); + const allAtOnce = document.getElementById("all-at-once") as HTMLButtonElement; + allAtOnce.disabled = true; let counter = 0; await tryCatch(() => Excel.run(async (context) => { @@ -111,7 +112,7 @@ script: })); console.log("Count of iterations: " + counter); - $allAtOnce.removeAttr("disabled"); + allAtOnce.disabled = false; } @@ -174,13 +175,12 @@ script: } language: typescript template: - content: | -
+ content: |- +

Check whether there is a path from left to right, moving forward one cell at a time (and only straight or diagonally).

-

Set up

-
+
Circle density (%)

-

Find the path:

-
+

- @@ -221,15 +219,9 @@ style: margin-bottom: 0; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/99-just-for-fun/patterns.yaml b/samples/excel/99-just-for-fun/patterns.yaml index ebdf9d0ee..723400183 100644 --- a/samples/excel/99-just-for-fun/patterns.yaml +++ b/samples/excel/99-just-for-fun/patterns.yaml @@ -8,9 +8,9 @@ api_set: ExcelApi: '1.4' script: content: |- - $("#squares").click(() => tryCatch(drawSquares)); - $("#spiral").click(() => tryCatch(drawSpiral)); - $("#decoration").click(() => tryCatch(drawDecoration)); + document.getElementById("squares").addEventListener("click", () => tryCatch(drawSquares)); + document.getElementById("spiral").addEventListener("click", () => tryCatch(drawSpiral)); + document.getElementById("decoration").addEventListener("click", () => tryCatch(drawDecoration)); async function drawSquares() { await Excel.run(async (context) => { @@ -20,7 +20,7 @@ script: sheet.activate(); formatBackground(sheet); - const size = parseInt($("#size").val() as string); + const size = parseInt((document.getElementById("size") as HTMLInputElement).value); for (let i = 0; i < size; i++) { const width = size * 2 - 2 * i; @@ -45,7 +45,7 @@ script: sheet.activate(); formatBackground(sheet); - const size = Math.floor(parseInt($("#size").val() as string) / 2); + const size = Math.floor(parseInt((document.getElementById("size") as HTMLInputElement).value) / 2); for (let i = 0; i < size - 1; i++) { @@ -106,7 +106,7 @@ script: sheet.activate(); formatBackground(sheet); - const size = Math.floor(parseInt($("#size").val() as string) / 2); + const size = Math.floor(parseInt((document.getElementById("size") as HTMLInputElement).value) / 2); for (let i = 0; i < size; i++) { const range1 = sheet.getCell(2 * i + 1, 2 * i + 1).getResizedRange(size - i, size - i); @@ -155,31 +155,27 @@ script: language: typescript template: content: |- -

Draw colorful patterns

- -
+

Draw colorful patterns

+
Choose size:
- -
+


-

-
language: html style: - content: | + content: |- h2:not(:first-child) { margin-top: 35px; } @@ -188,15 +184,9 @@ style: width: 100%; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/excel/99-just-for-fun/tetrominos.yaml b/samples/excel/99-just-for-fun/tetrominos.yaml index 3a0850856..2ca35b401 100644 --- a/samples/excel/99-just-for-fun/tetrominos.yaml +++ b/samples/excel/99-just-for-fun/tetrominos.yaml @@ -8,18 +8,17 @@ api_set: ExcelApi: '1.9' script: content: |- - $("#run").click(() => { - $("#setup").hide(); + document.getElementById("run").addEventListener("click", () => { + document.getElementById("setup").style.display = "none"; tryCatch(run); }); - - $("#selectedFile").change(() => tryCatch(readImageFromFile)); - $("#focusButton").click(() => tryCatch(focus)); + document.getElementById("selectedFile").addEventListener("change", () => tryCatch(readImageFromFile)); + document.getElementById("focusButton").addEventListener("click", () => tryCatch(focus)); let backgroundPicture = getDefaultBackgroundPicture(); function readImageFromFile() { - const myFile = document.getElementById("selectedFile"); + const myFile = document.getElementById("selectedFile") as HTMLInputElement; const reader = new FileReader(); reader.onload = (event) => { @@ -33,7 +32,7 @@ script: } function focus() { - $("#container").focus(); + document.getElementById("container").focus(); } async function run() { @@ -621,10 +620,12 @@ script: } } - await run($("#container")[0], $("#sessionPane")[0]); + const container = document.getElementById("container"); + const sessionPane = document.getElementById("sessionPane"); + await run(container, sessionPane); - $("#container").focus(); - $("#focus").show(); + container.focus(); + document.getElementById("focus").style.display = "block"; }); } @@ -633,7 +634,7 @@ script: try { await callback(); } catch (error) { - $("#setup").show(); + document.getElementById("setup").style.display = "block"; // Note: In a production add-in, you'd want to notify the user through your add-in's UI. console.error(error); } @@ -646,28 +647,27 @@ script: template: content: |-
-
+

This sample lets you repeatedly stack tetrominos, which are represented by Shapes. Select a background image (or leave blank for the default) and Start!. The controls will then be displayed.

- -
+

Select Background Image

-
+

-

language: html style: @@ -784,17 +784,11 @@ style: border: 1px solid black; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js diff --git a/samples/excel/default.yaml b/samples/excel/default.yaml index 10ea5b1db..3198ff5da 100644 --- a/samples/excel/default.yaml +++ b/samples/excel/default.yaml @@ -6,8 +6,8 @@ host: EXCEL api_set: ExcelApi: '1.1' script: - content: | - $("#run").click(() => tryCatch(run)); + content: |- + document.getElementById("run").addEventListener("click", () => tryCatch(run)); async function run() { await Excel.run(async (context) => { @@ -31,7 +31,7 @@ script: } language: typescript template: - content: | + content: |- @@ -49,15 +49,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/onenote/default.yaml b/samples/onenote/default.yaml index 57fbd0e52..0b94d1a3f 100644 --- a/samples/onenote/default.yaml +++ b/samples/onenote/default.yaml @@ -6,8 +6,8 @@ host: ONENOTE api_set: OneNoteApi: '1.1' script: - content: | - $("#run").click(() => tryCatch(run)); + content: |- + document.getElementById("run").addEventListener("click", () => tryCatch(run)); async function run() { await OneNote.run(async (context) => { @@ -29,7 +29,7 @@ script: } language: typescript template: - content: | + content: |- @@ -47,15 +47,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/10-roaming-settings/roaming-settings.yaml b/samples/outlook/10-roaming-settings/roaming-settings.yaml index 527dcca19..0933e6d36 100644 --- a/samples/outlook/10-roaming-settings/roaming-settings.yaml +++ b/samples/outlook/10-roaming-settings/roaming-settings.yaml @@ -1,29 +1,30 @@ id: outlook-roaming-settings-roaming-settings name: Use add-in settings -description: 'Gets, sets, and saves add-in roaming settings' +description: Gets, sets, saves, and removes add-in roaming settings. host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | - $("#get").click(get); - $("#set").click(set); - $("#save").click(save); + content: |- + document.getElementById("get").addEventListener("click", get); + document.getElementById("set").addEventListener("click", set); + document.getElementById("save").addEventListener("click", save); + document.getElementById("remove").addEventListener("click", remove); function get() { - const settingName = $("#settingName").val(); + const settingName = (document.getElementById("settingName") as HTMLInputElement).value; const settingValue = Office.context.roamingSettings.get(settingName); - $("#settingValue").val(settingValue); + (document.getElementById("settingValue") as HTMLInputElement).value = settingValue; console.log(`The value of setting "${settingName}" is "${settingValue}".`); } - + function set() { - const settingName = $("#settingName").val(); - const settingValue = $("#settingValue").val(); + const settingName = (document.getElementById("settingName") as HTMLInputElement).value; + const settingValue = (document.getElementById("settingValue") as HTMLInputElement).value; Office.context.roamingSettings.set(settingName, settingValue); console.log(`Setting "${settingName}" set to value "${settingValue}".`); } - + function save() { // Save settings in the mailbox to make it available in future sessions. Office.context.roamingSettings.saveAsync(function(result) { @@ -34,14 +35,20 @@ script: } }); } + + function remove() { + // Remove the specified setting from the mailbox. + const settingName = (document.getElementById("settingName") as HTMLInputElement).value; + Office.context.roamingSettings.remove(settingName); + console.log(`The "${settingName}" setting has been removed.`); + } language: typescript template: - content: | -
+ content: |- +

This sample shows how to set, save, and get add-in properties that can be accessed the next time the add-in is opened.

- -
+

Try it out

@@ -60,6 +67,9 @@ template: +
language: html style: @@ -75,15 +85,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/outlook/15-item-custom-properties/load-set-get-save.yaml b/samples/outlook/15-item-custom-properties/load-set-get-save.yaml index cf3c2fb7f..b928ad2fa 100644 --- a/samples/outlook/15-item-custom-properties/load-set-get-save.yaml +++ b/samples/outlook/15-item-custom-properties/load-set-get-save.yaml @@ -1,97 +1,114 @@ id: outlook-item-custom-properties-load-set-get-save name: Work with item custom properties -description: 'Gets the custom properties that the add-in placed on the current item, sets a new one, gets it, removes it, and saves all custom properties back to the item.' +description: Gets the custom properties that the add-in placed on the current item, sets a new one, gets it, removes it, and saves all custom properties back to the item. host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | + content: |- let customProps; - $("#load").click(load); - $("#get").click(get); - $("#set").click(set); - $("#remove").click(remove); - $("#save").click(save); - + document.getElementById("load").addEventListener("click", load); + document.getElementById("get").addEventListener("click", get); + document.getElementById("get-all").addEventListener("click", getAll); + document.getElementById("set").addEventListener("click", set); + document.getElementById("remove").addEventListener("click", remove); + document.getElementById("save").addEventListener("click", save); + function load() { - Office.context.mailbox.item.loadCustomPropertiesAsync(function (result) { - if (result.status === Office.AsyncResultStatus.Succeeded) { - console.log("Loaded following custom properties:"); - customProps = result.value; - const dataKey = Object.keys(customProps)[0]; - const data = customProps[dataKey]; - for (let propertyName in data) - { - let propertyValue = data[propertyName]; - console.log(`${propertyName}: ${propertyValue}`); - } - } - else { + Office.context.mailbox.item.loadCustomPropertiesAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { console.error(`loadCustomPropertiesAsync failed with message ${result.error.message}`); + return; } + + customProps = result.value; + console.log("Loaded the CustomProperties object."); }); } function get() { - const propertyName = $("#propertyName").val(); + const propertyName = (document.getElementById("get-property-name") as HTMLInputElement).value; const propertyValue = customProps.get(propertyName); - $("#propertyValue").val(propertyValue); console.log(`The value of custom property "${propertyName}" is "${propertyValue}".`); } + function getAll() { + let allCustomProps; + if (Office.context.requirements.isSetSupported("Mailbox", "1.9")) { + allCustomProps = customProps.getAll(); + } else { + allCustomProps = customProps["rawData"]; + } + + console.log(allCustomProps); + } + function set() { - const propertyName = $("#propertyName").val(); - const propertyValue = $("#propertyValue").val(); + const propertyName = (document.getElementById("set-property-name") as HTMLInputElement).value; + const propertyValue = (document.getElementById("property-value") as HTMLInputElement).value; customProps.set(propertyName, propertyValue); console.log(`Custom property "${propertyName}" set to value "${propertyValue}".`); } function remove() { - const propertyName = $("#propertyName").val(); + const propertyName = (document.getElementById("remove-property-name") as HTMLInputElement).value; customProps.remove(propertyName); console.log(`Custom property "${propertyName}" removed.`); } function save() { - customProps.saveAsync(function(result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { + customProps.saveAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { console.error(`saveAsync failed with message ${result.error.message}`); - } else { - console.log(`Custom properties saved with status: ${result.status}`); + return; } + + console.log(`Custom properties saved with status: ${result.status}`); }); } language: typescript template: - content: | -
-

This sample shows how to set, save, and get add-in's per-item properties that can be accessed the next time the add-in is opened for the same item.

+ content: |- +
+

This sample shows how to set, save, and get the custom per-item properties of an add-in.

- -
-

Try it out

-
- - +
+

Try it out

+

First load the CustomProperties object of the mail item.

+ +
+ +
-
- - +
+ +
- - - - +
+ + +
+ -
@@ -109,15 +126,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/outlook/20-item-body/add-inline-base64-image.yaml b/samples/outlook/20-item-body/add-inline-base64-image.yaml index 5d1b47f05..f2703f677 100644 --- a/samples/outlook/20-item-body/add-inline-base64-image.yaml +++ b/samples/outlook/20-item-body/add-inline-base64-image.yaml @@ -1,57 +1,81 @@ order: 3 id: outlook-item-body-add-inline-base64-image -name: Add inline Base64 image to message or appointment body (Compose) -description: Add an inline Base64 image to the body of a message or appointment being composed. +name: Add inline Base64-encoded image to message or appointment body (Compose) +description: Add an inline Base64-encoded image to the body of a message or appointment being composed. host: OUTLOOK api_set: Mailbox: '1.8' script: - content: | - $("#add-image").click(addImage); + content: |- + document.getElementById("prepend-image").addEventListener("click", prependImage); + document.getElementById("append-image").addEventListener("click", appendImage); + + 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=="; + + function prependImage() { + // Insert 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; + } - function addImage() { - const mailItem = Office.context.mailbox.item; - 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=="; + 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; + } + console.log("Inline Base64-encoded image added to the beginning of the body."); + }) + }); + } + + function appendImage() { // 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("

", `

`); + Office.context.mailbox.item.body.getAsync(Office.CoercionType.Html, (bodyResult) => { + if (bodyResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to get body: ${bodyResult.error.message}`); + return; + } - 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 end of the body. + const options = { isInline: true, asyncContext: bodyResult.value }; + Office.context.mailbox.item.addFileAttachmentFromBase64Async(base64String, "sample.png", options, (attachResult) => { + if (attachResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to attach file: ${attachResult.error.message}`); + return; + } + + let body = attachResult.asyncContext; + body += ''; + + Office.context.mailbox.item.body.setAsync(body, { coercionType: Office.CoercionType.Html }, (setResult) => { + if (setResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to set body: ${setResult.error.message}`); + return; } + + console.log("Inline Base64-encoded image added to the end of the body."); }); - } else { - console.log(bodyResult.error.message); - } + }); }); } language: typescript template: content: |- -

-

This sample adds an inline Base64 image to the body of the message or appointment being composed.

+
+

This sample adds an inline Base64-encoded image to the body of the message or appointment being composed.

Required mode: Compose

- -
+

Try it out

- +
language: html @@ -68,15 +92,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/20-item-body/append-text-on-send.yaml b/samples/outlook/20-item-body/append-text-on-send.yaml index b324ac54c..5c025a7ef 100644 --- a/samples/outlook/20-item-body/append-text-on-send.yaml +++ b/samples/outlook/20-item-body/append-text-on-send.yaml @@ -6,12 +6,12 @@ host: OUTLOOK api_set: Mailbox: '1.9' script: - content: | - $("#append-on-send").click(appendOnSend); + content: |- + document.getElementById("append-on-send").addEventListener("click", appendOnSend); function appendOnSend() { // This snippet appends text to the end of the message or appointment's body once it's sent. - const text = $("#text-field").val(); + const text = (document.getElementById("text-field") as HTMLInputElement).value; // It's recommended to call getTypeAsync and pass its returned value to the options.coercionType parameter of the appendOnSendAsync call. Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { @@ -34,12 +34,11 @@ script: language: typescript template: content: |- -
+

This sample appends text to the end of the message or appointment's body once it's sent.

Required mode: Compose

- -
+

Try it out

Important: To use appendOnSendAsync, you must set AppendOnSend as an extended permission in the ExtendedPermissions manifest element. To learn more about append-on-send and its configuration, see Implement append-on-send in your Outlook add-in.

@@ -65,15 +64,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/20-item-body/get-body-format.yaml b/samples/outlook/20-item-body/get-body-format.yaml index 50621c9f0..47d4cf236 100644 --- a/samples/outlook/20-item-body/get-body-format.yaml +++ b/samples/outlook/20-item-body/get-body-format.yaml @@ -6,8 +6,8 @@ host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | - $("#get-body-format").click(getBodyFormat); + content: |- + document.getElementById("get-body-format").addEventListener("click", getBodyFormat); function getBodyFormat() { // Get the mail item's body format (plain text or HTML) and log it to the console. @@ -23,12 +23,11 @@ script: language: typescript template: content: |- -
+

This sample gets the message or appointment's body format (plain text or HTML).

Required mode: Compose

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -38,15 +38,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/25-item-save-and-close/save.yaml b/samples/outlook/25-item-save-and-close/save.yaml index 77d79ce17..46ee419e8 100644 --- a/samples/outlook/25-item-save-and-close/save.yaml +++ b/samples/outlook/25-item-save-and-close/save.yaml @@ -1,3 +1,4 @@ +order: 3 id: outlook-item-save-and-close-save name: Save the item description: Saves the item (compose mode) @@ -5,8 +6,8 @@ host: OUTLOOK api_set: Mailbox: '1.3' script: - content: | - $("#run").click(run); + content: |- + document.getElementById("run").addEventListener("click", run); function run() { Office.context.mailbox.item.saveAsync(function (result) { @@ -20,12 +21,11 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to save the item in compose mode.

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -45,15 +45,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/30-recipients-and-attendees/get-all-attendees.yaml b/samples/outlook/30-recipients-and-attendees/get-all-attendees.yaml index 9a0206f82..389395766 100644 --- a/samples/outlook/30-recipients-and-attendees/get-all-attendees.yaml +++ b/samples/outlook/30-recipients-and-attendees/get-all-attendees.yaml @@ -7,7 +7,7 @@ api_set: Mailbox: '1.7' script: content: |- - $("#get-attendees").click(getAttendees); + document.getElementById("get-attendees").addEventListener("click", getAttendees); function getAttendees() { // This snippet gets an appointment's required and optional attendees and groups them by their response. @@ -92,12 +92,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to get all appointment attendees and organize them by their response.

Required mode: Appointment Organizer, Appointment Read

- -
+

Try it out

+
+
+
+ +
+

Get all notifications

+

Replace a notification

+

To replace a notification with an informational message, enter the ID of the notification you want to replace in the text field, then select Replace notification.

+

Remove a notification

+

To remove a notification, enter the ID of the notification you want to remove in the text field, then select Remove notification.

language: html @@ -132,15 +190,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/outlook/40-attachments/attachments-compose.yaml b/samples/outlook/40-attachments/attachments-compose.yaml index 1d0765464..cb2133d03 100644 --- a/samples/outlook/40-attachments/attachments-compose.yaml +++ b/samples/outlook/40-attachments/attachments-compose.yaml @@ -1,139 +1,146 @@ id: outlook-attachments-attachments-compose name: Manipulate attachments (Item Compose) -description: 'Adds, gets, and removes attachments from a message or an appointment in Compose mode.' +description: Adds, gets, and removes attachments from a message or an appointment in Compose mode. host: OUTLOOK api_set: - Mailbox: '1.1' + Mailbox: '1.8' script: - content: | - $("#add").click(add); - $("#addItemAttachment").click(addItemAttachment); - $("#addBase64").click(addBase64); - $("#get").click(get); - $("#remove").click(remove); + content: |- + document.getElementById("add").addEventListener("click", add); + document.getElementById("addBase64").addEventListener("click", addBase64); + document.getElementById("get").addEventListener("click", get); + document.getElementById("remove").addEventListener("click", remove); function add() { - const attachmentUrl = $("#attachmentUrl").val(); - Office.context.mailbox.item.addFileAttachmentAsync( - attachmentUrl, - getFileName(attachmentUrl), - { "asyncContext" : { var1: 1, var2: true } }, - function(result) { console.log(result); }); - } - - function addItemAttachment() { - const attachmentItemId = $("#attachmentItemId").val(); - Office.context.mailbox.item.addItemAttachmentAsync( - attachmentItemId, - "My attachment", - { "asyncContext" : { var3: 3, var4: false } }, - function(result) { console.log(result); }); + const attachmentUrl = (document.getElementById("attachmentUrl") as HTMLInputElement).value; + Office.context.mailbox.item.addFileAttachmentAsync( + attachmentUrl, + getFileName(attachmentUrl), + { isInline: false }, + (result) => { + console.log(result); + } + ); } function addBase64() { - base64String = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAACRUlEQVRYw82XzXHbMBCFP2F8tzsQc8Ixyh0zoiuIXIGdCsxUYKqC0B04FdiuwMoM7mGOOIXqQGoAymXhgSX+itJM9kIRFLAP+3YXD5Pdbscx5oxaAIW8Ztr6l2PWmQwF4IyaieP53qdfAqQ8CwBn1JU4vpWhrbxXQA5MZfynANmcDIAzKgcy4FKGXsVJFf3nLgKyBQptfT4KQMRz2N0fcbxqmRMDWXflx0VPnrdArq0vekQ1Dv0UeHZGNebHhwjU8AzwKM43RyZnbAf58Q6ghudeWd0Aus0+5EcMIIRi3beua0D3Nm39BEAx3i7HTK4DEBJn5YxKOnaRA5+ErpMBWMpzDvx1RuXCcxOISlufAjfC7zgAsqsvUvMAD0ApPaEtGi9AIlUzKgJo60tt/SyKRkzLrAXERluf7W1gOICWaMyB386oooOWsIHvXbSoHuUSFovtHqicUVnH3EJoeT0aQEf5/XBGlc6otIOWBXAtPeZkAIJ9Bt6cUU9tZautX2nrk3MACHYr1ZKProKRtDw4o8pzAPjWo+NtpXTTvoteDDg8noDAcwbcRedAkGdFXyk2GEDcegVAFp2gyVDHjRQ4o6q2smoqtR5Hd+qMqtoALCWUUymr1m43QMZfOaMK4C0SrMsDANJ2E5FNcbdbjHC+ENl+H0myJFbLtaq4Rt8dyPBYRQV1E40nMv9rl7xrOw3DGb+Whcqu3i/OM6CUOWvgRlufNmnLYy4m77uJI7AXtdNcTDrU71LEyv7v01/N/ovL6bmu5/8A1tNWZldH0W4AAAAASUVORK5CYII="; - Office.context.mailbox.item.addFileAttachmentFromBase64Async( - base64String, - "logo.png", - { isInline: false }, - function(result) { console.log(result); }); + const base64String = + "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAACRUlEQVRYw82XzXHbMBCFP2F8tzsQc8Ixyh0zoiuIXIGdCsxUYKqC0B04FdiuwMoM7mGOOIXqQGoAymXhgSX+itJM9kIRFLAP+3YXD5Pdbscx5oxaAIW8Ztr6l2PWmQwF4IyaieP53qdfAqQ8CwBn1JU4vpWhrbxXQA5MZfynANmcDIAzKgcy4FKGXsVJFf3nLgKyBQptfT4KQMRz2N0fcbxqmRMDWXflx0VPnrdArq0vekQ1Dv0UeHZGNebHhwjU8AzwKM43RyZnbAf58Q6ghudeWd0Aus0+5EcMIIRi3beua0D3Nm39BEAx3i7HTK4DEBJn5YxKOnaRA5+ErpMBWMpzDvx1RuXCcxOISlufAjfC7zgAsqsvUvMAD0ApPaEtGi9AIlUzKgJo60tt/SyKRkzLrAXERluf7W1gOICWaMyB386oooOWsIHvXbSoHuUSFovtHqicUVnH3EJoeT0aQEf5/XBGlc6otIOWBXAtPeZkAIJ9Bt6cUU9tZautX2nrk3MACHYr1ZKProKRtDw4o8pzAPjWo+NtpXTTvoteDDg8noDAcwbcRedAkGdFXyk2GEDcegVAFp2gyVDHjRQ4o6q2smoqtR5Hd+qMqtoALCWUUymr1m43QMZfOaMK4C0SrMsDANJ2E5FNcbdbjHC+ENl+H0myJFbLtaq4Rt8dyPBYRQV1E40nMv9rl7xrOw3DGb+Whcqu3i/OM6CUOWvgRlufNmnLYy4m77uJI7AXtdNcTDrU71LEyv7v01/N/ovL6bmu5/8A1tNWZldH0W4AAAAASUVORK5CYII="; + Office.context.mailbox.item.addFileAttachmentFromBase64Async( + base64String, + "logo.png", + { isInline: false }, + (result) => { + console.log(result); + } + ); } function get() { - Office.context.mailbox.item.getAttachmentsAsync(function (result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(result.error.message); - } else { - if (result.value.length > 0) { - for (let i = 0; i < result.value.length; i++) { - const attachment = result.value[i]; - console.log("ID: " + attachment.id + "\n" + - "Name: " + attachment.name + "\n" + - "Size: " + attachment.size + "\n" + - "isInline: " + attachment.isInline); - switch (attachment.attachmentType) { - case Office.MailboxEnums.AttachmentType.Cloud: - console.log("Attachment type: Attachment is stored in a cloud location."); - break; - case Office.MailboxEnums.AttachmentType.File: - console.log("Attachment type: Attachment is a file."); - break; - case Office.MailboxEnums.AttachmentType.Item: - console.log("Attachment type: Attachment is an Exchange item."); - break; - } - } - } - else { - console.log("No attachments on this message."); - } + Office.context.mailbox.item.getAttachmentsAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(result.error.message); + return; + } + + if (result.value.length > 0) { + for (let i = 0; i < result.value.length; i++) { + const attachment = result.value[i]; + let attachmentType; + switch (attachment.attachmentType) { + case Office.MailboxEnums.AttachmentType.Cloud: + attachmentType = "Attachment is stored in a cloud location"; + break; + case Office.MailboxEnums.AttachmentType.File: + attachmentType = "Attachment is a file"; + break; + case Office.MailboxEnums.AttachmentType.Item: + attachmentType = "Attachment is an Exchange item"; + break; } - }); + console.log( + "ID: " + + attachment.id + + "\n" + + "Type: " + + attachmentType + + "\n" + + "Name: " + + attachment.name + + "\n" + + "Size: " + + attachment.size + + "\n" + + "isInline: " + + attachment.isInline + ); + } + } else { + console.log("No attachments on this message."); + } + }); } function remove() { - Office.context.mailbox.item.removeAttachmentAsync( - $("#attachmentId").val(), - { asyncContext : null }, - function(result) - { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`${result.error.message}`); - } else { - console.log(`Attachment removed successfully.`); - } - } - ); + Office.context.mailbox.item.removeAttachmentAsync( + (document.getElementById("attachmentId") as HTMLInputElement).value, + (result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(result.error.message); + return; + } + + console.log(`Attachment removed successfully.`); + } + ); } function getFileName(url) { - const lastIndex = url.lastIndexOf('/'); - if (lastIndex >= 0) { - return url.substring(lastIndex + 1); - } - return url; + const lastIndex = url.lastIndexOf("/"); + if (lastIndex >= 0) { + return url.substring(lastIndex + 1); + } + return url; } language: typescript template: - content: | -
-

This sample shows how to add, get, and remove attachments from a message or an appointment in Compose mode.

-

Required mode: Item Compose

+ content: |- +
+

This sample shows how to add, get, and remove attachments from a message or an appointment in Compose mode.

+

Required mode: Item Compose

- -
-

Try it out

-
- - +
+

Try it out

+
+

ADD

+ +
+ +
- -
- - -
- - - -
- - +
+

REMOVE

+
+ +
-
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -145,15 +152,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/outlook/40-attachments/get-attachment-content.yaml b/samples/outlook/40-attachments/get-attachment-content.yaml index 58912cd3b..1e1cc2b27 100644 --- a/samples/outlook/40-attachments/get-attachment-content.yaml +++ b/samples/outlook/40-attachments/get-attachment-content.yaml @@ -5,19 +5,13 @@ host: OUTLOOK api_set: Mailbox: '1.8' script: - content: | - $("#attachment-content-compose").click(getAttachmentContentCompose); - $("#attachment-content-read").click(getAttachmentContentRead); - - const item = Office.context.mailbox.item; + content: |- + document.getElementById("attachment-content-compose").addEventListener("click", getAttachmentContentCompose); + document.getElementById("attachment-content-read").addEventListener("click", getAttachmentContentRead); function getAttachmentContentCompose() { - // Gets the attachments of the current message or appointment in compose mode. - const options = { asyncContext: { currentItem: item } }; - // The getAttachmentsAsync call can only be used in compose mode. - item.getAttachmentsAsync(options, callback); - - function callback(result) { + // Gets the attachments of the current message or appointment in compose mode. The getAttachmentsAsync call can only be used in compose mode. + Office.context.mailbox.item.getAttachmentsAsync((result) => { if (result.status === Office.AsyncResultStatus.Failed) { console.log(result.error.message); return; @@ -30,14 +24,14 @@ script: for (let i = 0; i < result.value.length; i++) { // Log the attachment type and its contents to the console. - result.asyncContext.currentItem.getAttachmentContentAsync(result.value[i].id, handleAttachmentsCallback); + Office.context.mailbox.item.getAttachmentContentAsync(result.value[i].id, handleAttachmentsCallback); } - } + }); } function getAttachmentContentRead() { - // Gets the attachments of the current message or appointment in read mode. - // The item.attachments call can only be used in read mode. + // Gets the attachments of the current message or appointment in read mode. The item.attachments call can only be used in read mode. + const item = Office.context.mailbox.item; const attachments = item.attachments; if (attachments.length <= 0) { console.log("Mail item has no attachments."); @@ -78,12 +72,11 @@ script: language: typescript template: content: |- -
+

This sample gets the attachment content from a message or an appointment in read or compose mode.

Required mode: Compose or Read

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -40,15 +51,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/45-categories/work-with-categories.yaml b/samples/outlook/45-categories/work-with-categories.yaml index 126f70bd0..5c8e29fc7 100644 --- a/samples/outlook/45-categories/work-with-categories.yaml +++ b/samples/outlook/45-categories/work-with-categories.yaml @@ -1,15 +1,15 @@ order: 1 id: outlook-categories-work-with-categories name: Work with item categories -description: 'Gets, adds, and removes categories assigned to the item.' +description: Gets, adds, and removes categories assigned to the item. host: OUTLOOK api_set: Mailbox: '1.8' script: - content: | - $("#get-categories").click(getCategories); - $("#add-categories").click(addCategories); - $("#remove-categories").click(removeCategories); + content: |- + document.getElementById("get-categories").addEventListener("click", getCategories); + document.getElementById("add-categories").addEventListener("click", addCategories); + document.getElementById("remove-categories").addEventListener("click", removeCategories); function getCategories() { Office.context.mailbox.item.categories.getAsync(function(asyncResult) { @@ -78,11 +78,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to get, add, and remove categories assigned to the item.

- -
+

Try it out

-
+
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -61,15 +60,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/55-display-items/display-new-appointment.yaml b/samples/outlook/55-display-items/display-new-appointment.yaml index 6137d2d36..770c12e9a 100644 --- a/samples/outlook/55-display-items/display-new-appointment.yaml +++ b/samples/outlook/55-display-items/display-new-appointment.yaml @@ -6,9 +6,9 @@ host: OUTLOOK api_set: Mailbox: '1.9' script: - content: | - $("#run").click(run); - $("#run-async").click(runAsync); + content: |- + document.getElementById("run").addEventListener("click", run); + document.getElementById("run-async").addEventListener("click", runAsync); function run() { const start = new Date(); @@ -53,12 +53,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to display a new appointment and populate attendees, location, body, and a few other properties.

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -81,15 +80,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/55-display-items/display-new-message.yaml b/samples/outlook/55-display-items/display-new-message.yaml index 66d43f9aa..5aca34788 100644 --- a/samples/outlook/55-display-items/display-new-message.yaml +++ b/samples/outlook/55-display-items/display-new-message.yaml @@ -1,14 +1,14 @@ order: 1 id: outlook-display-items-display-new-message name: Create a new message -description: 'Opens a new message form with a sample content, recipients, and an inline image attachment' +description: Opens a new message form with a sample content, recipients, and an inline image attachment host: OUTLOOK api_set: Mailbox: '1.9' script: - content: | - $("#run").click(run); - $("#run-async").click(runAsync); + content: |- + document.getElementById("run").addEventListener("click", run); + document.getElementById("run-async").addEventListener("click", runAsync); function run() { Office.context.mailbox.displayNewMessageForm({ @@ -20,7 +20,7 @@ script: { type: "file", name: "image.png", - url: "http://www.cutestpaw.com/wp-content/uploads/2011/11/Cute-Black-Dogs-s.jpg", + url: "https://i.imgur.com/9S36xvA.jpg", isInline: true } ] @@ -40,24 +40,23 @@ script: { type: "file", name: "image.png", - url: "http://www.cutestpaw.com/wp-content/uploads/2011/11/Cute-Black-Dogs-s.jpg", + url: "https://i.imgur.com/9S36xvA.jpg", isInline: true } ] }, - function(asyncResult) { + (asyncResult) => { console.log(JSON.stringify(asyncResult)); } ); } language: typescript template: - content: | -
+ content: |- +

This sample shows how to display a new message, populate recipients, subject, and body, and add an inline image attachment.

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -80,15 +79,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/outlook/55-display-items/display-reply-forms.yaml b/samples/outlook/55-display-items/display-reply-forms.yaml index 745772799..1c8d46bfb 100644 --- a/samples/outlook/55-display-items/display-reply-forms.yaml +++ b/samples/outlook/55-display-items/display-reply-forms.yaml @@ -6,11 +6,11 @@ host: OUTLOOK api_set: Mailbox: '1.9' script: - content: | - $("#display-reply-form").click(displayReplyForm); - $("#display-reply-form-async").click(displayReplyFormAsync); - $("#display-reply-all-form").click(displayReplyAllForm); - $("#display-reply-all-form-async").click(displayReplyAllFormAsync); + content: |- + document.getElementById("display-reply-form").addEventListener("click", displayReplyForm); + document.getElementById("display-reply-form-async").addEventListener("click", displayReplyFormAsync); + document.getElementById("display-reply-all-form").addEventListener("click", displayReplyAllForm); + document.getElementById("display-reply-all-form-async").addEventListener("click", displayReplyAllFormAsync); // The async version is only available starting with requirement set 1.9. function displayReplyForm() { @@ -39,11 +39,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to create reply or reply-all messages and populate the body of the reply.

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -73,15 +72,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/55-display-items/display-reply-with-attachments.yaml b/samples/outlook/55-display-items/display-reply-with-attachments.yaml index 3af4cc04a..a8c28a08d 100644 --- a/samples/outlook/55-display-items/display-reply-with-attachments.yaml +++ b/samples/outlook/55-display-items/display-reply-with-attachments.yaml @@ -1,62 +1,191 @@ order: 6 id: outlook-display-items-display-reply-with-attachments -name: 'Create a reply, with attachments' -description: Opens a reply message forms and adds sample attachments. +name: Create a reply with attachments +description: Opens a reply or reply-all message form and adds sample attachments. host: OUTLOOK api_set: Mailbox: '1.9' script: - content: | - $("#run").click(run); - $("#run-async").click(runAsync); + content: |- + document.getElementById("reply").addEventListener("click", reply); + document.getElementById("reply-async").addEventListener("click", replyAsync); + document.getElementById("reply-all").addEventListener("click", replyAll); + document.getElementById("reply-all-async").addEventListener("click", replyAllAsync); + + function reply() { + // Define attachments. + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; - function run() { + // Create the reply with attachments. Office.context.mailbox.item.displayReplyForm({ - htmlBody: "This is a reply with a couple of attachments - an inline image and an item
", - attachments: [ - { type: "file", url: "http://i.imgur.com/9S36xvA.jpg", name: "dog.jpg", isInline: true }, - { type: "item", itemId: Office.context.mailbox.item.itemId, name: "test_email.msg" } - ], - options: { asyncContext: null }, - callback: function(result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment], + callback: (result) => { + if (result.status === Office.AsyncResultStatus.Failed) { console.error(`Action failed with message ${result.error.message}`); + return; } + + console.log("Created a reply with attachments."); } }); } - function runAsync() { - // The async version is only available starting with requirement set 1.9, - // and provides a callback when the new appointment form has been created. + function replyAll() { + // Define attachments. + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + // Create the reply with attachments. + Office.context.mailbox.item.displayReplyAllForm({ + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment], + callback: (result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + + console.log("Created a reply-all form with attachments."); + } + }); + } + + function replyAsync() { + // Define attachments. + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + // The async version was introduced in requirement set 1.9. + // It provides a callback when the new appointment form has been created. Office.context.mailbox.item.displayReplyFormAsync( { - htmlBody: "This is a reply with a couple of attachments - an inline image and an item
", - attachments: [ - { type: "file", url: "http://i.imgur.com/9S36xvA.jpg", name: "dog.jpg", isInline: true }, - { type: "item", itemId: Office.context.mailbox.item.itemId, name: "test_email.msg" } - ] + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment] }, - function(asyncResult) { - console.log(JSON.stringify(asyncResult)); + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${asyncResult.error.message}`); + return; + } + + console.log("Created reply with attachments."); + } + ); + } + + function replyAllAsync() { + // Define attachments. + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + // The async version was introduced in requirement set 1.9. + // It provides a callback when the new appointment form has been created. + Office.context.mailbox.item.displayReplyAllFormAsync( + { + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment] + }, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${asyncResult.error.message}`); + return; + } + + console.log("Created a reply-all form with attachments."); } ); } language: typescript template: content: |- -
+

This sample shows how to create a reply message and add an inline image attachment and an item attachment.

+

Required mode: Compose

- -
+

Try it out

- + + + -
language: html style: @@ -72,15 +201,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/60-sensitivity-label/sensitivity-label.yaml b/samples/outlook/60-sensitivity-label/sensitivity-label.yaml index c196d0ec7..8b0db6aaa 100644 --- a/samples/outlook/60-sensitivity-label/sensitivity-label.yaml +++ b/samples/outlook/60-sensitivity-label/sensitivity-label.yaml @@ -6,9 +6,9 @@ host: OUTLOOK api_set: Mailbox: '1.13' script: - content: | - $("#get-sensitivity-label").click(getCurrentSensitivityLabel); - $("#set-sensitivity-label").click(setSensitivityLabel); + content: |- + document.getElementById("get-sensitivity-label").addEventListener("click", getCurrentSensitivityLabel); + document.getElementById("set-sensitivity-label").addEventListener("click", setSensitivityLabel); function getCurrentSensitivityLabel() { // This snippet gets the current mail item's sensitivity label. @@ -59,12 +59,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to get and set the sensitivity label on a message or appointment being composed. To learn more about the sensitivity label API, see Manage the sensitivity label of your message or appointment in compose mode.

Required mode: Compose

- -
+

Try it out

- - +
+

Try it out on a message or appointment from a shared folder or shared mailbox.

+
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -137,15 +52,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/70-mime-headers/get-internet-headers-message-read.yaml b/samples/outlook/70-mime-headers/get-internet-headers-message-read.yaml index abd3744ce..12d2e2a8a 100644 --- a/samples/outlook/70-mime-headers/get-internet-headers-message-read.yaml +++ b/samples/outlook/70-mime-headers/get-internet-headers-message-read.yaml @@ -2,23 +2,24 @@ id: outlook-mime-headers-get-internet-headers-message-read name: Get internet headers description: Gets internet headers on a message in Read mode. host: OUTLOOK -api_set: {} +api_set: + Mailbox: '1.8' script: - content: | - $("#run").click(run); + content: |- + document.getElementById("run").addEventListener("click", run); function run() { Office.context.mailbox.item.getAllInternetHeadersAsync(function (asyncResult) { if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { console.log("Internet headers received successfully"); - if (asyncResult.value.match(/x-preferred-fruit:.*/gim)) { - console.log("Sender's preferred fruit: " + asyncResult.value.match(/x-preferred-fruit:.*/gim)[0].slice(19)); + if (asyncResult.value.match(/preferred-fruit:.*/gim)) { + console.log("Sender's preferred fruit: " + asyncResult.value.match(/preferred-fruit:.*/gim)[0].slice(17)); } else { console.log("Didn't receive header with sender's preferred fruit"); } - if (asyncResult.value.match(/x-preferred-vegetable:.*/gim)) { + if (asyncResult.value.match(/preferred-vegetable:.*/gim)) { console.log( - "Sender's preferred vegetable: " + asyncResult.value.match(/x-preferred-vegetable:.*/gim)[0].slice(23) + "Sender's preferred vegetable: " + asyncResult.value.match(/preferred-vegetable:.*/gim)[0].slice(21) ); } else { console.log("Didn't receive header with sender's preferred vegetable"); @@ -36,11 +37,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to get internet headers on a message in Read mode.

Required mode: Message Read

-
+

Try it out

- -
- language: html -style: - content: | - section.samples { - margin-top: 20px; - } - - section.samples .ms-Button, section.setup .ms-Button { - display: block; - margin-bottom: 5px; - margin-left: 20px; - min-width: 80px; - } - language: css -libraries: | - https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 diff --git a/samples/outlook/75-entities-and-regex-matches/contextual.yaml b/samples/outlook/75-entities-and-regex-matches/contextual.yaml deleted file mode 100644 index ab5a9593b..000000000 --- a/samples/outlook/75-entities-and-regex-matches/contextual.yaml +++ /dev/null @@ -1,89 +0,0 @@ -id: outlook-entities-and-regex-matches-contextual -name: 'Entities and Regex matches (Item Read, contextual)' -description: Gets extracted entities and regex matches when the add-in is opened as a contextual add-in. -host: OUTLOOK -api_set: - Mailbox: '1.1' -script: - content: | - $("#getFilteredEntitiesByName").click(getFilteredEntitiesByName); - $("#getRegExMatches").click(getRegExMatches); - $("#getRegExMatchesByName").click(getRegExMatchesByName); - - function getFilteredEntitiesByName() { - // This API would only work when you click on highlighted physical address that has the word "Way" in it. - console.log(Office.context.mailbox.item.getFilteredEntitiesByName("sampleFilterName")); - } - - function getRegExMatches() { - // This API would only work when you click on highlighted word "ScriptLab". - console.log(Office.context.mailbox.item.getRegExMatches()); - } - - function getRegExMatchesByName() { - // This API would only work when you click on highlighted word "ScriptLab". - console.log(Office.context.mailbox.item.getRegExMatchesByName("sampleRegexName")); - } - - /* - This add-in declares extension point manifest rules copied below. To see it activated contextually - for address entity, try running it on an email that has "1 Microsoft Way, Redmond, WA 98052" in its content; - for regex match, try running it on an email that has "ScriptLab" in its content. - - Note: The following only applies when your add-in uses an XML manifest. Entities and contextual add-ins aren't supported when a Teams manifest for Office Add-ins (preview)(https://learn.microsoft.com/office/dev/add-ins/develop/json-manifest-overview) is in use. - - - - - - - - */ - language: typescript -template: - content: | -
-

This sample shows how to get extracted entities and regex matches.

-

Note: Entities and contextual add-ins only support the use of an XML manifest. These features aren't supported when your add-in uses a - Teams manifest for Office Add-ins (preview).

-

Required mode: Item Read, contextual add-in

-
- -
-

Tip: Try this out as a contextual add-in.

- - - -
- language: html -style: - content: | - section.samples { - margin-top: 20px; - } - - section.samples .ms-Button, section.setup .ms-Button { - display: block; - margin-bottom: 5px; - margin-left: 20px; - min-width: 80px; - } - language: css -libraries: | - https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 diff --git a/samples/outlook/75-entities-and-regex-matches/selected.yaml b/samples/outlook/75-entities-and-regex-matches/selected.yaml deleted file mode 100644 index e2f622e5d..000000000 --- a/samples/outlook/75-entities-and-regex-matches/selected.yaml +++ /dev/null @@ -1,124 +0,0 @@ -id: outlook-entities-and-regex-matches-selected -name: 'Selected entities and Regex matches (Item Read, contextual)' -description: Gets selected entities and regex matches. -host: OUTLOOK -api_set: - Mailbox: '1.6' -script: - content: | - $("#getSelectedEntities").click(getSelectedEntities); - $("#getSelectedRegExMatches").click(getSelectedRegExMatches); - - function getSelectedEntities() { - const entities = Office.context.mailbox.item.getSelectedEntities(); - let entityTypesFound = 0; - if (entities.addresses.length > 0) { - console.warn("physical addresses: "); - console.log(entities.addresses); - entityTypesFound++; - } - if (entities.contacts.length > 0) { - console.warn("contacts: "); - entities.contacts.forEach(function (contact) { console.log(contact.personName); }) - entityTypesFound++; - } - if (entities.emailAddresses.length > 0) { - console.warn("email addresses: "); - console.log(entities.emailAddresses); - entityTypesFound++; - } - if (entities.meetingSuggestions.length > 0) { - console.warn("meetings suggestions: "); - entities.meetingSuggestions.forEach(function (meetingSuggestion) { console.log(meetingSuggestion.meetingString); }) - entityTypesFound++; - } - if (entities.phoneNumbers.length > 0) { - console.warn("phone numbers: "); - entities.phoneNumbers.forEach(function (phoneNumber) { console.log(phoneNumber.originalPhoneString); }) - entityTypesFound++; - } - if (entities.taskSuggestions.length > 0) { - console.warn("task suggestions: "); - entities.taskSuggestions.forEach(function (taskSuggestion) { console.log(taskSuggestion.taskString); }) - entityTypesFound++; - } - if (entities.urls.length > 0) { - console.warn("URLs: "); - console.log(entities.urls); - entityTypesFound++; - } - if (entityTypesFound == 0) - { - console.error("Open add-in by clicking on a highlighted entity, for this API to return something useful."); - } - } - - function getSelectedRegExMatches() { - const matches = Office.context.mailbox.item.getSelectedRegExMatches(); - if (matches) { - console.log(matches); - } - else { - console.error("Open add-in by clicking on a highlighted regex match, for this API to return something useful."); - } - } - - /* - This add-in declares extension point manifest rules copied below. To see it activated contextually - for address entity, try running it on an email that has "1 Microsoft Way, Redmond, WA 98052" in its content; - for regex match, try running it on an email that has "ScriptLab" in its content. - - Note: The following only applies when your add-in uses an XML manifest. Entities and contextual add-ins aren't supported when a Teams manifest for Office Add-ins (preview)(https://learn.microsoft.com/office/dev/add-ins/develop/json-manifest-overview) is in use. - - - - - - - - */ - language: typescript -template: - content: | -
-

This sample shows how to get selected entities and regex matches.

-

Note: Entities and contextual add-ins only support the use of an XML manifest. These features aren't supported when your add-in uses a - Teams manifest for Office Add-ins (preview).

-

Required mode: Item Read

-
- -
-

Tip: Try this out as a contextual add-in.

- - -
- language: html -style: - content: | - section.samples { - margin-top: 20px; - } - - section.samples .ms-Button, section.setup .ms-Button { - display: block; - margin-bottom: 5px; - margin-left: 20px; - min-width: 80px; - } - language: css -libraries: | - https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 diff --git a/samples/outlook/75-regex-matches/contextual.yaml b/samples/outlook/75-regex-matches/contextual.yaml new file mode 100644 index 000000000..4be7a3f0a --- /dev/null +++ b/samples/outlook/75-regex-matches/contextual.yaml @@ -0,0 +1,85 @@ +id: outlook-regex-matches-contextual +name: Get regex matches (Item Read, contextual) +description: Gets regex matches when the add-in is opened as a contextual add-in. +host: OUTLOOK +api_set: + Mailbox: '1.6' +script: + content: |- + document.getElementById("getRegExMatches").addEventListener("click", getRegExMatches); + document.getElementById("getRegExMatchesByName").addEventListener("click", getRegExMatchesByName); + document.getElementById("getSelectedRegExMatches").addEventListener("click", getSelectedRegExMatches); + + function getRegExMatches() { + // This API only works when you click on the highlighted word "ScriptLab". + console.log(Office.context.mailbox.item.getRegExMatches()); + } + + function getRegExMatchesByName() { + // This API only works when you click on the highlighted word "ScriptLab". + console.log(Office.context.mailbox.item.getRegExMatchesByName("sampleRegexName")); + } + + function getSelectedRegExMatches() { + const matches = Office.context.mailbox.item.getSelectedRegExMatches(); + if (matches) { + console.log(matches); + } else { + console.error("Open add-in by clicking on a highlighted regex match, for this API to return something useful."); + } + } + + /* This add-in declares extension point manifest rules copied below. + For regex match, try running it on an email that has "ScriptLab" in its content. + Note: The following only applies when your add-in uses an XML manifest. Contextual add-ins aren't supported when a unified app manifest for Microsoft 365 (https://learn.microsoft.com/office/dev/add-ins/develop/unified-manifest-overview) is in use. + + + + + + */ + language: typescript +template: + content: |- +
+

This sample shows how to get regex matches.

+

Note: Contextual add-ins only support the use of an XML manifest. This feature isn't supported when your + add-in uses a + unified app manifest + for Microsoft 365.

+

Required mode: Item Read, contextual add-in

+
+
+

Tip: Try this out as a contextual add-in.

+ + + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/outlook/80-events/drag-drop-item.yaml b/samples/outlook/80-events/drag-drop-item.yaml new file mode 100644 index 000000000..7fb596045 --- /dev/null +++ b/samples/outlook/80-events/drag-drop-item.yaml @@ -0,0 +1,72 @@ +id: outlook-events-drag-drop-item +name: Drag and drop an item into the task pane +description: Handles the drag-and-drop event when a user drags and drops messages and file attachments into the add-in task pane. +host: OUTLOOK +api_set: + Mailbox: '1.5' +script: + content: | + Office.onReady(() => { + dragAndDropEventHandler(event); + }); + + function dragAndDropEventHandler(event) { + Office.context.mailbox.addHandlerAsync(Office.EventType.DragAndDropEvent, (event) => { + console.log(`Event type: ${event.type}`); + + const eventData = event.dragAndDropEventData; + console.log(`x-coordinate: ${eventData.pageX}, y-coordinate: ${eventData.pageY}`); + + if (eventData.type == "drop") { + console.log("Items dropped into task pane."); + const files = eventData.dataTransfer.files; + files.forEach((file) => { + const content = file.fileContent; + const name = file.name; + const fileType = file.type; + console.log(`File name: ${name}`); + console.log(`File type: ${fileType}`); + console.log(`Contents: ${content.text().then((text) => { console.log(text); })}`); + }); + } + }); + } + language: typescript +template: + content: |- +
+

Drag and drop messages and file attachments into the add-in task pane.

+

To learn more about the drag-and-drop feature, see Drag and drop messages and + attachments into the task pane of an Outlook add-in.

+

Required mode: Compose or Read

+

Supported Outlook clients: Outlook on the web and the new Outlook on Windows

+
+
+

Try it out

+
    +
  1. Drag a message or file attachment from your mailbox to the task pane. As you drag the item across the task pane, the event name and the coordinates of your mouse pointer are displayed in the console.
  2. +
  3. Drop the message or file attachment into the task pane. The properties + of the dropped item are displayed in the console.
  4. +
+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/outlook/85-tokens-and-service-calls/basic-rest-cors.yaml b/samples/outlook/85-tokens-and-service-calls/basic-rest-cors.yaml deleted file mode 100644 index 47c43946c..000000000 --- a/samples/outlook/85-tokens-and-service-calls/basic-rest-cors.yaml +++ /dev/null @@ -1,66 +0,0 @@ -order: 5 -id: outlook-tokens-and-service-calls-basic-rest-cors -name: Get a message using REST -description: Gets a message using REST without any back-end code. -host: OUTLOOK -api_set: - Mailbox: '1.5' -script: - content: | - $("#run").click(run); - - function run() { - Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, function (result) { - const ewsId = Office.context.mailbox.item.itemId; - const token = result.value; - const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); - const getMessageUrl = Office.context.mailbox.restUrl + '/v2.0/me/messages/' + restId; - - const xhr = new XMLHttpRequest(); - xhr.open('GET', getMessageUrl); - xhr.setRequestHeader("Authorization", "Bearer " + token); - xhr.onload = function (e) { - console.log(this.response); - } - xhr.send(); - }); - } - language: typescript -template: - content: | -
-

This sample shows how to get a message using REST, without any back-end code.

-
- -
-

Try it out

- -
- language: html -style: - content: | - section.samples { - margin-top: 20px; - } - - section.samples .ms-Button, section.setup .ms-Button { - display: block; - margin-bottom: 5px; - margin-left: 20px; - min-width: 80px; - } - language: css -libraries: | - https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file diff --git a/samples/outlook/85-tokens-and-service-calls/ids-and-urls.yaml b/samples/outlook/85-tokens-and-service-calls/ids-and-urls.yaml deleted file mode 100644 index 4b167e07a..000000000 --- a/samples/outlook/85-tokens-and-service-calls/ids-and-urls.yaml +++ /dev/null @@ -1,62 +0,0 @@ -order: 1 -id: outlook-tokens-and-service-calls-ids-and-urls -name: Endpoint URLs and item IDs -description: 'Retrieves and displays REST and EWS endpoint URLs and item IDs, and converts item IDs for different protocols.' -host: OUTLOOK -api_set: - Mailbox: '1.5' -script: - content: | - $("#run").click(run); - - function run() { - console.log("EWS URL: " + Office.context.mailbox.ewsUrl); - const ewsId = Office.context.mailbox.item.itemId; - console.log("EWS item ID: " + Office.context.mailbox.item.itemId); - - console.log("REST URL: " + Office.context.mailbox.restUrl); - const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); - console.log("REST item ID: " + restId); - - const ewsId2 = Office.context.mailbox.convertToEwsId(restId, Office.MailboxEnums.RestVersion.v2_0); - console.log("EWS ID (from REST ID): " + ewsId2); - } - language: typescript -template: - content: | -
-

This sample shows how to retrieve REST and EWS endpoint URLs and item IDs, and convert item IDs for different protocols.

-
- -
-

Try it out

- -
- language: html -style: - content: | - section.samples { - margin-top: 20px; - } - - section.samples .ms-Button, section.setup .ms-Button { - display: block; - margin-bottom: 5px; - margin-left: 20px; - min-width: 80px; - } - language: css -libraries: | - https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 diff --git a/samples/outlook/85-tokens-and-service-calls/item-id-compose.yaml b/samples/outlook/85-tokens-and-service-calls/item-id-compose.yaml deleted file mode 100644 index a797444d4..000000000 --- a/samples/outlook/85-tokens-and-service-calls/item-id-compose.yaml +++ /dev/null @@ -1,59 +0,0 @@ -order: 10 -id: outlook-tokens-and-service-calls-item-id-compose -name: Get an item ID in compose mode -description: 'Gets an item ID in compose mode, to use in certain delegate scenarios.' -host: OUTLOOK -api_set: - Mailbox: '1.8' -script: - content: | - $("#run").click(run); - - function run() { - Office.context.mailbox.item.getItemIdAsync(function (result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`getItemIdAsync failed with message: ${result.error.message}`); - } else { - console.log(result.value); - } - }); - } - language: typescript -template: - content: | -
-

This sample shows how to get an item ID in compose mode, to use in delegate scenarios where the item can't be saved due to insufficient delegate permissions.

-
- -
-

Try it out

- -
- language: html -style: - content: | - section.samples { - margin-top: 20px; - } - - section.samples .ms-Button, section.setup .ms-Button { - display: block; - margin-bottom: 5px; - margin-left: 20px; - min-width: 80px; - } - language: css -libraries: | - https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file diff --git a/samples/outlook/85-tokens-and-service-calls/user-callback-token.yaml b/samples/outlook/85-tokens-and-service-calls/user-callback-token.yaml deleted file mode 100644 index cec954b38..000000000 --- a/samples/outlook/85-tokens-and-service-calls/user-callback-token.yaml +++ /dev/null @@ -1,59 +0,0 @@ -order: 4 -id: outlook-tokens-and-service-calls-user-callback-token -name: Get a callback token -description: Gets a callback token to use for calling outlook services from add-in's backend service. -host: OUTLOOK -api_set: - Mailbox: '1.1' -script: - content: | - $("#run").click(run); - - function run() { - Office.context.mailbox.getCallbackTokenAsync(function (result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Token retrieval failed with message: ${result.error.message}`); - } else { - console.log(result.value); - } - }); - } - language: typescript -template: - content: | -
-

This sample shows how to get a callback token to use for calling outlook services from add-in's backend service.

-
- -
-

Try it out

- -
- language: html -style: - content: | - section.samples { - margin-top: 20px; - } - - section.samples .ms-Button, section.setup .ms-Button { - display: block; - margin-bottom: 5px; - margin-left: 20px; - min-width: 80px; - } - language: css -libraries: | - https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file diff --git a/samples/outlook/85-tokens-and-service-calls/user-identity-token.yaml b/samples/outlook/85-tokens-and-service-calls/user-identity-token.yaml deleted file mode 100644 index e974bfb1e..000000000 --- a/samples/outlook/85-tokens-and-service-calls/user-identity-token.yaml +++ /dev/null @@ -1,59 +0,0 @@ -order: 3 -id: outlook-tokens-and-service-calls-user-identity-token -name: Get a user identity token -description: Gets a user identity token to use in authentication flows. -host: OUTLOOK -api_set: - Mailbox: '1.1' -script: - content: | - $("#run").click(run); - - function run() { - Office.context.mailbox.getUserIdentityTokenAsync(function (result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Token retrieval failed with message: ${result.error.message}`); - } else { - console.log(result.value); - } - }); - } - language: typescript -template: - content: | -
-

This sample shows how to get a user identity token to use in authentication flows.

-
- -
-

Try it out

- -
- language: html -style: - content: | - section.samples { - margin-top: 20px; - } - - section.samples .ms-Button, section.setup .ms-Button { - display: block; - margin-bottom: 5px; - margin-left: 20px; - min-width: 80px; - } - language: css -libraries: | - https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file diff --git a/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-attendee.yaml b/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-attendee.yaml similarity index 59% rename from samples/outlook/85-tokens-and-service-calls/get-icaluid-as-attendee.yaml rename to samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-attendee.yaml index fbc5444b7..00fc8499a 100644 --- a/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-attendee.yaml +++ b/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-attendee.yaml @@ -1,13 +1,13 @@ order: 9 id: outlook-tokens-and-service-calls-get-icaluid-as-attendee -name: Get an appointment's iCalUId as an attendee -description: Uses EWS to get an appointment's iCalUId value where the user is the attendee. +name: Get an appointment's iCalUId as an attendee (Exchange on-premises only) +description: Uses Exchange Web Services (EWS) in an Exchange on-premises environment to get an appointment's iCalUId value where the user is an attendee. host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | - $("#run").click(run); + content: |- + document.getElementById("run").addEventListener("click", run); function run() { const ewsId = Office.context.mailbox.item.itemId; @@ -42,20 +42,23 @@ script: } language: typescript template: - content: | -
-

This sample shows how to get an appointment's iCalUId value if the user is the attendee.

+ content: |- +
+

This sample uses Exchange Web Services (EWS) to get an appointment's iCalUId value if the user is an attendee.

+

Important: Exchange user identity and callback tokens are only supported in Exchange on-premises environments. + In Exchange Online environments, use nested app authentication (NAA) + to get an access token. Then, use Microsoft Graph to get the iCalUId property. +

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -67,15 +70,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-organizer.yaml b/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-organizer.yaml similarity index 62% rename from samples/outlook/85-tokens-and-service-calls/get-icaluid-as-organizer.yaml rename to samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-organizer.yaml index 2b2503008..c782dc0a6 100644 --- a/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-organizer.yaml +++ b/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-organizer.yaml @@ -1,13 +1,13 @@ order: 8 id: outlook-tokens-and-service-calls-get-icaluid-as-organizer -name: Get an appointment's iCalUId as an organizer -description: Uses EWS to get an appointment's iCalUId value where the user is the organizer. +name: Get an appointment's iCalUId as the organizer (Exchange on-premises only) +description: Uses Exchange Web Services (EWS) in an Exchange on-premises environment to get an appointment's iCalUId value where the user is the organizer. host: OUTLOOK api_set: Mailbox: '1.3' script: - content: | - $("#run").click(run); + content: |- + document.getElementById("run").addEventListener("click", run); function run() { Office.context.mailbox.item.saveAsync((result) => { @@ -49,13 +49,16 @@ script: } language: typescript template: - content: | -
-

This sample shows how to get an appointment's iCalUId value if the user is the organizer.

+ content: |- +
+

This sample uses Exchange Web Services (EWS) to get an appointment's iCalUId value if the user is the organizer.

+

Important: Exchange user identity and callback tokens are only supported in Exchange on-premises environments. + In Exchange Online environments, use nested app authentication (NAA) + to get an access token. Then, use Microsoft Graph to get the iCalUId property. +

- language: html style: @@ -71,15 +74,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/85-tokens-for-exchange-on-premises/ids-and-urls.yaml b/samples/outlook/85-tokens-for-exchange-on-premises/ids-and-urls.yaml new file mode 100644 index 000000000..e31656ee1 --- /dev/null +++ b/samples/outlook/85-tokens-for-exchange-on-premises/ids-and-urls.yaml @@ -0,0 +1,61 @@ +order: 1 +id: outlook-tokens-and-service-calls-ids-and-urls +name: Endpoint URLs and item IDs in Exchange on-premises environments +description: Retrieves the Exchange Web Services (EWS) endpoint URL and item IDs and converts item IDs for different protocols. +host: OUTLOOK +api_set: + Mailbox: '1.5' +script: + content: |- + document.getElementById("run").addEventListener("click", run); + + function run() { + // Get the EWS URL and EWS item ID. + console.log("EWS URL: " + Office.context.mailbox.ewsUrl); + const ewsId = Office.context.mailbox.item.itemId; + console.log("EWS item ID: " + Office.context.mailbox.item.itemId); + + // Convert the EWS item ID to a REST-formatted ID. + const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); + console.log("REST item ID: " + restId); + + // Convert the REST-formatted ID back to an EWS-formatted ID. + const ewsId2 = Office.context.mailbox.convertToEwsId(restId, Office.MailboxEnums.RestVersion.v2_0); + console.log("EWS ID (from REST ID): " + ewsId2); + } + language: typescript +template: + content: |- +
+

This sample shows how to retrieve the EWS endpoint URL and item IDs, and convert item IDs for different protocols.

+

Important: Exchange user identity and callback tokens are only supported in Exchange on-premises environments. + In Exchange Online environments, use nested app authentication (NAA) + to get an access token. +

+
+
+

Try it out

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/outlook/85-tokens-and-service-calls/make-ews-request-async.yaml b/samples/outlook/85-tokens-for-exchange-on-premises/make-ews-request-async.yaml similarity index 61% rename from samples/outlook/85-tokens-and-service-calls/make-ews-request-async.yaml rename to samples/outlook/85-tokens-for-exchange-on-premises/make-ews-request-async.yaml index 6efee558c..c15444a51 100644 --- a/samples/outlook/85-tokens-and-service-calls/make-ews-request-async.yaml +++ b/samples/outlook/85-tokens-for-exchange-on-premises/make-ews-request-async.yaml @@ -1,13 +1,13 @@ order: 6 id: outlook-tokens-and-service-calls-make-ews-request-async -name: Get a message using EWS -description: Gets a message using EWS without any back-end code. +name: Get a message using Exchange Web Services (EWS) in Exchange on-premises environments +description: Uses EWS in an Exchange on-premises environment to get a message without any backend code. host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | - $("#run").click(run); + content: |- + document.getElementById("run").addEventListener("click", run); function run() { const ewsId = Office.context.mailbox.item.itemId; @@ -25,18 +25,21 @@ script: ' ' + ''; - Office.context.mailbox.makeEwsRequestAsync(request, function (result) { + Office.context.mailbox.makeEwsRequestAsync(request, (result) => { console.log(result); }); } language: typescript template: - content: | -
-

This sample shows how to get a message using EWS, without any back-end code.

+ content: |- +
+

This sample shows how to get a message using EWS, without any backend code.

+

Important: This API is only supported in Exchange on-premises environments. + In Exchange Online environments, use nested app authentication (NAA) + to get an access token. Then, use Microsoft Graph to get the message. +

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -56,15 +59,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/85-tokens-and-service-calls/send-message-using-make-ews-request-async.yaml b/samples/outlook/85-tokens-for-exchange-on-premises/send-message-using-make-ews-request-async.yaml similarity index 67% rename from samples/outlook/85-tokens-and-service-calls/send-message-using-make-ews-request-async.yaml rename to samples/outlook/85-tokens-for-exchange-on-premises/send-message-using-make-ews-request-async.yaml index c7e830764..c2cd39c56 100644 --- a/samples/outlook/85-tokens-and-service-calls/send-message-using-make-ews-request-async.yaml +++ b/samples/outlook/85-tokens-for-exchange-on-premises/send-message-using-make-ews-request-async.yaml @@ -1,13 +1,13 @@ order: 7 id: outlook-tokens-and-service-calls-send-message-using-make-ews-request-async -name: Send a message using EWS -description: Sends a message using EWS without any back-end code. +name: Send a message using Exchange Web Services (EWS) in Exchange on-premises environments +description: Uses EWS in an Exchange on-premises environment to send a message without any backend code. host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | - $("#run").click(run); + content: |- + document.getElementById("run").addEventListener("click", run); function run() { const request = ''+ @@ -28,18 +28,21 @@ script: ' '+ ''; - Office.context.mailbox.makeEwsRequestAsync(request, function (result) { + Office.context.mailbox.makeEwsRequestAsync(request, (result) => { console.log(result); }); } language: typescript template: - content: | -
+ content: |- +

This sample shows how to send a message using EWS, without any back-end code.

+

Important: This API is only supported in Exchange on-premises environments. + In Exchange Online environments, use nested app authentication (NAA) + to get an access token. Then, use Microsoft Graph to send the message. +

- -
+

Try it out

language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -59,15 +62,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/85-tokens-for-exchange-on-premises/user-callback-token.yaml b/samples/outlook/85-tokens-for-exchange-on-premises/user-callback-token.yaml new file mode 100644 index 000000000..82cf1e8db --- /dev/null +++ b/samples/outlook/85-tokens-for-exchange-on-premises/user-callback-token.yaml @@ -0,0 +1,58 @@ +order: 4 +id: outlook-tokens-and-service-calls-user-callback-token +name: Get a callback token in Exchange on-premises environments +description: Gets a callback token to call Outlook services from an add-in's backend service in an Exchange on-premises environment. +host: OUTLOOK +api_set: + Mailbox: '1.1' +script: + content: |- + document.getElementById("run").addEventListener("click", run); + + function run() { + Office.context.mailbox.getCallbackTokenAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`Token retrieval failed with message: ${result.error.message}`); + return; + } + + console.log(result.value); + }); + } + language: typescript +template: + content: |- +
+

This sample shows how to get a callback token to call Outlook services from an add-in's backend service.

+

Important: Exchange user identity and callback tokens are only supported in Exchange on-premises environments. + Additionally, the Outlook REST v2.0 endpoint has been deprecated. Use + nested app authentication (NAA) + to get an access token instead. +

+
+
+

Try it out

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/85-tokens-for-exchange-on-premises/user-identity-token.yaml b/samples/outlook/85-tokens-for-exchange-on-premises/user-identity-token.yaml new file mode 100644 index 000000000..07e604373 --- /dev/null +++ b/samples/outlook/85-tokens-for-exchange-on-premises/user-identity-token.yaml @@ -0,0 +1,57 @@ +order: 3 +id: outlook-tokens-and-service-calls-user-identity-token +name: Get a user identity token in Exchange on-premises environments +description: Gets a user identity token for authentication flows in an Exchange on-premises environment. +host: OUTLOOK +api_set: + Mailbox: '1.1' +script: + content: |- + document.getElementById("run").addEventListener("click", run); + + function run() { + Office.context.mailbox.getUserIdentityTokenAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`Token retrieval failed with message: ${result.error.message}`) + return; + } + + console.log(result.value); + }); + } + language: typescript +template: + content: |- +
+

This sample shows how to get a user identity token to use in authentication flows.

+

Important: This API is only supported in Exchange on-premises environments. + In Exchange Online environments, use nested app authentication (NAA) + to get an access token. +

+
+
+

Try it out

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/90-other-item-apis/delay-message-delivery.yaml b/samples/outlook/90-other-item-apis/delay-message-delivery.yaml index 9230db2d7..c5861ddc6 100644 --- a/samples/outlook/90-other-item-apis/delay-message-delivery.yaml +++ b/samples/outlook/90-other-item-apis/delay-message-delivery.yaml @@ -6,13 +6,13 @@ host: OUTLOOK api_set: Mailbox: '1.13' script: - content: | - $("#get-date").click(getDeliveryDate); - $("#set-time-five-minutes").click(() => computeDelay("set-time-five-minutes")); - $("#set-time-fifteen-minutes").click(() => computeDelay("set-time-fifteen-minutes")); - $("#set-time-thirty-minutes").click(() => computeDelay("set-time-thirty-minutes")); - $("#set-time-sixty-minutes").click(() => computeDelay("set-time-sixty-minutes")); - $("#set-time-one-day").click(() => computeDelay("set-time-one-day")); + content: |- + document.getElementById("get-date").addEventListener("click", getDeliveryDate); + document.getElementById("set-time-five-minutes").addEventListener("click", () => computeDelay("set-time-five-minutes")); + document.getElementById("set-time-fifteen-minutes").addEventListener("click", () => computeDelay("set-time-fifteen-minutes")); + document.getElementById("set-time-thirty-minutes").addEventListener("click", () => computeDelay("set-time-thirty-minutes")); + document.getElementById("set-time-sixty-minutes").addEventListener("click", () => computeDelay("set-time-sixty-minutes")); + document.getElementById("set-time-one-day").addEventListener("click", () => computeDelay("set-time-one-day")); let totalDelay = 0; @@ -65,12 +65,11 @@ script: language: typescript template: content: |- -
+

This sample gets and sets the delivery date and time of a message in compose mode. To learn more about this API, see Manage the delivery date and time of a message.

Required mode: Compose

- -
+

Try it out

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/90-other-item-apis/get-date-time-created-read.yaml b/samples/outlook/90-other-item-apis/get-date-time-created-read.yaml index f41ce02e7..da459a365 100644 --- a/samples/outlook/90-other-item-apis/get-date-time-created-read.yaml +++ b/samples/outlook/90-other-item-apis/get-date-time-created-read.yaml @@ -6,8 +6,8 @@ host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | - $("#get").click(get); + content: |- + document.getElementById("get").addEventListener("click", get); function get() { console.log(`Creation date and time: ${Office.context.mailbox.item.dateTimeCreated}`); @@ -15,11 +15,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to get the creation date and time of an item in Read mode.

Required modes: Appointment Attendee, Message Read

-
+

Try it out

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/90-other-item-apis/get-end-read.yaml b/samples/outlook/90-other-item-apis/get-end-read.yaml index 55e37fb88..e66f3af01 100644 --- a/samples/outlook/90-other-item-apis/get-end-read.yaml +++ b/samples/outlook/90-other-item-apis/get-end-read.yaml @@ -6,8 +6,8 @@ host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | - $("#get").click(get); + content: |- + document.getElementById("get").addEventListener("click", get); function get() { console.log(`Appointment ends: ${Office.context.mailbox.item.end}`); @@ -15,11 +15,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to get the end date and time of an item in Read mode.

Required modes: Appointment Attendee, Message Read (meeting request)

-
+

Try it out

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/90-other-item-apis/get-internet-message-id-read.yaml b/samples/outlook/90-other-item-apis/get-internet-message-id-read.yaml index 829fa5309..37a258bd1 100644 --- a/samples/outlook/90-other-item-apis/get-internet-message-id-read.yaml +++ b/samples/outlook/90-other-item-apis/get-internet-message-id-read.yaml @@ -6,8 +6,8 @@ host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | - $("#get").click(get); + content: |- + document.getElementById("get").addEventListener("click", get); function get() { console.log(`Internet message ID: ${Office.context.mailbox.item.internetMessageId}`); @@ -15,11 +15,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to get the internet message ID of a message in Read mode.

Required mode: Message Read

-
+

Try it out

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/90-other-item-apis/get-item-class-read.yaml b/samples/outlook/90-other-item-apis/get-item-class-read.yaml index 363e80cd3..70e0759ba 100644 --- a/samples/outlook/90-other-item-apis/get-item-class-read.yaml +++ b/samples/outlook/90-other-item-apis/get-item-class-read.yaml @@ -6,8 +6,8 @@ host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | - $("#get").click(get); + content: |- + document.getElementById("get").addEventListener("click", get); function get() { console.log(`Item class: ${Office.context.mailbox.item.itemClass}`); @@ -15,11 +15,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to get the item class of an item in Read mode.

Required mode: Read

-
+

Try it out

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml b/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml index cd5277f34..d58d33125 100644 --- a/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml +++ b/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml @@ -6,9 +6,9 @@ host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | - $("#get").click(get); - $("#set").click(set); + content: |- + document.getElementById("get").addEventListener("click", get); + document.getElementById("set").addEventListener("click", set); function get() { Office.context.mailbox.item.start.getAsync((result) => { @@ -34,11 +34,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to get and set the start date and time of an appointment in Compose mode.

Required mode: Appointment Organizer

-
+

Try it out

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/90-other-item-apis/send-async.yaml b/samples/outlook/90-other-item-apis/send-async.yaml new file mode 100644 index 000000000..41ef2e0a8 --- /dev/null +++ b/samples/outlook/90-other-item-apis/send-async.yaml @@ -0,0 +1,53 @@ +order: 30 +id: outlook-send-async +name: Send the current message or appointment (Compose) +description: Sends the current message or appointment. +host: OUTLOOK +api_set: + Mailbox: '1.15' +script: + content: |- + document.getElementById("send-async").addEventListener("click", sendAsync); + + function sendAsync() { + // This snippet sends the current message or appointment being composed. + Office.context.mailbox.item.sendAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + }); + } + language: typescript +template: + content: |- +
+

This sample shows how to programmatically send the current message or appointment being composed.

+

Required mode: Compose

+
+
+

Try it out

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/90-other-item-apis/session-data-apis.yaml b/samples/outlook/90-other-item-apis/session-data-apis.yaml index 0947b5ca8..d89b45d0c 100644 --- a/samples/outlook/90-other-item-apis/session-data-apis.yaml +++ b/samples/outlook/90-other-item-apis/session-data-apis.yaml @@ -1,17 +1,17 @@ order: 20 id: outlook-other-item-apis-session-data-apis name: Work with session data APIs (Compose) -description: 'Sets, gets, gets all, removes, and clears session data in Compose mode.' +description: Sets, gets, gets all, removes, and clears session data in Compose mode. host: OUTLOOK api_set: Mailbox: '1.11' script: - content: | - $("#setSessionData").click(setSessionData); - $("#getSessionData").click(getSessionData); - $("#getAllSessionData").click(getAllSessionData); - $("#removeSessionData").click(removeSessionData); - $("#clearSessionData").click(clearSessionData); + content: |- + document.getElementById("setSessionData").addEventListener("click", setSessionData); + document.getElementById("getSessionData").addEventListener("click", getSessionData); + document.getElementById("getAllSessionData").addEventListener("click", getAllSessionData); + document.getElementById("removeSessionData").addEventListener("click", removeSessionData); + document.getElementById("clearSessionData").addEventListener("click", clearSessionData); function setSessionData() { Office.context.mailbox.item.sessionData.setAsync( "Date", @@ -68,14 +68,14 @@ script: language: typescript template: content: |- -
+

This sample shows how to set, get, get all, remove, and clear session data in compose mode.

Required mode: Compose

-
+
@@ -106,12 +106,8 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - core-js@2.4.1/client/core.min.js - @types/core-js - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/outlook/90-other-item-apis/set-selected-data.yaml b/samples/outlook/90-other-item-apis/set-selected-data.yaml index e98f0c23a..7d2be55ff 100644 --- a/samples/outlook/90-other-item-apis/set-selected-data.yaml +++ b/samples/outlook/90-other-item-apis/set-selected-data.yaml @@ -6,8 +6,8 @@ host: OUTLOOK api_set: Mailbox: '1.1' script: - content: | - $("#set-selected-data").click(setSelectedData); + content: |- + document.getElementById("set-selected-data").addEventListener("click", setSelectedData); function setSelectedData() { Office.context.mailbox.item.setSelectedDataAsync("Replaced", function(asyncResult) { @@ -21,12 +21,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to replace the selected text in the item body or subject/title.

Required mode: Compose

- -
+

Try it out

Select text in the item body or subject then push the Replace selected text button.

- - - -
- language: html -style: - content: |- - section.samples { - margin-top: 20px; - } - - section.samples .ms-Button, section.setup .ms-Button { - display: block; - margin-bottom: 5px; - margin-left: 20px; - min-width: 80px; - } - language: css -libraries: | - https://appsforoffice.microsoft.com/lib/beta/hosted/office.js - @types/office-js-preview - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 diff --git a/samples/outlook/99-preview-apis/get-set-isalldayevent.yaml b/samples/outlook/99-preview-apis/get-set-isalldayevent.yaml new file mode 100644 index 000000000..d9d8c44aa --- /dev/null +++ b/samples/outlook/99-preview-apis/get-set-isalldayevent.yaml @@ -0,0 +1,69 @@ +order: 1 +id: outlook-get-set-isalldayevent +name: Get and set the isAllDayEvent property (Appointment Organizer) +description: Gets and sets the isAllDayEvent property of an appointment being composed. +host: OUTLOOK +api_set: + Mailbox: preview +script: + content: |- + document.getElementById("getIsAllDayEvent").addEventListener("click", getIsAllDayEvent); + document.getElementById("setIsAllDayEventTrue").addEventListener("click", setIsAllDayEventTrue); + + function getIsAllDayEvent() { + Office.context.mailbox.item.isAllDayEvent.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Is this an all-day event? " + asyncResult.value); + } else { + console.log("Failed to get if this is an all-day event. Error: " + JSON.stringify(asyncResult.error)); + } + }); + } + + function setIsAllDayEventTrue() { + Office.context.mailbox.item.isAllDayEvent.setAsync(true, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Failed to set all-day event: " + JSON.stringify(asyncResult.error)); + } else { + console.log("Appointment set to all-day event."); + } + }); + } + language: typescript +template: + content: |- +
+

This sample shows how to get and set the isAllDayEvent property of an appointment being composed. +

+ Required mode: Appointment Organizer +

+

+
+
+ + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/beta/hosted/office.js + @types/office-js-preview + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml b/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml index 722728905..fcb27dd05 100644 --- a/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml +++ b/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml @@ -6,16 +6,14 @@ host: OUTLOOK api_set: Mailbox: preview script: - content: | - $("#set-body").click(setDisplayedBody); - $("#set-subject").click(setDisplayedSubject); + content: |- + document.getElementById("set-body").addEventListener("click", setDisplayedBody); + document.getElementById("set-subject").addEventListener("click", setDisplayedSubject); function setDisplayedBody() { // This snippet temporarily sets the content displayed in the body of a message in read mode. // The set content will remain visible until the user switches to a different message in the Reading Pane or closes the window of the current message. - const bodyText = $("#body-text-field") - .val() - .toString(); + const bodyText = (document.getElementById("body-text-field") as HTMLInputElement).value; Office.context.mailbox.item.display.body.setAsync(bodyText, (asyncResult) => { if (asyncResult.status === Office.AsyncResultStatus.Failed) { console.log(`Action failed with error: ${asyncResult.error.message}`); @@ -29,9 +27,7 @@ script: function setDisplayedSubject() { // This snippet temporarily sets the content displayed in the subject field of a message in read mode. // The set content will remain visible until the user switches to a different message in the Reading Pane or closes the window of the current message. - const subjectText = $("#subject-text-field") - .val() - .toString(); + const subjectText = (document.getElementById("subject-text-field") as HTMLInputElement).value; Office.context.mailbox.item.display.subject.setAsync(subjectText, (asyncResult) => { if (asyncResult.status === Office.AsyncResultStatus.Failed) { console.log(`Action failed with error: ${asyncResult.error.message}`); @@ -44,13 +40,12 @@ script: language: typescript template: content: |- -
+

This sample shows how to temporarily set the content displayed in the body or subject of a message in read mode.

Required mode: Message Read

- -
+

Try it out

@@ -83,15 +78,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/beta/hosted/office.js @types/office-js-preview - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/outlook/default.yaml b/samples/outlook/default.yaml index 03b07809b..7d8729c82 100644 --- a/samples/outlook/default.yaml +++ b/samples/outlook/default.yaml @@ -5,8 +5,8 @@ author: OfficeDev host: OUTLOOK api_set: null script: - content: | - $("#run").click(run); + content: |- + document.getElementById("run").addEventListener("click", run); function run() { const userProfile = Office.context.mailbox.userProfile; @@ -14,7 +14,7 @@ script: } language: typescript template: - content: | + content: |- @@ -32,15 +32,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/powerpoint/basics/basic-api-call-js.yaml b/samples/powerpoint/basics/basic-api-call-js.yaml index b43a99e5d..903944372 100644 --- a/samples/powerpoint/basics/basic-api-call-js.yaml +++ b/samples/powerpoint/basics/basic-api-call-js.yaml @@ -1,12 +1,13 @@ order: 2 id: powerpoint-basics-basic-api-call-js name: Basic API call (JavaScript) -description: Performs a basic PowerPoint API call using JavaScript +description: Performs a basic PowerPoint API call using JavaScript. host: POWERPOINT -api_set: PowerPointApi '1.4' +api_set: + PowerPointApi: '1.4' script: - content: | - $("#run").click(() => tryCatch(run)); + content: |- + document.getElementById("run").addEventListener("click", () => tryCatch(run)); function run() { // This function gets the collection of shapes on the first slide, @@ -38,7 +39,7 @@ script: language: typescript template: content: |- -
+
This sample executes a code snippet that adds a text box to the first slide in the presentation.
@@ -39,15 +39,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/powerpoint/default.yaml b/samples/powerpoint/default.yaml index 175564923..cbf9fc811 100644 --- a/samples/powerpoint/default.yaml +++ b/samples/powerpoint/default.yaml @@ -5,8 +5,8 @@ author: OfficeDev host: POWERPOINT api_set: {} script: - content: | - $("#run").click(run); + content: |- + document.getElementById("run").addEventListener("click", run); function run() { Office.context.document.getSelectedDataAsync(Office.CoercionType.Text, (asyncResult) => { @@ -19,7 +19,7 @@ script: } language: typescript template: - content: | + content: |- @@ -37,15 +37,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/powerpoint/document/create-presentation.yaml b/samples/powerpoint/document/create-presentation.yaml index b11beeb0a..a2c0b605f 100644 --- a/samples/powerpoint/document/create-presentation.yaml +++ b/samples/powerpoint/document/create-presentation.yaml @@ -1,21 +1,21 @@ id: powerpoint-create-presentation name: Create presentation -description: 'Creates a new, empty presentation and creates a new presentation by copying an existing one.' +description: Creates a new, empty presentation and creates a new presentation by copying an existing one. author: OfficeDev host: POWERPOINT api_set: - PowerPoint: 1.1 + PowerPointApi: '1.1' script: - content: | - $("#create-new-blank-presentation").click(() => tryCatch(createBlankPresentation)); - $("#file").change(() => tryCatch(createPresentationFromExisting)); + content: |- + document.getElementById("create-new-blank-presentation").addEventListener("click", () => tryCatch(createBlankPresentation)); + document.getElementById("file").addEventListener("change", () => tryCatch(createPresentationFromExisting)); function createBlankPresentation() { PowerPoint.createPresentation(); } function createPresentationFromExisting() { - const myFile = document.getElementById("file"); + const myFile = document.getElementById("file") as HTMLInputElement; const reader = new FileReader(); reader.onload = (event) => { @@ -42,11 +42,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to create a new, empty presentation and how to create a new presentation by copying an existing one.

- -
+

Try it out

Create empty presentation

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/powerpoint/images/insert-image.yaml b/samples/powerpoint/images/insert-image.yaml index 4b1d7f071..bc432ec35 100644 --- a/samples/powerpoint/images/insert-image.yaml +++ b/samples/powerpoint/images/insert-image.yaml @@ -6,8 +6,8 @@ author: OfficeDev host: POWERPOINT api_set: {} script: - content: | - $('#insert').click(run); + content: |- + document.getElementById('insert').addEventListener("click", run); function run() { Office.context.document.setSelectedDataAsync(getImageAsBase64String(), { @@ -32,10 +32,9 @@ script: language: typescript template: content: |- -
+

Insert an image into the current slide.

- @@ -53,15 +52,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/powerpoint/images/insert-svg.yaml b/samples/powerpoint/images/insert-svg.yaml index b4f8cacf4..d3d66522e 100644 --- a/samples/powerpoint/images/insert-svg.yaml +++ b/samples/powerpoint/images/insert-svg.yaml @@ -6,8 +6,8 @@ author: OfficeDev host: POWERPOINT api_set: {} script: - content: | - $('#insert').click(newImage); + content: |- + document.getElementById('insert').addEventListener("click", newImage); function newImage() { Office.context.document.setSelectedDataAsync(getImageAsBase64String(), { @@ -33,11 +33,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to insert an SVG image using an XML string as the source.

- -
+

Try it out

+
+
+

Try it out

+ + + + + + + + + + + + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + @types/office-js + + office-ui-fabric-js@1.4.0/dist/css/fabric.min.css + office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css + + core-js@2.4.1/client/core.min.js + @types/core-js diff --git a/samples/powerpoint/shapes/binding-to-shapes.yaml b/samples/powerpoint/shapes/binding-to-shapes.yaml new file mode 100644 index 000000000..6059ca2ba --- /dev/null +++ b/samples/powerpoint/shapes/binding-to-shapes.yaml @@ -0,0 +1,370 @@ +order: 5 +id: powerpoint-shapes-binding-to-shapes +name: Binding to shapes +description: Shows how to create binding references for images and work with z-order. +host: POWERPOINT +api_set: + PowerPointApi: '1.8' +script: + content: | + document + .getElementById("insert-image-and-create-binding") + .addEventListener("click", () => tryCatch(insertImageWithBinding)); + document.getElementById("replace-binding1").addEventListener("click", () => + tryCatch(() => { + replaceBinding(1); + }) + ); + document.getElementById("replace-binding2").addEventListener("click", () => + tryCatch(() => { + replaceBinding(2); + }) + ); + document.getElementById("replace-binding3").addEventListener("click", () => + tryCatch(() => { + replaceBinding(3); + }) + ); + document.getElementById("load-bindings").addEventListener("click", () => tryCatch(loadBindings)); + document.getElementById("bring-to-front").addEventListener("click", () => tryCatch(bringToFront)); + document.getElementById("bring-forward").addEventListener("click", () => tryCatch(bringForward)); + document.getElementById("send-backward").addEventListener("click", () => tryCatch(sendBackward)); + document.getElementById("send-to-back").addEventListener("click", () => tryCatch(sendToBack)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + const flowerImage = getImageAsBase64String(); + + const greenery1 = returnGreenery1AsBase64(); + + const greenery2 = returnGreenery2AsBase64(); + + const greenery3 = returnGreenery3AsBase64(); + + async function insertImageWithBinding() { + // Inserts an image with binding. + await PowerPoint.run(async (context) => { + const bindingId = (document.getElementById("temp-binding-id") as HTMLInputElement).value; + const slide = context.presentation.getSelectedSlides().getItemAt(0); + const myShape = slide.shapes.addGeometricShape(PowerPoint.GeometricShapeType.rectangle, { + top: 100, + left: 30, + width: 200, + height: 200 + }); + + myShape.fill.setImage(flowerImage); + context.presentation.bindings.add(myShape, PowerPoint.BindingType.shape, bindingId); + await context.sync(); + + const bindingsDropdown = document.getElementById("bindings-dropdown") as HTMLSelectElement; + + const option = new Option(`Binding ${bindingId}`, bindingId); + + // When a binding ID already exists, the binding is updated to refer to the new shape + // so select the existing item rather than add a new one. + const foundIndex = findDropdownItem(bindingsDropdown, option.text); + if (foundIndex < 0) { + bindingsDropdown.add(option); + bindingsDropdown.selectedIndex = bindingsDropdown.options.length - 1; + } else { + bindingsDropdown.selectedIndex = foundIndex; + } + }); + } + + async function replaceBinding(greenery) { + // Update image in binding with selected replacement image. + await PowerPoint.run(async (context) => { + if (greenery === 1) + context.presentation.bindings + .getItem((document.getElementById("bindings-dropdown") as HTMLSelectElement).value) + .getShape() + .fill.setImage(greenery1); + else if (greenery === 2) + context.presentation.bindings + .getItem((document.getElementById("bindings-dropdown") as HTMLSelectElement).value) + .getShape() + .fill.setImage(greenery2); + else + context.presentation.bindings + .getItem((document.getElementById("bindings-dropdown") as HTMLSelectElement).value) + .getShape() + .fill.setImage(greenery3); + + await context.sync(); + }); + } + + async function getShapeForBindingId(bindingId: string): Promise { + // Gets shape associated with binding ID. + return PowerPoint.run(async (context) => { + const binding = context.presentation.bindings.getItem(bindingId); + const shape = binding.getShape(); + return shape; + }); + } + + async function loadBindings() { + // Loads bindings. + await PowerPoint.run(async (context) => { + const bindings = context.presentation.bindings; + bindings.load("items"); + await context.sync(); + + const bindingCount = bindings.items.length; + if (bindingCount === 0) { + console.log(`There are no bindings.`); + } else if (bindingCount === 1) { + console.log("There's 1 binding."); + } else { + console.log(`There are ${bindingCount} bindings.`); + } + + bindings.items.forEach((binding) => { + getShapeForBindingId(binding.id).then((shape) => { + if (shape) { + console.log(`Binding ID: ${binding.id} refers to shape ID ${shape.id}`); + } else { + console.log(`Binding ID: ${binding.id} doesn't refers to shape.`); + } + }); + }); + + populateBindingsDropdown(bindings.items); + }); + } + + function findDropdownItem(dropdown: HTMLSelectElement, text: string): number { + // Finds dropdown items. + for (let index = 0; index < dropdown.options.length; ++index) { + if (dropdown.options[index].text === text) { + return index; + } + } + + return -1; + } + + async function populateBindingsDropdown(bindings: PowerPoint.Binding[]) { + // Populates bindings dropdown list. + const bindingsDropdown = document.getElementById("bindings-dropdown") as HTMLSelectElement; + bindingsDropdown.options.length = 0; + bindings.forEach((binding) => { + const option = new Option(`Binding ${binding.id}`, binding.id); + bindingsDropdown.add(option); + }); + + bindingsDropdown.selectedIndex = 0; + } + + function bringToFront() { + // Brings the shape to the front. + changeZOrder(PowerPoint.ShapeZOrder.bringToFront); + } + + function bringForward() { + // Brings the shape forward. + changeZOrder(PowerPoint.ShapeZOrder.bringForward); + } + + function sendBackward() { + // Sends the shape backward. + changeZOrder(PowerPoint.ShapeZOrder.sendBackward); + } + + function sendToBack() { + // Sends the shape to the back. + changeZOrder(PowerPoint.ShapeZOrder.sendToBack); + } + + async function changeZOrder(operation: PowerPoint.ShapeZOrder) { + // Changes the z-order position of the selected shapes. + return PowerPoint.run(async (context) => { + const selectedShapes = context.presentation.getSelectedShapes(); + selectedShapes.load(); + await context.sync(); + + if (selectedShapes.items.length === 0) { + console.log("No shapes are selected."); + } else { + let direction = 1; // Start with bottom-most (lowest number). + + // Start with top-most when sending to back or bringing forward. + + switch (operation) { + case PowerPoint.ShapeZOrder.bringForward: + + case PowerPoint.ShapeZOrder.sendToBack: + direction = -1; // Reverse direction. + + break; + } + + // Change the z-order position for each of the selected shapes, + + // starting with the bottom-most when bringing to front or sending backward, + + // or top-most when sending to back or bringing forward, + + // so the selected shapes retain their relative z-order positions after they're changed. + + selectedShapes.items + .sort((a, b) => (a.zOrderPosition - b.zOrderPosition) * direction) + .forEach((shape) => { + try { + const originalZOrderPosition = shape.zOrderPosition; + shape.setZOrder(operation); + + console.log(`Changed z-order of shape ${shape.id}.`); + } catch (err) { + console.log(`Unable to change z-order of shape ${shape.id}. ${err.message}`); + } + }); + + await context.sync(); + } + }); + } + + function logSelectedShapesZOrder(selectedShapes: PowerPoint.ShapeScopedCollection) { + // Logs the z-order position of the selected shapes. + console.log(`Selected shapes:`); + + selectedShapes.items.forEach((shape, index) => { + console.log(` [${index}] shape ID ${shape.id}, z-order position: ${shape.zOrderPosition}`); + }); + } + + function getImageAsBase64String() { + // A production add-in code could get an image from an + + // online source and pass it to a library function that + + // converts to Base64. + + return "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"; + } + + function returnGreenery1AsBase64() { + return "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"; + } + + function returnGreenery2AsBase64() { + return "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"; + } + + function returnGreenery3AsBase64() { + return "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"; + } + + async function setup() { + await PowerPoint.run(async (context) => { + // Adds a new slide with some content. + const slideCountResult = context.presentation.slides.getCount(); + context.presentation.slides.add(); + await context.sync(); + + const newSlide = context.presentation.slides.getItemAt(slideCountResult.value); + newSlide.load("id"); + newSlide.shapes.addGeometricShape(PowerPoint.GeometricShapeType.hexagon); + await context.sync(); + + console.log(`Added slide - ID: ${newSlide.id}`); + + // Switch to the new slide. + context.presentation.setSelectedSlides([newSlide.id]); + await context.sync(); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+

This sample shows how to create binding references for images.

+
+
+

Set up

+ +
+
+

Try it out

+

Insert image with binding

+

Try adding a few images. Enter an ID, then select the button. A binding with that ID will be created which refers + to the shape.

+

Binding ID: + +

+ +

Show the bindings in the document

+

The console will show the bindings in the document.

+ +

Update an image using its binding

+

Select a binding ID from the dropdown list then pick a replacement picture.

+

Choose the binding for the image you want to update:

+ +

+

Select the replacement image:

+ + + +

+

After adding a few images, try z-Order APIs

+

Click on or select the image you want to act on.

+ + + + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: | + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + @types/office-js + + office-ui-fabric-js@1.4.0/dist/css/fabric.min.css + office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css + + core-js@2.4.1/client/core.min.js + @types/core-js diff --git a/samples/powerpoint/shapes/get-set-shapes.yaml b/samples/powerpoint/shapes/get-set-shapes.yaml index 330aa10ec..4e24db0c5 100644 --- a/samples/powerpoint/shapes/get-set-shapes.yaml +++ b/samples/powerpoint/shapes/get-set-shapes.yaml @@ -1,25 +1,25 @@ order: 2 id: powerpoint-shapes-get-set-shapes -name: 'Get, set, load, and save shapes' +name: Get, set, load, and save shapes description: Get and set one or more selected shapes. Load and save one or more shapes. host: POWERPOINT api_set: PowerPointApi: '1.5' script: content: | - $("#getSelectedShapes").click(() => tryCatch(getSelectedShapes)); - $("#setSelectedShapes").click(() => tryCatch(setSelectedShapes)); - $("#changeFill").click(() => tryCatch(changeFill)); - $("#saveShapeSelection").click(() => tryCatch(saveShapeSelection)); - $("#loadShapeSelection").click(() => tryCatch(loadShapeSelection)); - $("#createShapes").click(() => tryCatch(createShapes)); - $("#arrangeSelected").click(() => tryCatch(arrangeSelected)); + document.getElementById("getSelectedShapes").addEventListener("click", () => tryCatch(getSelectedShapes)); + document.getElementById("setSelectedShapes").addEventListener("click", () => tryCatch(setSelectedShapes)); + document.getElementById("changeFill").addEventListener("click", () => tryCatch(changeFill)); + document.getElementById("saveShapeSelection").addEventListener("click", () => tryCatch(saveShapeSelection)); + document.getElementById("loadShapeSelection").addEventListener("click", () => tryCatch(loadShapeSelection)); + document.getElementById("createShapes").addEventListener("click", () => tryCatch(createShapes)); + document.getElementById("arrangeSelected").addEventListener("click", () => tryCatch(arrangeSelected)); async function getSelectedShapes() { // Gets the shapes you selected on the slide and displays their IDs on the task pane. await PowerPoint.run(async (context) => { let finalTable = ""; - const shapes = context.presentation.getSelectedShapes(); + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); const shapeCount = shapes.getCount(); await context.sync(); finalTable += "
getSelectedShapes.getCount returned:" + shapeCount.value + "
"; @@ -31,8 +31,9 @@ script: finalTable += "" + index + "" + shape.id + ""; }); finalTable += ""; - $("#outputSpan").empty(); - $("#outputSpan").append(finalTable); + const outputSpan = document.getElementById("outputSpan"); + outputSpan.innerHTML = ""; + outputSpan.innerHTML += finalTable; }); } @@ -42,14 +43,17 @@ script: context.presentation.load("slides"); await context.sync(); const slide1 = context.presentation.slides.getItemAt(0); - slide1.load("shapes"); + slide1.load("shapes/items/type"); await context.sync(); - const shapes = slide1.shapes; - const shape1 = shapes.getItemAt(0); - const shape2 = shapes.getItemAt(1); + + const shapes = slide1.shapes.items.filter((item) => item.type === PowerPoint.ShapeType.geometricShape); + const shape1: PowerPoint.Shape = shapes[0]; + const shape2: PowerPoint.Shape = shapes[1]; shape1.load("id"); shape2.load("id"); await context.sync(); + + console.log(`IDs: ${shape1.id}, ${shape2.id}`) slide1.setSelectedShapes([shape1.id, shape2.id]); await context.sync(); }); @@ -58,7 +62,7 @@ script: async function changeFill() { // Changes the selected shapes fill color to red. await PowerPoint.run(async (context) => { - const shapes = context.presentation.getSelectedShapes(); + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); const shapeCount = shapes.getCount(); shapes.load("items"); await context.sync(); @@ -76,7 +80,7 @@ script: await PowerPoint.run(async (context) => { context.presentation.load("slides"); await context.sync(); - const slides = context.presentation.getSelectedSlides(); + const slides: PowerPoint.SlideScopedCollection = context.presentation.getSelectedSlides(); const slideCount = slides.getCount(); slides.load("items"); await context.sync(); @@ -84,7 +88,7 @@ script: slides.items.map((slide) => { savedSlideSelection.push(slide.id); }); - const shapes = context.presentation.getSelectedShapes(); + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); const shapeCount = shapes.getCount(); shapes.load("items"); await context.sync(); @@ -97,7 +101,7 @@ script: async function loadShapeSelection() { // Reselects shapes that were saved previously. await PowerPoint.run(async (context) => { - const slide1 = context.presentation.slides.getItem(savedSlideSelection[0]); + const slide1: PowerPoint.Slide = context.presentation.slides.getItem(savedSlideSelection[0]); await context.sync(); slide1.setSelectedShapes(savedShapeSelection); await context.sync(); @@ -120,13 +124,15 @@ script: // Creates random shapes on the selected slide. await PowerPoint.run(async (context) => { let finalTable = ""; - const currentSlide = context.presentation.getSelectedSlides().getItemAt(0); + const currentSlide: PowerPoint.Slide = context.presentation.getSelectedSlides().getItemAt(0); const maxNewShapeWidth = 200; const maxNewShapeHeight = 200; const minNewShapeWidth = 50; const minNewShapeHeight = 50; for (let i = 0; i < 20; i++) { - const rectangle = currentSlide.shapes.addGeometricShape(PowerPoint.GeometricShapeType.rectangle); + const rectangle: PowerPoint.Shape = currentSlide.shapes.addGeometricShape( + PowerPoint.GeometricShapeType.rectangle + ); rectangle.height = getRandomBetween(minNewShapeWidth, maxNewShapeWidth); rectangle.width = getRandomBetween(minNewShapeHeight, maxNewShapeHeight); rectangle.left = getRandomBetween(0, slideWidth - rectangle.width); @@ -134,8 +140,9 @@ script: rectangle.fill.foregroundColor = generateRandomHexColor(); } finalTable += "Done
"; - $("#slide-tags").empty(); - $("#slide-tags").append(finalTable); + const outputSpan = document.getElementById("outputSpan"); + outputSpan.innerHTML = ""; + outputSpan.innerHTML += finalTable; }); } @@ -144,7 +151,7 @@ script: async function arrangeSelected() { // Arranges the selected shapes in a line from left to right. await PowerPoint.run(async (context) => { - const shapes = context.presentation.getSelectedShapes(); + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); const shapeCount = shapes.getCount(); shapes.load("items"); await context.sync(); @@ -176,12 +183,11 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to get selected shapes, and how to select and change specific shapes.

- -
+

Try it out


@@ -194,7 +200,7 @@ template:
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -213,15 +219,9 @@ style: transition: max-height 0.2s ease-out; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/powerpoint/shapes/get-shapes-by-type.yaml b/samples/powerpoint/shapes/get-shapes-by-type.yaml new file mode 100644 index 000000000..747202762 --- /dev/null +++ b/samples/powerpoint/shapes/get-shapes-by-type.yaml @@ -0,0 +1,140 @@ +order: 3 +id: powerpoint-shapes-get-shapes-by-type +name: Select shapes by type +description: Gets shapes in a slide based on their type, such as GeometricShape or Line. +host: POWERPOINT +api_set: + PowerPointApi: '1.4' +script: + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("change-lines").addEventListener("click", () => tryCatch(changeLines)); + document.getElementById("change-geometric-shapes").addEventListener("click", () => tryCatch(changeGeometricShapes)); + + async function changeLines() { + // Changes the dash style of every line in the slide. + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); + await context.sync(); + + // Change the dash style for shapes of the type `line`. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.line) { + shape.lineFormat.dashStyle = PowerPoint.ShapeLineDashStyle.dashDot; + } + }); + await context.sync(); + }); + } + + async function changeGeometricShapes() { + // Changes the transparency of every geometric shape in the slide. + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); + await context.sync(); + + // Change the shape transparency to be halfway transparent. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.geometricShape) { + shape.fill.transparency = 0.5; + } + }); + await context.sync(); + }); + } + + async function setup() { + await PowerPoint.run(async (context) => { + // Create shapes of different types. + const shapes = context.presentation.slides.getItemAt(0).shapes; + + // Create geometric shapes. + shapes.addGeometricShape(PowerPoint.GeometricShapeType.diamond, { + left: 100, + top: 100, + height: 150, + width: 150 + }); + shapes.addGeometricShape(PowerPoint.GeometricShapeType.octagon, { + left: 400, + top: 300, + height: 150, + width: 150 + }); + + // Create lines. + shapes.addLine(PowerPoint.ConnectorType.elbow, { + left: 400, + top: 150, + height: 20, + width: 150 + }); + shapes.addLine(PowerPoint.ConnectorType.curve, { + left: 100, + top: 300, + height: 150, + width: 20 + }); + + await context.sync(); + }); + } + + /** Default helper for invoking an action and handling errors. */ + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+

This sample shows how select and change shapes based on their types.

+
+
+

Setup

+

Create some shapes in a new, blank presentation.

+

+ +

+

Try it out

+

+ +

+ +

+

+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/powerpoint/shapes/group-ungroup-shapes.yaml b/samples/powerpoint/shapes/group-ungroup-shapes.yaml new file mode 100644 index 000000000..6d8e8f3fe --- /dev/null +++ b/samples/powerpoint/shapes/group-ungroup-shapes.yaml @@ -0,0 +1,193 @@ +order: 6 +id: powerpoint-shapes-group-ungroup-shapes +name: Group and ungroup shapes +description: Shows how to create two shapes then group and ungroup them. +author: aafvstam +host: POWERPOINT +api_set: + PowerPointApi: '1.8' +script: + content: | + document.getElementById("group-shapes").addEventListener("click", () => tryCatch(groupShapes)); + document.getElementById("move-group").addEventListener("click", () => tryCatch(moveGroup)); + document.getElementById("ungroup-shapes").addEventListener("click", () => tryCatch(ungroupShapes)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + async function groupShapes() { + await PowerPoint.run(async (context) => { + // Groups the geometric shapes on the current slide. + + // Get the shapes on the current slide. + context.presentation.load("slides"); + const slide: PowerPoint.Slide = context.presentation.getSelectedSlides().getItemAt(0); + slide.load("shapes/items/type,shapes/items/id"); + await context.sync(); + + const shapes: PowerPoint.ShapeCollection = 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}`); + }); + } + + async function moveGroup() { + await PowerPoint.run(async (context) => { + // Move the first shape group to the top-left of the current slide. + + // Get the shapes on the current slide. + context.presentation.load("slides"); + const slide: PowerPoint.Slide = context.presentation.getSelectedSlides().getItemAt(0); + slide.load("shapes/items/type,shapes/items/id"); + await context.sync(); + + const shapes: PowerPoint.ShapeCollection = 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 move."); + return; + } + + // Move the first grouped shapes. + const firstGroupId = shapeGroups[0].id; + const shapeGroupToMove = shapes.getItem(firstGroupId); + shapeGroupToMove.top = 0; + shapeGroupToMove.left = 0; + await context.sync(); + + console.log(`Moved shape group with group ID: ${firstGroupId}`); + }); + } + + async function ungroupShapes() { + await PowerPoint.run(async (context) => { + // Ungroups the first shape group on the current slide. + + // Get the shapes on the current slide. + context.presentation.load("slides"); + const slide: PowerPoint.Slide = context.presentation.getSelectedSlides().getItemAt(0); + slide.load("shapes/items/type,shapes/items/id"); + await context.sync(); + + const shapes: PowerPoint.ShapeCollection = 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}`); + }); + } + + async function setup() { + await PowerPoint.run(async (context) => { + // Adds a new slide with two shapes. + const slideCountResult = context.presentation.slides.getCount(); + context.presentation.slides.add(); + await context.sync(); + + const newSlide = context.presentation.slides.getItemAt(slideCountResult.value); + newSlide.load("id"); + + // Create two shapes. + const shape1 = newSlide.shapes.addGeometricShape(PowerPoint.GeometricShapeType.rectangle); + shape1.left = 100; + shape1.top = 100; + shape1.width = 150; + shape1.height = 100; + shape1.fill.foregroundColor = "darkred"; + + const shape2 = newSlide.shapes.addGeometricShape(PowerPoint.GeometricShapeType.ellipse); + shape2.left = 300; + shape2.top = 100; + shape2.width = 150; + shape2.height = 100; + shape2.fill.foregroundColor = "darkblue"; + + await context.sync(); + + console.log(`Added slide - ID: ${newSlide.id}`); + + // Switch to the new slide. + context.presentation.setSelectedSlides([newSlide.id]); + await context.sync(); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+

Shows how to group then ungroup shapes.

+

Code sample based on community contribution from Maarten van Stam.

+
+
+

Set up

+ +
+
+

Try it out

+ + + +
+ language: html +style: + content: | + section.samples { + margin-top: 20px; + } + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + .content { + padding: 0 18px; + /* display: none; */ + overflow: hidden; + background-color: #f1f1f1; + max-height: 0; + transition: max-height 0.2s ease-out; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + @types/office-js + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/powerpoint/shapes/shapes.yaml b/samples/powerpoint/shapes/shapes.yaml index b8c93987a..da2850890 100644 --- a/samples/powerpoint/shapes/shapes.yaml +++ b/samples/powerpoint/shapes/shapes.yaml @@ -1,31 +1,33 @@ +order: 1 id: powerpoint-shapes -name: 'Insert shape, line, and text box' -description: 'Inserts geometric shapes, lines, and text boxes to a slide.' +name: Insert shape, line, and text box +description: Inserts geometric shapes, lines, and text boxes to a slide. host: POWERPOINT -api_set: PowerPointApi '1.4' +api_set: + PowerPointApi: '1.4' script: - content: | - $("#create-hexagon").click(() => tryCatch(createHexagon)); - $("#shrink-hexagon").click(() => tryCatch(shrinkHexagon)); - $("#move-hexagon").click(() => tryCatch(moveHexagon)); - $("#create-line").click(() => tryCatch(createLine)); - $("#create-text-box").click(() => tryCatch(createTextBox)); - $("#create-shape-with-text").click(() => tryCatch(createShapeWithText)); - $("#remove-all").click(() => tryCatch(removeAll)); + content: |- + document.getElementById("create-hexagon").addEventListener("click", () => tryCatch(createHexagon)); + document.getElementById("shrink-hexagon").addEventListener("click", () => tryCatch(shrinkHexagon)); + document.getElementById("move-hexagon").addEventListener("click", () => tryCatch(moveHexagon)); + document.getElementById("create-line").addEventListener("click", () => tryCatch(createLine)); + document.getElementById("create-text-box").addEventListener("click", () => tryCatch(createTextBox)); + document.getElementById("create-shape-with-text").addEventListener("click", () => tryCatch(createShapeWithText)); + document.getElementById("remove-all").addEventListener("click", () => tryCatch(removeAll)); async function createHexagon() { // This function gets the collection of shapes on the first slide, // and adds a hexagon shape to the collection, while specifying its // location and size. Then it names the shape. await PowerPoint.run(async (context) => { - const shapes = context.presentation.slides.getItemAt(0).shapes; - const hexagon = shapes.addGeometricShape(PowerPoint.GeometricShapeType.hexagon, - { - left: 100, - top: 100, - height: 150, - width: 150 - }); + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + const shapeOptions: PowerPoint.ShapeAddOptions = { + left: 100, + top: 100, + height: 150, + width: 150 + }; + const hexagon: PowerPoint.Shape = shapes.addGeometricShape(PowerPoint.GeometricShapeType.hexagon, shapeOptions); hexagon.name = "Hexagon"; await context.sync(); @@ -36,8 +38,8 @@ script: // This function gets the collection of shapes on the first slide, // gets the first shape in the collection, and resets its size. await PowerPoint.run(async (context) => { - const shapes = context.presentation.slides.getItemAt(0).shapes; - const hexagon = shapes.getItemAt(0); + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + const hexagon: PowerPoint.Shape = shapes.getItemAt(0); hexagon.height = 50; hexagon.width = 50; @@ -49,8 +51,8 @@ script: // This function gets the collection of shapes on the first slide, // gets the first shape in the collection, and resets its location. await PowerPoint.run(async (context) => { - const shapes = context.presentation.slides.getItemAt(0).shapes; - const hexagon = shapes.getItemAt(0); + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + const hexagon: PowerPoint.Shape = shapes.getItemAt(0); hexagon.top = 50; hexagon.left = 150; @@ -63,11 +65,11 @@ script: // and adds a line to the collection, while specifying its // start and end points. Then it names the shape. await PowerPoint.run(async (context) => { - const shapes = context.presentation.slides.getItemAt(0).shapes; + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; // For a line, left and top are the coordinates of the start point, // while height and width are the coordinates of the end point. - const line = shapes.addLine(PowerPoint.ConnectorType.straight, + const line: PowerPoint.Shape = shapes.addLine(PowerPoint.ConnectorType.straight, { left: 400, top: 200, @@ -85,8 +87,8 @@ script: // and adds a text box to the collection, while specifying its text, // location, and size. Then it names the text box. await PowerPoint.run(async (context) => { - const shapes = context.presentation.slides.getItemAt(0).shapes; - const textbox = shapes.addTextBox("Hello!", + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + const textbox: PowerPoint.Shape = shapes.addTextBox("Hello!", { left: 100, top: 300, @@ -105,8 +107,8 @@ script: // location and size. Then it names the shape, sets its text and font // color, and centers it inside the braces. await PowerPoint.run(async (context) => { - const shapes = context.presentation.slides.getItemAt(0).shapes; - const braces = shapes.addGeometricShape(PowerPoint.GeometricShapeType.bracePair, { + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + const braces: PowerPoint.Shape = shapes.addGeometricShape(PowerPoint.GeometricShapeType.bracePair, { left: 100, top: 400, height: 50, @@ -125,8 +127,8 @@ script: // This function gets the collection of shapes on the first slide, // and then iterates through them, deleting each one. await PowerPoint.run(async (context) => { - const slide = context.presentation.slides.getItemAt(0); - const shapes = slide.shapes; + const slide: PowerPoint.Slide = context.presentation.slides.getItemAt(0); + const shapes: PowerPoint.ShapeCollection = slide.shapes; // Load all the shapes in the collection without loading their properties. shapes.load("items/$none"); @@ -151,11 +153,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to create, resize, move, and delete shapes.

- -
+

Try it out

Begin by deleting all shapes that are currently on the slide.

@@ -164,20 +165,16 @@ template: Remove all shapes

-

Create, shrink, and move a shape.

-

-

- @@ -185,21 +182,17 @@ template:

Create other shapes.

-

-

- -

language: html style: @@ -215,15 +208,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/powerpoint/slide-management/add-slides.yaml b/samples/powerpoint/slide-management/add-slides.yaml index 75fe109b1..ab7faeaa3 100644 --- a/samples/powerpoint/slide-management/add-slides.yaml +++ b/samples/powerpoint/slide-management/add-slides.yaml @@ -6,33 +6,38 @@ host: POWERPOINT api_set: PowerPointApi: '1.3' script: - content: | - $("#slide-masters").click(() => tryCatch(logSlideMasters)); - $("#add-slide").click(() => tryCatch(addSlide)); + content: |- + document.getElementById("slide-masters").addEventListener("click", () => tryCatch(logSlideMasters)); + document.getElementById("add-slide").addEventListener("click", () => tryCatch(addSlide)); async function addSlide() { - const chosenMaster = $("#master-id").val() as string; - const chosenLayout = $("#layout-id").val() as string; + const chosenMaster = (document.getElementById("master-id") as HTMLInputElement).value; + const chosenLayout = (document.getElementById("layout-id") as HTMLInputElement).value; await PowerPoint.run(async function(context) { - context.presentation.slides.add({ - slideMasterId: chosenMaster, - layoutId: chosenLayout - }); + // Create a new slide using an existing master slide and layout. + const newSlideOptions: PowerPoint.AddSlideOptions = { + slideMasterId: chosenMaster, /* An ID from `Presentation.slideMasters`. */ + layoutId: chosenLayout /* An ID from `SlideMaster.layouts`. */ + }; + context.presentation.slides.add(newSlideOptions); await context.sync(); }); } async function logSlideMasters() { await PowerPoint.run(async function(context) { - const slideMasters = context.presentation.slideMasters.load("id, name, layouts/items/name, layouts/items/id"); - + // Load information about all the slide masters and associated layouts. + const slideMasters: PowerPoint.SlideMasterCollection = context.presentation.slideMasters.load("id, name, layouts/items/name, layouts/items/id"); await context.sync(); + // Log the name and ID of each slide master. for (let i = 0; i < slideMasters.items.length; i++) { console.log("Master name: " + slideMasters.items[i].name); console.log("Master ID: " + slideMasters.items[i].id); - const layoutsInMaster = slideMasters.items[i].layouts; + + // Log the name and ID of each slide layout in the slide master. + const layoutsInMaster: PowerPoint.SlideLayoutCollection = slideMasters.items[i].layouts; for (let j = 0; j < layoutsInMaster.items.length; j++) { console.log(" Layout name: " + layoutsInMaster.items[j].name + " Layout ID: " + layoutsInMaster.items[j].id); } @@ -52,34 +57,29 @@ script: language: typescript template: content: |- -
+

This sample shows how to add a slide and optionally to specify the slide master and layout of the slide.

- -
+

Try it out

On the Home ribbon, open the New Slide drop down menu to see the slide masters and slide layouts in the presentation. Be sure there are at least two slide masters. To add a master, see Use multiple slide masters in one presentation. The page will open in your browser.

-

Press Add slide to add a slide with the default layout of the default slide master to the end of the presentation.

-

Press Log slide masters info to log to the console a list of all the slide masters, their child layouts, and the IDs of the masters and the layouts.

-

Copy one of the slide master IDs from the console and enter it in the Master ID text box. (Example: 6147483651#7142061614)

-

Copy one of the layout IDs from the console, under the same master you choose above, and enter it in the Layout ID text box. (Example: 2147483651#3142061614)

-

Press Add slide again to add a slide with the corresponding master and layout.

+
language: html @@ -96,15 +96,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/powerpoint/slide-management/export-import-slide.yaml b/samples/powerpoint/slide-management/export-import-slide.yaml new file mode 100644 index 000000000..20ba32a3a --- /dev/null +++ b/samples/powerpoint/slide-management/export-import-slide.yaml @@ -0,0 +1,306 @@ +order: 5 +id: powerpoint-slide-management-export-import-slide +name: Export and import slide +description: Shows how to export and import a slide. +host: POWERPOINT +api_set: + PowerPointApi: '1.8' +script: + content: | + document.getElementById("export-slide-button").addEventListener("click", () => tryCatch(exportSlide)); + document.getElementById("clear-exported-slide-button").addEventListener("click", () => tryCatch(clearExportedSlide)); + document.getElementById("import-slide-button").addEventListener("click", () => tryCatch(importSlide)); + document.getElementById("slide-image-button").addEventListener("click", () => tryCatch(addSlideImageToNewSlide)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + async function exportSlide() { + // Exports current slide. + await PowerPoint.run(async (context) => { + const slide = context.presentation.getSelectedSlides().getItemAt(0); + const slideBase64DataResult = slide.exportAsBase64(); + const imageBase64DataResult = slide.getImageAsBase64({ height: 300 }); + await context.sync(); + + localStorage.setItem("exportedSlide", slideBase64DataResult.value); + localStorage.setItem("exportedSlideImage", imageBase64DataResult.value); + + updateSlideImage(imageBase64DataResult.value); + + console.log("Slide was exported."); + }); + } + + function clearExportedSlide() { + // Clears exported slide. + localStorage.removeItem("exportedSlide"); + localStorage.removeItem("exportedSlideImage"); + updateSlideImage(""); + console.log("Exported slide was cleared."); + } + + async function importSlide() { + // Imports the slide that was most recently exported. + const slideBase64Data = localStorage.getItem("exportedSlide"); + if (slideBase64Data === null) { + console.warn("Unable to import. You must first export a slide."); + return; + } + + await PowerPoint.run(async (context) => { + const currentSlide = context.presentation.getSelectedSlides().getItemAt(0); + currentSlide.load("id"); + await context.sync(); + + context.presentation.insertSlidesFromBase64(slideBase64Data, { targetSlideId: currentSlide.id }); + }); + } + + async function getSlideImage(options?: PowerPoint.SlideGetImageOptions): Promise { + // Gets slide image. + return PowerPoint.run(async (context) => { + const slide = context.presentation.getSelectedSlides().getItemAt(0); + const imageBase64Result = slide.getImageAsBase64(options); + await context.sync(); + + return imageBase64Result.value; + }); + } + + async function getImageDimensions(base64Data: string): Promise<{ width: number; height: number }> { + // Gets image dimensions. + return new Promise((resolve, reject) => { + const image = new Image(); + image.onerror = () => { + reject(); + }; + image.onload = () => { + resolve({ width: image.width, height: image.height }); + }; + image.src = `data:image/png;base64,${base64Data}`; + }); + } + + async function addSlideWithImage(imageBase64): Promise { + // Adds a new slide including an image. + return PowerPoint.run(async (context) => { + const presentation = context.presentation; + const currentSlide = presentation.getSelectedSlides().getItemAt(0); + const slideCountResult = context.presentation.slides.getCount(); + + currentSlide.layout.load(); + await context.sync(); + + const slideCount = slideCountResult.value; + + console.log(`Adding slide using layout ${currentSlide.layout.id}`); + + // Add a new slide at the end of the presentation. + context.presentation.slides.add({ layoutId: currentSlide.layout.id }); + try { + await context.sync(); + } catch (err) { + console.error(`Unable to add slide (with layout from current slide). ${err}`); + + // Try adding without specifying the layout. + context.presentation.slides.add(); + + try { + await context.sync(); + } catch (err) { + console.error(`Unable to add slide. ${err}`); + throw err; + } + } + + console.log("Slide added"); + + // Get added slide. + const slide = context.presentation.slides.getItemAt(slideCount); + + slide.load(["id"]); + + await context.sync(); + + console.log(`Added slide id: ${slide.id}`); + + // Switch to the new slide. + context.presentation.setSelectedSlides([slide.id]); + try { + await context.sync(); + } catch (err) { + console.error(`Unable to switch to the new slide. ${err}`); + throw err; + } + + console.log("Switched to the added slide."); + + const activeSlide = context.presentation.getSelectedSlides().getItemAt(0); + activeSlide.load(["id"]); + await context.sync(); + + console.log(`Active slide id: ${activeSlide.id}`); + + const imageDimensions = await getImageDimensions(imageBase64); + const shapeAddOptions = { + height: imageDimensions.height, + width: imageDimensions.width + }; + + let shape; + + shape = await addImageToCurrentSlide(imageBase64); + shape.load(["id"]); + await context.sync(); + + // Select the added image. + activeSlide.setSelectedShapes([shape.id]); + await context.sync(); + }); + } + + async function addImageToCurrentSlide( + imageBase64: string, + options?: PowerPoint.ShapeAddOptions + ): Promise { + // Adds an image to the current slide. + const setSelectedDataOptions: Office.SetSelectedDataOptions = { + coercionType: Office.CoercionType.Image + }; + if (options) { + if (options.height) { + setSelectedDataOptions.imageHeight = options.height; + } + if (options.left) { + setSelectedDataOptions.imageLeft = options.left; + } + if (options.top) { + setSelectedDataOptions.imageTop = options.top; + } + if (options.width) { + setSelectedDataOptions.imageWidth = options.width; + } + } + + return new Promise((resolve, reject) => { + Office.context.document.setSelectedDataAsync( + imageBase64, + setSelectedDataOptions, + async (result: Office.AsyncResult) => { + if (result.error) { + console.error(`ERROR in setSelectedDataAsync(): ${result.error}`); + reject(result.error); + } else { + const shape = await PowerPoint.run(async (context) => { + const slide = context.presentation.getSelectedSlides().getItemAt(0); + slide.shapes.load(); + await context.sync(); + + return slide.shapes.items[slide.shapes.items.length - 1]; + }); + resolve(shape); + } + } + ); + }); + } + + async function addSlideImageToNewSlide() { + // Adds an image of current slide to the new slide. + const imageBase64 = await getSlideImage({ height: 500 }); + + await addSlideWithImage(imageBase64); + } + + function updateSlideImage(imageBase64: string) { + const slideImageElement = document.getElementById("slide-image") as HTMLImageElement; + slideImageElement.src = imageBase64 ? `data:image/png;base64,${imageBase64}` : ""; + } + + async function setup() { + await PowerPoint.run(async (context) => { + // Adds a new slide with some content. + const slideCountResult = context.presentation.slides.getCount(); + context.presentation.slides.add(); + await context.sync(); + + const newSlide = context.presentation.slides.getItemAt(slideCountResult.value); + newSlide.load("id"); + newSlide.shapes.addGeometricShape(PowerPoint.GeometricShapeType.hexagon); + await context.sync(); + + console.log(`Added slide - ID: ${newSlide.id}`); + + // Switch to the new slide. + context.presentation.setSelectedSlides([newSlide.id]); + await context.sync(); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+ This sample demonstrates how to export and import a slide. +
+
+

Set up

+ +
+
+

Try it out

+ + + +

Once a slide has been exported, click the Import slide button to insert into the presentation.

+

To add it to a different presentation, open that presentation and select a slide. It will be inserted after the + selected slide.

+
+

Click the following button to capture an image of the current slide and add it to a new slide at the end of the presentation.

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + + img { + border: 5px solid #555; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + @types/office-js + + office-ui-fabric-js@1.4.0/dist/css/fabric.min.css + office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css + + core-js@2.4.1/client/core.min.js + @types/core-js diff --git a/samples/powerpoint/slide-management/get-set-slides.yaml b/samples/powerpoint/slide-management/get-set-slides.yaml index 7096e5448..9010a097e 100644 --- a/samples/powerpoint/slide-management/get-set-slides.yaml +++ b/samples/powerpoint/slide-management/get-set-slides.yaml @@ -1,17 +1,17 @@ order: 4 id: powerpoint-slide-management-get-set-slides -name: 'Get, set, load, and save slides' +name: Get, set, load, and save slides description: Get and set one or more selected slides. Load and save one or more slides. host: POWERPOINT api_set: PowerPointApi: '1.5' script: content: |- - $("#getSelectedSlides").click(() => tryCatch(getSelectedSlides)); - $("#setSelectedSlides").click(() => tryCatch(setSelectedSlides)); - $("#deleteSlides").click(() => tryCatch(deleteSlides)); - $("#saveSlideSelection").click(() => tryCatch(saveSlideSelection)); - $("#loadSlideSelection").click(() => tryCatch(loadSlideSelection)); + document.getElementById("getSelectedSlides").addEventListener("click", () => tryCatch(getSelectedSlides)); + document.getElementById("setSelectedSlides").addEventListener("click", () => tryCatch(setSelectedSlides)); + document.getElementById("deleteSlides").addEventListener("click", () => tryCatch(deleteSlides)); + document.getElementById("saveSlideSelection").addEventListener("click", () => tryCatch(saveSlideSelection)); + document.getElementById("loadSlideSelection").addEventListener("click", () => tryCatch(loadSlideSelection)); async function getSelectedSlides() { // Gets the selected slides and displays their IDs on the task pane. @@ -23,15 +23,17 @@ script: const allSlidesCount = context.presentation.slides.getCount(); context.presentation.slides.load("items"); await context.sync(); - let allSlideItems = context.presentation.slides.items; + let allSlideItems: PowerPoint.Slide[] = context.presentation.slides.items; allSlideItems.map((slide, index) => { allSlidesList[slide.id] = `Slide ${index + 1}`; }); - if ($("#id-check-usenative").is(":checked")) { + const checkbox = document.getElementById("id-check-usenative") as HTMLInputElement; + if (checkbox && checkbox.checked) { context.presentation.load("tags"); } - const slides = context.presentation.getSelectedSlides(); + + const slides: PowerPoint.SlideScopedCollection = context.presentation.getSelectedSlides(); const slideCount = slides.getCount(); slides.load("items"); await context.sync(); @@ -42,8 +44,9 @@ script: finalTable += "" + index + " - " + allSlidesList[slide.id] + "" + slide.id + ""; }); finalTable += ""; - $("#outputSpan").empty(); - $("#outputSpan").append(finalTable); + const outputSpan = document.getElementById("outputSpan"); + outputSpan.innerHTML = "" + outputSpan.innerHTML += finalTable; }); } async function deleteSlides() { @@ -51,7 +54,7 @@ script: await PowerPoint.run(async (context) => { context.presentation.load("slides"); await context.sync(); - const slides = context.presentation.getSelectedSlides(); + const slides: PowerPoint.SlideScopedCollection = context.presentation.getSelectedSlides(); const slideCount = slides.getCount(); slides.load("items"); await context.sync(); @@ -66,9 +69,9 @@ script: await PowerPoint.run(async (context) => { context.presentation.load("slides"); await context.sync(); - const slide2 = context.presentation.slides.getItemAt(1); - const slide4 = context.presentation.slides.getItemAt(3); - const slide5 = context.presentation.slides.getItemAt(4); + const slide2: PowerPoint.Slide = context.presentation.slides.getItemAt(1); + const slide4: PowerPoint.Slide = context.presentation.slides.getItemAt(3); + const slide5: PowerPoint.Slide = context.presentation.slides.getItemAt(4); slide2.load("id"); slide4.load("id"); slide5.load("id"); @@ -91,7 +94,7 @@ script: let finalTable = ""; context.presentation.load("slides"); await context.sync(); - const slides = context.presentation.getSelectedSlides(); + const slides: PowerPoint.SlideScopedCollection = context.presentation.getSelectedSlides(); const slideCount = slides.getCount(); await context.sync(); finalTable += "
getSelectedSlides.getCount returned:" + slideCount.value + "
"; @@ -105,8 +108,9 @@ script: savedSlideSelection.push(slide.id); }); finalTable += ""; - $("#outputSpan").empty(); - $("#outputSpan").append(finalTable); + const outputSpan = document.getElementById("outputSpan"); + outputSpan.innerHTML = "" + outputSpan.innerHTML += finalTable; }); } @@ -129,12 +133,11 @@ script: } language: typescript template: - content: | -
+ content: |- +

This sample shows how to get selected slides, and how to select specific slides.

- -
+

Try it out


@@ -145,7 +148,7 @@ template:
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -164,15 +167,9 @@ style: transition: max-height 0.2s ease-out; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/powerpoint/slide-management/get-slide-metadata.yaml b/samples/powerpoint/slide-management/get-slide-metadata.yaml index c507d2d43..9a83ed396 100644 --- a/samples/powerpoint/slide-management/get-slide-metadata.yaml +++ b/samples/powerpoint/slide-management/get-slide-metadata.yaml @@ -1,13 +1,13 @@ order: 3 id: powerpoint-basics-get-slide-metadata name: Get slide metadata -description: 'Gets the title, index, and ID of the selected slide(s).' +description: Gets the title, index, and ID of the selected slides. author: OfficeDev host: POWERPOINT api_set: {} script: content: |- - $("#get-slide-metadata").click(getSlideMetadata); + document.getElementById("get-slide-metadata").addEventListener("click", getSlideMetadata); function getSlideMetadata() { Office.context.document.getSelectedDataAsync(Office.CoercionType.SlideRange, @@ -23,11 +23,10 @@ script: language: typescript template: content: |- -
+

Demonstrates how to get slide metadata.

Select one or more slides and click Get slide metadata to get the ID, title, and index of the slide(s).

- @@ -43,17 +42,11 @@ style: margin-bottom: 5px; margin-left: 20px; min-width: 80px; - } + } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/powerpoint/slide-management/insert-slides.yaml b/samples/powerpoint/slide-management/insert-slides.yaml index 73b182b99..399523abf 100644 --- a/samples/powerpoint/slide-management/insert-slides.yaml +++ b/samples/powerpoint/slide-management/insert-slides.yaml @@ -4,12 +4,12 @@ name: Insert slides from other presentation description: Inserts slides from another PowerPoint file into the current presentation. host: POWERPOINT api_set: - PowerPointApi: '1.2' + PowerPointApi: '1.5' script: - content: | - $("#insert-all-slides").click(() => tryCatch(insertAllSlides)); - $("#insert-after-target-slide").click(() => tryCatch(insertAfterSelectedSlide)); - $("#file").change(() => tryCatch(storeFileAsBase64)); + content: |- + document.getElementById("insert-all-slides").addEventListener("click", () => tryCatch(insertAllSlides)); + document.getElementById("insert-after-target-slide").addEventListener("click", () => tryCatch(insertAfterSelectedSlide)); + document.getElementById("file").addEventListener("change", () => tryCatch(storeFileAsBase64)); let chosenFileBase64; @@ -39,37 +39,22 @@ script: async function insertAfterSelectedSlide() { await PowerPoint.run(async function(context) { - const selectedSlideID = await getSelectedSlideID(); + // Get the ID of the first selected slide. + const presentation: PowerPoint.Presentation = context.presentation; + const selected: PowerPoint.Slide = presentation.getSelectedSlides().getItemAt(0); + selected.load("id"); + await context.sync(); - context.presentation.insertSlidesFromBase64(chosenFileBase64, { + // Insert the other presentation after the selected slide. + const insertOptions: PowerPoint.InsertSlideOptions = { formatting: PowerPoint.InsertSlideFormatting.useDestinationTheme, - targetSlideId: selectedSlideID + "#" - }); + targetSlideId: selected.id + }; + presentation.insertSlidesFromBase64(chosenFileBase64, insertOptions); await context.sync(); }); } - function getSelectedSlideID() { - // Wrap a call of one of the Common APIs in a Promise-returning - // function, so that it can be easily called within a run() function - // of an application-specific API. - return new OfficeExtension.Promise(function(resolve, reject) { - Office.context.document.getSelectedDataAsync(Office.CoercionType.SlideRange, function(asyncResult) { - try { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - reject(console.error(asyncResult.error.message)); - } else { - const result = asyncResult.value as any; - resolve(result.slides[0].id); - } - } - catch (error) { - reject(console.log(error)); - } - }); - }); - } - /** Default helper for invoking an action and handling errors. */ async function tryCatch(callback) { try { @@ -83,11 +68,10 @@ script: language: typescript template: content: |- -
+

This sample shows how to insert slides from another presentation into the current presentation.

- -
+

Try it out

    @@ -108,7 +92,7 @@ template: -

    To undo an insertion, click anywhere on the presentation and press Ctrl-Z.

    +

    To undo an insertion, click anywhere on the presentation and press Ctrl+Z.

language: html style: @@ -124,15 +108,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/powerpoint/tags/tags.yaml b/samples/powerpoint/tags/tags.yaml index 52fda7222..45aa7828a 100644 --- a/samples/powerpoint/tags/tags.yaml +++ b/samples/powerpoint/tags/tags.yaml @@ -5,13 +5,13 @@ host: POWERPOINT api_set: PowerPointApi: '1.3' script: - content: | - $("#add-selected-slide-tag").click(() => tryCatch(addTagToSelectedSlide)); - $("#delete-slides-by-audience").click(() => tryCatch(deleteSlidesByAudience)); - $("#add-slide-tags").click(() => tryCatch(addMultipleSlideTags)); - $("#add-shape-tag").click(() => tryCatch(addShapeTag)); - $("#add-presentation-tag").click(() => tryCatch(addPresentationTag)); - $("#delete-presentation-tag").click(() => tryCatch(deletePresentationTag)); + content: |- + document.getElementById("add-selected-slide-tag").addEventListener("click", () => tryCatch(addTagToSelectedSlide)); + document.getElementById("delete-slides-by-audience").addEventListener("click", () => tryCatch(deleteSlidesByAudience)); + document.getElementById("add-slide-tags").addEventListener("click", () => tryCatch(addMultipleSlideTags)); + document.getElementById("add-shape-tag").addEventListener("click", () => tryCatch(addShapeTag)); + document.getElementById("add-presentation-tag").addEventListener("click", () => tryCatch(addPresentationTag)); + document.getElementById("delete-presentation-tag").addEventListener("click", () => tryCatch(deletePresentationTag)); async function addTagToSelectedSlide() { await PowerPoint.run(async function(context) { @@ -20,12 +20,12 @@ script: // Decrement because the getSelectedSlideByIndex method is 1-based, // but the getItemAt method is 0-based. selectedSlideIndex = selectedSlideIndex - 1; - const slide = context.presentation.slides.getItemAt(selectedSlideIndex); + const slide: PowerPoint.Slide = context.presentation.slides.getItemAt(selectedSlideIndex); slide.tags.add("CUSTOMER_TYPE", "Premium"); await context.sync(); - const audienceTag = slide.tags.getItem("CUSTOMER_TYPE"); + const audienceTag: PowerPoint.Tag = slide.tags.getItem("CUSTOMER_TYPE"); audienceTag.load("key, value"); await context.sync(); @@ -56,7 +56,7 @@ script: async function deleteSlidesByAudience() { await PowerPoint.run(async function(context) { - const slides = context.presentation.slides; + const slides: PowerPoint.SlideCollection = context.presentation.slides; slides.load("tags/key, tags/value"); await context.sync(); @@ -64,7 +64,7 @@ script: for (let i = 0; i < slides.items.length; i++) { let currentSlide = slides.items[i]; for (let j = 0; j < currentSlide.tags.items.length; j++) { - let currentTag = currentSlide.tags.items[j]; + let currentTag: PowerPoint.Tag = currentSlide.tags.items[j]; if (currentTag.key === "CUSTOMER_TYPE" && currentTag.value === "Premium") { currentSlide.delete(); } @@ -77,7 +77,7 @@ script: async function addMultipleSlideTags() { await PowerPoint.run(async function(context) { - const slide = context.presentation.slides.getItemAt(0); + const slide: PowerPoint.Slide = context.presentation.slides.getItemAt(0); slide.tags.add("OCEAN", "Indian"); slide.tags.add("PLANET", "Jupiter"); slide.tags.add("CONTINENT", "Antarctica"); @@ -96,13 +96,13 @@ script: async function addShapeTag() { await PowerPoint.run(async function(context) { - const slide = context.presentation.slides.getItemAt(0); - const shape = slide.shapes.getItemAt(0); + const slide: PowerPoint.Slide = context.presentation.slides.getItemAt(0); + const shape: PowerPoint.Shape = slide.shapes.getItemAt(0); shape.tags.add("MOUNTAIN", "Denali"); await context.sync(); - const myShapeTag = shape.tags.getItem("MOUNTAIN"); + const myShapeTag: PowerPoint.Tag = shape.tags.getItem("MOUNTAIN"); myShapeTag.load("key, value"); await context.sync(); @@ -113,12 +113,12 @@ script: async function addPresentationTag() { await PowerPoint.run(async function (context) { - let presentationTags = context.presentation.tags; + let presentationTags: PowerPoint.TagCollection = context.presentation.tags; presentationTags.add("COLOR", "blue"); await context.sync(); - const tag = presentationTags.getItem("COLOR"); + const tag: PowerPoint.Tag = presentationTags.getItem("COLOR"); tag.load("key, value"); await context.sync(); @@ -129,7 +129,7 @@ script: async function deletePresentationTag() { await PowerPoint.run(async function (context) { - let presentationTags = context.presentation.tags; + let presentationTags: PowerPoint.TagCollection = context.presentation.tags; presentationTags.delete("COLOR"); @@ -151,41 +151,32 @@ script: language: typescript template: content: |- -
+

These snippets show how to use tags with the presentation and its slides and shapes.

- -
+

Try it out

-

1. Add several slides to the deck. Add content to each so they are visually distinct in the thumbnail pane.

-

2. Select a single slide and press Add tag to tag the slide to be shown only to premium customers.

-

3. Repeat step 2 for another slide.

-

4. Press Delete premium customer slides to remove from the presentation slides that should only be shown to premium customers.

-

5. Press Add slide tags to add mulitiple tags to the first slide of the presentation.

-

6. Select the first slide and on the ribbon, navigate Insert > Illustrations > Shapes to add a shape to it. Press Add shape tag.

-

7. Press Add presentation tag.

-

8. Press Delete presentation tag.


@@ -162,7 +164,7 @@ template:
language: html style: - content: | + content: |- section.samples { margin-top: 20px; } @@ -181,15 +183,9 @@ style: transition: max-height 0.2s ease-out; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/project/basics/basic-common-api-call.yaml b/samples/project/basics/basic-common-api-call.yaml index 5e15a37cc..9a1b68aa0 100644 --- a/samples/project/basics/basic-common-api-call.yaml +++ b/samples/project/basics/basic-common-api-call.yaml @@ -7,8 +7,8 @@ host: PROJECT api_set: Selection: 1.1 script: - content: | - $("#run").click(run); + content: |- + document.getElementById("run").addEventListener("click", run); function run() { Office.context.document.getSelectedDataAsync(Office.CoercionType.Text, (asyncResult) => { @@ -21,24 +21,17 @@ script: } language: typescript template: - content: | + content: |- language: html style: - content: | - /* Your style goes here */ + content: /* Your style goes here */ language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/project/default.yaml b/samples/project/default.yaml index 4e90aaa56..11f70dd5e 100644 --- a/samples/project/default.yaml +++ b/samples/project/default.yaml @@ -5,8 +5,8 @@ author: OfficeDev host: PROJECT api_set: {} script: - content: | - $("#run").click(run); + content: |- + document.getElementById("run").addEventListener("click", run); function run() { Office.context.document.getSelectedDataAsync(Office.CoercionType.Text, (asyncResult) => { @@ -19,7 +19,7 @@ script: } language: typescript template: - content: | + content: |- @@ -37,15 +37,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/web/default.yaml b/samples/web/default.yaml index b8b93782f..dba053526 100644 --- a/samples/web/default.yaml +++ b/samples/web/default.yaml @@ -5,15 +5,15 @@ author: OfficeDev host: WEB api_set: {} script: - content: | - $("#run").click(run); + content: |- + document.getElementById("run").addEventListener("click", run); function run() { console.log("Your code goes here"); } language: typescript template: - content: | + content: |- @@ -31,12 +31,6 @@ style: min-width: 80px; } language: css -libraries: | - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file +libraries: |- + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/01-basics/basic-api-call-es5.yaml b/samples/word/01-basics/basic-api-call-es5.yaml index c27dbdf75..29b33f94a 100644 --- a/samples/word/01-basics/basic-api-call-es5.yaml +++ b/samples/word/01-basics/basic-api-call-es5.yaml @@ -8,7 +8,7 @@ api_set: WordApi: '1.1' script: content: |- - $("#run").click(() => tryCatch(run)); + document.getElementById("run").addEventListener("click", () => tryCatch(run)); function run() { return Word.run(function (context) { @@ -23,7 +23,7 @@ script: }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. function tryCatch(callback) { Promise.resolve() .then(callback) @@ -35,7 +35,7 @@ script: language: typescript template: content: |- -
+
This sample executes a code snippet that prints the selected text to the console. Make sure to enter and select text before clicking "Print selection".
- -
+

Try it out

Register event handler.
- -
+

Try it out

1. Insert content controls.
- -
+

Try it out

Insert content controls.
- -
+

Try it out

1. Insert content controls.
- -
+

Try it out

1. Insert content controls.
- -
+

Try it out

1. Insert content controls. +
+
+

Try it out

+ + + + + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml b/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml new file mode 100644 index 000000000..2904ffa23 --- /dev/null +++ b/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml @@ -0,0 +1,240 @@ +order: 8 +id: word-content-controls-insert-and-change-checkbox-content-control +name: Manage checkbox content controls +description: Inserts, updates, retrieves, and deletes checkbox content controls. +host: WORD +api_set: + WordApi: '1.7' +script: + content: |- + document.getElementById("insert-controls").addEventListener("click", () => tryCatch(insertCheckboxContentControls)); + document.getElementById("toggle-control").addEventListener("click", () => tryCatch(toggleCheckboxContentControl)); + document.getElementById("change-controls").addEventListener("click", () => tryCatch(toggleCheckboxContentControls)); + document.getElementById("delete-control").addEventListener("click", () => tryCatch(deleteCheckboxContentControl)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + async function insertCheckboxContentControls() { + // Traverses each paragraph of the document and places a checkbox content control at the beginning of each. + await Word.run(async (context) => { + let paragraphs = context.document.body.paragraphs; + paragraphs.load("$none"); // Don't need any properties; just start each paragraph with a content control. + + await context.sync(); + + for (let i = 0; i < paragraphs.items.length; i++) { + let contentControl = paragraphs.items[i] + .getRange(Word.RangeLocation.start) + .insertContentControl(Word.ContentControlType.checkBox); + } + console.log("Checkbox content controls inserted: " + paragraphs.items.length); + + await context.sync(); + }); + } + + async function toggleCheckboxContentControl() { + // Toggles the isChecked property of the first checkbox content control found in the selection. + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.checkBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,checkboxContentControl/isChecked"); + + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,checkboxContentControl/isChecked"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.checkBox) { + console.warn("No checkbox content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + + const isCheckedBefore = selectedContentControl.checkboxContentControl.isChecked; + console.log("isChecked state before:", `id: ${selectedContentControl.id} ... isChecked: ${isCheckedBefore}`); + selectedContentControl.checkboxContentControl.isChecked = !isCheckedBefore; + selectedContentControl.load("id,checkboxContentControl/isChecked"); + await context.sync(); + + console.log( + "isChecked state after:", + `id: ${selectedContentControl.id} ... isChecked: ${selectedContentControl.checkboxContentControl.isChecked}` + ); + }); + } + + async function toggleCheckboxContentControls() { + // Toggles the isChecked property on all checkbox content controls. + await Word.run(async (context) => { + let contentControls = context.document.getContentControls({ + types: [Word.ContentControlType.checkBox] + }); + contentControls.load("items"); + + await context.sync(); + + const length = contentControls.items.length; + console.log(`Number of checkbox content controls: ${length}`); + + if (length <= 0) { + return; + } + + const checkboxContentControls = []; + for (let i = 0; i < length; i++) { + let contentControl = contentControls.items[i]; + contentControl.load("id,checkboxContentControl/isChecked"); + checkboxContentControls.push(contentControl); + } + + await context.sync(); + + console.log("isChecked state before:"); + const updatedCheckboxContentControls = []; + for (let i = 0; i < checkboxContentControls.length; i++) { + const currentCheckboxContentControl = checkboxContentControls[i]; + const isCheckedBefore = currentCheckboxContentControl.checkboxContentControl.isChecked; + console.log(`id: ${currentCheckboxContentControl.id} ... isChecked: ${isCheckedBefore}`); + + currentCheckboxContentControl.checkboxContentControl.isChecked = !isCheckedBefore; + currentCheckboxContentControl.load("id,checkboxContentControl/isChecked"); + updatedCheckboxContentControls.push(currentCheckboxContentControl); + } + + await context.sync(); + + console.log("isChecked state after:"); + for (let i = 0; i < updatedCheckboxContentControls.length; i++) { + const currentCheckboxContentControl = updatedCheckboxContentControls[i]; + console.log( + `id: ${currentCheckboxContentControl.id} ... isChecked: ${currentCheckboxContentControl.checkboxContentControl.isChecked}` + ); + } + }); + } + + async function deleteCheckboxContentControl() { + // Deletes the first checkbox content control found in the selection. + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.checkBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id"); + + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.checkBox) { + console.warn("No checkbox content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + + console.log(`About to delete checkbox content control with id: ${selectedContentControl.id}`); + selectedContentControl.delete(false); + await context.sync(); + + console.log("Deleted checkbox content control."); + }); + } + + async function setup() { + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph("Task 3", "Start"); + body.insertParagraph("Task 2", "Start"); + body.insertParagraph("Task 1", "Start"); + body.paragraphs.getLast().insertText("Task 4", "Replace"); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + if (error.code === Word.ErrorCodes.itemNotFound) { + console.warn("No checkbox content control is currently selected."); + } else { + console.error(error); + } + } + } + language: typescript +template: + content: |- +
+ This sample demonstrates how to insert, change, and delete checkbox content controls. +
+
+

Set up

+ +
+
+

Try it out

+

+ Insert checkbox content controls on each paragraph. + +

+

+ Modify isChecked property of the first checkbox content control found in your selected content. + +

+

+ Modify isChecked property of all checkbox content controls. + +

+

+ Delete the first checkbox content control found in your selected content. + +

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml b/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml new file mode 100644 index 000000000..5dca81e43 --- /dev/null +++ b/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml @@ -0,0 +1,316 @@ +order: 9 +id: word-content-controls-insert-and-change-combo-box-content-control +name: Manage combo box content controls +description: Inserts, updates, and deletes combo box content controls. +host: WORD +api_set: + WordApi: '1.9' +script: + content: |- + document.getElementById("insert-control").addEventListener("click", () => tryCatch(insertComboBoxContentControl)); + document.getElementById("add-item").addEventListener("click", () => tryCatch(addItemToComboBoxContentControl)); + document.getElementById("get-items").addEventListener("click", () => tryCatch(getListFromComboBoxContentControl)); + document.getElementById("delete-item").addEventListener("click", () => tryCatch(deleteItemFromComboBoxContentControl)); + document.getElementById("delete-list").addEventListener("click", () => tryCatch(deleteListFromComboBoxContentControl)); + document.getElementById("delete-control").addEventListener("click", () => tryCatch(deleteComboBoxContentControl)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + async function insertComboBoxContentControl() { + // Places a combo box content control at the end of the selection. + await Word.run(async (context) => { + let selection = context.document.getSelection(); + selection.getRange(Word.RangeLocation.end).insertContentControl(Word.ContentControlType.comboBox); + await context.sync(); + + console.log("Combo box content control inserted at the end of the selection."); + }); + } + + async function addItemToComboBoxContentControl() { + // Adds the provided list item to the first combo box content control in the selection. + await Word.run(async (context) => { + const listItemText = (document.getElementById("item-to-add") as HTMLInputElement).value.trim(); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.comboBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,comboBoxContentControl"); + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,comboBoxContentControl"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.comboBox) { + console.warn("No combo box content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + + selectedContentControl.comboBoxContentControl.addListItem(listItemText); + await context.sync(); + + console.log(`List item added to control with ID ${selectedContentControl.id}: ${listItemText}`); + }); + } + + async function getListFromComboBoxContentControl() { + // Gets the list items from the first combo box content control found in the selection. + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.comboBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,comboBoxContentControl"); + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,comboBoxContentControl"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.comboBox) { + console.warn("No combo box content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + + let selectedComboBox: Word.ComboBoxContentControl = selectedContentControl.comboBoxContentControl; + selectedComboBox.listItems.load("items"); + await context.sync(); + + const currentItems: Word.ContentControlListItemCollection = selectedComboBox.listItems; + console.log(`The list from the combo box content control with ID ${selectedContentControl.id}:`, currentItems); + }); + } + + async function deleteItemFromComboBoxContentControl() { + // Deletes the provided list item from the first combo box content control in the selection. + await Word.run(async (context) => { + const listItemText = (document.getElementById("item-to-delete") as HTMLInputElement).value.trim(); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.comboBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,comboBoxContentControl"); + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,comboBoxContentControl"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.comboBox) { + console.warn("No combo box content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + + let selectedComboBox: Word.ComboBoxContentControl = selectedContentControl.comboBoxContentControl; + selectedComboBox.listItems.load("items/*"); + await context.sync(); + + let listItems: Word.ContentControlListItemCollection = selectedContentControl.comboBoxContentControl.listItems; + let itemToDelete: Word.ContentControlListItem = listItems.items.find((item) => item.displayText === listItemText); + if (!itemToDelete) { + console.warn(`List item doesn't exist in control with ID ${selectedContentControl.id}: ${listItemText}`); + return; + } + + itemToDelete.delete(); + await context.sync(); + + console.log(`List item deleted from control with ID ${selectedContentControl.id}: ${listItemText}`); + }); + } + + async function deleteListFromComboBoxContentControl() { + // Deletes the list items from first combo box content control found in the selection. + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.comboBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,comboBoxContentControl"); + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,comboBoxContentControl"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.comboBox) { + console.warn("No combo box content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + + console.log(`About to delete the list from the combo box content control with ID ${selectedContentControl.id}`); + selectedContentControl.comboBoxContentControl.deleteAllListItems(); + await context.sync(); + + console.log("Deleted the list from the combo box content control."); + }); + } + + async function deleteComboBoxContentControl() { + // Deletes the first combo box content control found in the selection. + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.comboBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id"); + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.comboBox) { + console.warn("No combo box content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + + console.log(`About to delete combo box content control with ID ${selectedContentControl.id}`); + selectedContentControl.delete(false); + await context.sync(); + + console.log("Deleted combo box content control."); + }); + } + + async function setup() { + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph("One more paragraph.", "Start"); + body.insertParagraph("Inserting another paragraph.", "Start"); + body.insertParagraph( + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", + "Start" + ); + body.paragraphs + .getLast() + .insertText( + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", + "Replace" + ); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + if (error.code === Word.ErrorCodes.itemNotFound) { + console.warn("No combo box content control is currently selected."); + } else { + console.error(error); + } + } + } + language: typescript +template: + content: |- +
+ This sample demonstrates how to insert, change, and delete combo box content controls. +
+
+

Set up

+ +
+
+

Try it out

+

+ Insert a combo box content control after selected text. + +

+

+

Add a unique list item to the first combo box content control found in your selected + content. +
+ + + +

+

+ Get all list items from the first combo box content control found in your selected content. + +

+

+

Delete a list item from the first combo box content control found in your selected + content. +
+ + + +

+

+ Delete all list items from the first combo box content control found in your selected content. + +

+

+ Delete the first combo box content control found in your selected content. + +

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/10-content-controls/insert-and-change-content-controls.yaml b/samples/word/10-content-controls/insert-and-change-content-controls.yaml index 161de751f..00f9ac93e 100644 --- a/samples/word/10-content-controls/insert-and-change-content-controls.yaml +++ b/samples/word/10-content-controls/insert-and-change-content-controls.yaml @@ -1,16 +1,16 @@ order: 1 id: word-content-controls-insert-and-change-content-controls name: Content control basics -description: 'Inserts, updates, and retrieves content controls.' +description: Inserts, updates, and retrieves content controls. author: OfficeDev host: WORD api_set: WordApi: '1.1' script: - content: | - $("#insert-controls").click(() => tryCatch(insertContentControls)); - $("#change-controls").click(() => tryCatch(modifyContentControls)); - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("insert-controls").addEventListener("click", () => tryCatch(insertContentControls)); + document.getElementById("change-controls").addEventListener("click", () => tryCatch(modifyContentControls)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); async function insertContentControls() { // Traverses each paragraph of the document and wraps a content control on each with either a even or odd tags. @@ -47,7 +47,7 @@ script: await context.sync(); for (let i = 0; i < evenContentControls.items.length; i++) { - // Change a few properties and append a paragraph + // Change a few properties and append a paragraph. evenContentControls.items[i].set({ color: "red", title: "Odd ContentControl #" + (i + 1), @@ -57,7 +57,7 @@ script: } for (let j = 0; j < oddContentControls.items.length; j++) { - // Change a few properties and append a paragraph + // Change a few properties and append a paragraph. oddContentControls.items[j].set({ color: "green", title: "Even ContentControl #" + (j + 1), @@ -72,24 +72,24 @@ script: async function setup() { await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.clear(); - body.insertParagraph("One more paragraph. ", "Start"); - body.insertParagraph("Inserting another paragraph. ", "Start"); + body.insertParagraph("One more paragraph.", "Start"); + body.insertParagraph("Inserting another paragraph.", "Start"); body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", "Start" ); body.paragraphs .getLast() .insertText( - "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries. ", + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", "Replace" ); }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -101,18 +101,16 @@ script: language: typescript template: content: |- -
+
This sample demonstrates how to insert and change content control properties.
- -
+

Set up

- -
+

Try it out

Insert content controls on each paragraph. +
+
+

Try it out

+

+ Insert a dropdown list content control after selected text. + +

+

+

Add a unique list item to the first dropdown list content control found in your selected + content. +
+ + + +

+

+ Get all list items from the first dropdown list content control found in your selected content. + +

+

+

Delete a list item from the first dropdown list content control found in your selected + content. +
+ + + +

+

+ Delete all list items from the first dropdown list content control found in your selected content. + +

+

+ Delete the first dropdown list content control found in your selected content. + +

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/15-images/insert-and-get-pictures.yaml b/samples/word/15-images/insert-and-get-pictures.yaml index 7a7a62fa7..a24cb7b69 100644 --- a/samples/word/15-images/insert-and-get-pictures.yaml +++ b/samples/word/15-images/insert-and-get-pictures.yaml @@ -2,15 +2,14 @@ order: 1 id: word-images-insert-and-get-pictures name: Use inline pictures description: Inserts and gets inline pictures. -author: OfficeDev host: WORD api_set: - WordApi: '1.1' + WordApiDesktop: '1.1' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#insert").click(() => tryCatch(insertImage)); - $("#get").click(() => tryCatch(getImage)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("insert").addEventListener("click", () => tryCatch(insertImage)); + document.getElementById("get").addEventListener("click", () => tryCatch(getImage)); async function insertImage() { // Inserts an image anchored to the last paragraph. @@ -27,11 +26,11 @@ script: async function getImage() { // Gets the first image in the document. await Word.run(async (context) => { - const firstPicture = context.document.body.inlinePictures.getFirst(); - firstPicture.load("width, height"); + const firstPicture: Word.InlinePicture = context.document.body.inlinePictures.getFirst(); + firstPicture.load("width, height, imageFormat"); await context.sync(); - console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`); + console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`, `Image format: ${firstPicture.imageFormat}`); // Get the image encoded as Base64. const base64 = firstPicture.getBase64ImageSrc(); @@ -43,22 +42,22 @@ script: async function setup() { // Sets up by adding a dummy paragraph. await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.clear(); body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document. ", + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", "End" ); body.paragraphs .getLast() .insertText( - "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching Online cover page, header, and sidebar. Click Insert and then choose the elements you want from the different Online galleries.", + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", "End" ); }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -73,18 +72,16 @@ script: language: typescript template: content: |- -
+
This sample demonstrates how to insert and get inline pictures in a document.
- -
+

Set up

- -
+

Try it out

- -
+

Try it out

+

+ + + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/20-lists/organize-list.yaml b/samples/word/20-lists/organize-list.yaml index 00113c034..5007a602d 100644 --- a/samples/word/20-lists/organize-list.yaml +++ b/samples/word/20-lists/organize-list.yaml @@ -7,27 +7,28 @@ host: WORD api_set: WordApi: '1.3' script: - content: | - $("#insert-list").click(() => tryCatch(insertOrganizeList)); - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("insert-list").addEventListener("click", () => tryCatch(insertOrganizeList)); + document.getElementById("get-list-props").addEventListener("click", () => tryCatch(getListProps)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); async function insertOrganizeList() { // Inserts a list starting with the first paragraph then set numbering and bullet types of the list items. await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; paragraphs.load("$none"); await context.sync(); // Use the first paragraph to start a new list. - const list = paragraphs.items[0].startNewList(); + const list: Word.List = paragraphs.items[0].startNewList(); list.load("$none"); await context.sync(); // To add new items to the list, use Start or End on the insertLocation parameter. list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + const paragraph: Word.Paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); // Set numbering for list level 1. list.setLevelNumbering(0, Word.ListNumbering.arabic); @@ -41,18 +42,45 @@ script: list.load("levelTypes"); await context.sync(); + }); + } + + async function getListProps() { + // Gets information about the first list in the document. + await Word.run(async (context) => { + const lists: Word.ListCollection = context.document.body.lists; + lists.load("items"); + + await context.sync(); + + if (lists.items.length === 0) { + console.warn("There are no lists in this document."); + return; + } + + // Get the first list. + const list: Word.List = lists.getFirst(); + list.load("levelTypes,levelExistences"); + + await context.sync(); - const levelTypes = list.levelTypes; - console.log("Level types of this list:"); + const levelTypes = list.levelTypes; + console.log("Level types of the first list:"); for (let i = 0; i < levelTypes.length; i++) { console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); } + + const levelExistences = list.levelExistences; + console.log("Level existences of the first list:"); + for (let i = 0; i < levelExistences.length; i++) { + console.log(`- Level ${i + 1} (index ${i}): ${levelExistences[i]}`); + } }); } async function setup() { await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.clear(); body.insertParagraph( "Create a list then customize the numbering and bullets. You can also organize the list items into multiple levels and change the style, alignment, etc.", @@ -61,7 +89,7 @@ script: }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -73,22 +101,23 @@ script: language: typescript template: content: |- -
+
This sample demonstrates how to create and organize a list.
- -
+

Set up

- -
+

Try it out

+
language: html style: @@ -106,13 +135,7 @@ style: language: css libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml b/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml index 5c6bcb403..536f169e4 100644 --- a/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml +++ b/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml @@ -7,15 +7,15 @@ host: WORD api_set: WordApi: '1.1' script: - content: | - $("#get-paragraph").click(() => tryCatch(getParagraph)); - $("#get-sentences").click(() => tryCatch(getSentences)); - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("get-paragraph").addEventListener("click", () => tryCatch(getParagraph)); + document.getElementById("get-sentences").addEventListener("click", () => tryCatch(getSentences)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); async function getParagraph() { await Word.run(async (context) => { // The collection of paragraphs of the current selection returns the full paragraphs contained in it. - const paragraph = context.document.getSelection().paragraphs.getFirst(); + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); paragraph.load("text"); await context.sync(); @@ -26,14 +26,14 @@ script: async function getSentences() { await Word.run(async (context) => { // Get the complete sentence (as range) associated with the insertion point. - const sentences = context.document + const sentences: Word.RangeCollection = context.document .getSelection() .getTextRanges(["."] /* Using the "." as delimiter */, false /*means without trimming spaces*/); sentences.load("$none"); await context.sync(); // Expand the range to the end of the paragraph to get all the complete sentences. - const sentencesToTheEndOfParagraph = sentences.items[0] + const sentencesToTheEndOfParagraph: Word.RangeCollection = sentences.items[0] .getRange() .expandTo( context.document @@ -53,22 +53,22 @@ script: async function setup() { await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.clear(); body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", "Start" ); body.paragraphs .getLast() .insertText( - "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries.", + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", "Replace" ); }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -80,18 +80,16 @@ script: language: typescript template: content: |- -
+
This sample demonstrates how to get the paragraph and paragraph sentences associated with the current insertion point.
- -
+

Set up

- -
+

Try it out

Select an insertion point in the document.

+

+
+

Try it out

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/25-paragraph/get-word-count.yaml b/samples/word/25-paragraph/get-word-count.yaml index 36ddd1817..7ab14f35c 100644 --- a/samples/word/25-paragraph/get-word-count.yaml +++ b/samples/word/25-paragraph/get-word-count.yaml @@ -7,14 +7,14 @@ host: WORD api_set: WordApi: '1.1' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#count").click(() => tryCatch(run)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("count").addEventListener("click", () => tryCatch(run)); async function run() { // Counts how many times each term appears in the document. await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; paragraphs.load("text"); await context.sync(); @@ -63,20 +63,20 @@ script: async function setup() { await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.clear(); body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", "Start" ); body.insertParagraph( - "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries.", + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", "End" ); }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -88,18 +88,16 @@ script: language: typescript template: content: |- -
+
This sample demonstrates how to get the count for words and terms in the document body.
- -
+

Set up

- -
+

Try it out

Get the word/term count.

@@ -122,15 +120,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/25-paragraph/insert-formatted-text.yaml b/samples/word/25-paragraph/insert-formatted-text.yaml index 49dc12016..77dec94c7 100644 --- a/samples/word/25-paragraph/insert-formatted-text.yaml +++ b/samples/word/25-paragraph/insert-formatted-text.yaml @@ -8,16 +8,16 @@ api_set: WordApi: '1.1' script: content: |- - $("#add-text").click(() => tryCatch(addFormattedText)); - $("#add-paragraph").click(() => tryCatch(addFormattedParagraph)); - $("#add-preset").click(() => tryCatch(addPreStyledFormattedText)); + document.getElementById("add-text").addEventListener("click", () => tryCatch(addFormattedText)); + document.getElementById("add-paragraph").addEventListener("click", () => tryCatch(addFormattedParagraph)); + document.getElementById("add-preset").addEventListener("click", () => tryCatch(addPreStyledFormattedText)); async function addFormattedText() { await Word.run(async (context) => { // Insert the sentence, then adjust the formatting. // Note that replace affects the calling object, in this case the entire document body. // A similar method can also be used at the range level. - const sentence = context.document.body.insertText( + const sentence: Word.Range = context.document.body.insertText( "This is some formatted text!", "Replace" ); @@ -34,7 +34,7 @@ script: async function addFormattedParagraph() { await Word.run(async (context) => { // Second sentence, let's insert it as a paragraph after the previously inserted one. - const secondSentence = context.document.body.insertParagraph( + const secondSentence: Word.Paragraph = context.document.body.insertParagraph( "This is the first text with a custom style.", "End" ); @@ -52,7 +52,7 @@ script: async function addPreStyledFormattedText() { await Word.run(async (context) => { - const sentence = context.document.body.insertParagraph( + const sentence: Word.Paragraph = context.document.body.insertParagraph( "To be or not to be", "End" ); @@ -64,7 +64,7 @@ script: }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -76,11 +76,10 @@ script: language: typescript template: content: |- -

+
This sample shows how to insert basic formatted text and apply built-in styles.
- -
+

Try it out

- -
+

Try it out

Apply to all pages

- -
+

Try it out

- -
+

Try it out

+ +

From the console, copy a paragraph ID and paste it into the following field.
+ + + +

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/25-paragraph/onchanged-event.yaml b/samples/word/25-paragraph/onchanged-event.yaml new file mode 100644 index 000000000..833138a41 --- /dev/null +++ b/samples/word/25-paragraph/onchanged-event.yaml @@ -0,0 +1,121 @@ +order: 11 +id: word-paragraph-onchanged-event +name: On changing content in paragraphs +description: Registers, triggers, and deregisters the onParagraphChanged event that tracks when content is changed in paragraphs. +host: WORD +api_set: + WordApi: '1.6' +script: + content: |- + document.getElementById("register-event-handler").addEventListener("click", () => tryCatch(registerEventHandler)); + document.getElementById("get-paragraph-by-id").addEventListener("click", () => tryCatch(getParagraphById)); + document.getElementById("deregister-event-handler").addEventListener("click", () => tryCatch(deregisterEventHandler)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + let eventContext; + + async function registerEventHandler() { + // Registers the onParagraphChanged event handler on the document. + await Word.run(async (context) => { + eventContext = context.document.onParagraphChanged.add(paragraphChanged); + await context.sync(); + + console.log("Added event handler for when content is changed in paragraphs."); + }); + } + + async function paragraphChanged(event: Word.ParagraphChangedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.type} event detected. IDs of paragraphs where content was changed:`, event.uniqueLocalIds); + }); + } + + async function getParagraphById() { + await Word.run(async (context) => { + const paragraphId = (document.getElementById("paragraph-id") as HTMLInputElement).value; + const paragraph: Word.Paragraph = context.document.getParagraphByUniqueLocalId(paragraphId); + paragraph.load(); + await paragraph.context.sync(); + + console.log(paragraph); + }); + } + + async function deregisterEventHandler() { + await Word.run(eventContext.context, async (context) => { + eventContext.remove(); + await context.sync(); + }); + + eventContext = null; + console.log("Removed event handler that was tracking content changes in paragraphs."); + } + + async function setup() { + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph("Paragraph 1", "End"); + body.insertParagraph("Paragraph 2", "End"); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+ This sample demonstrates how to use the onChanged event with paragraphs. +
+
+

Set up

+ +
+
+

Try it out

+ +

+

Within a paragraph, make a change in the text. Then, from the console, copy the paragraph + ID where content was changed and paste into the following field.
+ + + +

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/25-paragraph/ondeleted-event.yaml b/samples/word/25-paragraph/ondeleted-event.yaml new file mode 100644 index 000000000..28643099d --- /dev/null +++ b/samples/word/25-paragraph/ondeleted-event.yaml @@ -0,0 +1,121 @@ +order: 12 +id: word-paragraph-ondeleted-event +name: On deleting paragraphs +description: Registers, triggers, and deregisters the onParagraphDeleted event that tracks the removal of paragraphs. +host: WORD +api_set: + WordApi: '1.6' +script: + content: |- + document.getElementById("register-event-handler").addEventListener("click", () => tryCatch(registerEventHandler)); + document.getElementById("delete-paragraph").addEventListener("click", () => tryCatch(deleteParagraph)); + document.getElementById("deregister-event-handler").addEventListener("click", () => tryCatch(deregisterEventHandler)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + let eventContext; + + async function registerEventHandler() { + // Registers the onParagraphDeleted event handler on the document. + await Word.run(async (context) => { + eventContext = context.document.onParagraphDeleted.add(paragraphDeleted); + await context.sync(); + + console.log("Added event handlers for when paragraphs are deleted."); + }); + } + + async function paragraphDeleted(event: Word.ParagraphDeletedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.type} event detected. IDs of paragraphs that were deleted:`, event.uniqueLocalIds); + }); + } + + async function deleteParagraph() { + await Word.run(async (context) => { + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("items"); + await context.sync(); + + if (paragraphs.items.length == 0) { + console.log("There are no paragraphs in this document."); + } else { + console.log("Paragraph to be deleted:", paragraphs.items[0]); + paragraphs.items[0].delete(); + await context.sync(); + } + }); + } + + async function deregisterEventHandler() { + await Word.run(eventContext.context, async (context) => { + eventContext.remove(); + await context.sync(); + }); + + eventContext = null; + console.log("Removed event handler that was tracking when paragraphs are deleted."); + } + + async function setup() { + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph("Paragraph 1", "End"); + body.insertParagraph("Paragraph 2", "End"); + body.insertParagraph("Paragraph 3", "End"); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+ This sample demonstrates how to use the onDeleted event with paragraphs. +
+
+

Set up

+ +
+
+

Try it out

+ + + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/25-paragraph/paragraph-properties.yaml b/samples/word/25-paragraph/paragraph-properties.yaml index fd51c0c93..43493a296 100644 --- a/samples/word/25-paragraph/paragraph-properties.yaml +++ b/samples/word/25-paragraph/paragraph-properties.yaml @@ -1,18 +1,20 @@ order: 6 id: word-paragraph-paragraph-properties name: Paragraph properties -description: 'Sets indentation, space between paragraphs, and other paragraph properties.' +description: Sets indentation, space between paragraphs, and other paragraph properties. author: OfficeDev host: WORD api_set: - WordApi: '1.2' + WordApi: '1.1' script: - content: | - $("#indent").click(() => tryCatch(indent)); - $("#spacing").click(() => tryCatch(spacing)); - $("#space-after").click(() => tryCatch(spaceAfter)); - $("#align").click(() => tryCatch(align)); - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("indent").addEventListener("click", () => tryCatch(indent)); + document.getElementById("spacing").addEventListener("click", () => tryCatch(spacing)); + document.getElementById("space-after").addEventListener("click", () => tryCatch(spaceAfter)); + document.getElementById("line-unit-spacing-after").addEventListener("click", () => tryCatch(spaceAfterInLines)); + document.getElementById("line-unit-spacing-before").addEventListener("click", () => tryCatch(spaceBeforeInLines)); + document.getElementById("align").addEventListener("click", () => tryCatch(align)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); async function indent() { await Word.run(async (context) => { @@ -34,13 +36,31 @@ script: async function spaceAfter() { await Word.run(async (context) => { - // Adjust space between paragraphs. + // Set the space (in points) after the first paragraph. context.document.body.paragraphs.getFirst().spaceAfter = 20; await context.sync(); }); } + async function spaceAfterInLines() { + await Word.run(async (context) => { + // Set the space (in line units) after the first paragraph. + context.document.body.paragraphs.getFirst().lineUnitAfter = 1; + + await context.sync(); + }); + } + + async function spaceBeforeInLines() { + await Word.run(async (context) => { + // Set the space (in line units) before the first paragraph. + context.document.body.paragraphs.getFirst().lineUnitBefore = 1; + + await context.sync(); + }); + } + async function align() { await Word.run(async (context) => { // Center last paragraph alignment. @@ -52,16 +72,16 @@ script: async function setup() { await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.clear(); body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", "Start" ); body.paragraphs .getLast() .insertText( - "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries.", + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", "Replace" ); body.paragraphs.getFirst().alignment = "Left"; @@ -69,7 +89,7 @@ script: }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -81,18 +101,16 @@ script: language: typescript template: content: |- -
+
This sample demonstrates paragraph property usage.
- -
+

Set up

- -
+

Try it out

+ +

+ +

@@ -123,13 +149,7 @@ style: language: css libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/25-paragraph/search.yaml b/samples/word/25-paragraph/search.yaml index bfc17600e..ea8337044 100644 --- a/samples/word/25-paragraph/search.yaml +++ b/samples/word/25-paragraph/search.yaml @@ -7,15 +7,15 @@ host: WORD api_set: WordApi: '1.1' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#basic-search").click(() => tryCatch(basicSearch)); - $("#wildcard-search").click(() => tryCatch(wildcardSearch)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("basic-search").addEventListener("click", () => tryCatch(basicSearch)); + document.getElementById("wildcard-search").addEventListener("click", () => tryCatch(wildcardSearch)); async function basicSearch() { // Does a basic text search and highlights matches in the document. await Word.run(async (context) => { - const results = context.document.body.search("Online"); + const results : Word.RangeCollection = context.document.body.search("extend"); results.load("length"); await context.sync(); @@ -33,7 +33,7 @@ script: // Does a wildcard search and highlights matches in the document. await Word.run(async (context) => { // Construct a wildcard expression and set matchWildcards to true in order to use wildcards. - const results = context.document.body.search("$*.[0-9][0-9]", { matchWildcards: true }); + const results : Word.RangeCollection = context.document.body.search("$*.[0-9][0-9]", { matchWildcards: true }); results.load("length"); await context.sync(); @@ -50,16 +50,16 @@ script: async function setup() { await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.clear(); body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video ($10,000.00), you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", "Start" ); body.paragraphs .getLast() .insertText( - "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching Online cover page, header, and sidebar. Click Insert and then choose the Online elements you want from the different Online galleries.", + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", "Replace" ); @@ -78,18 +78,16 @@ script: language: typescript template: content: |- -

+
This sample demonstrates basic and advanced search capabilities of the API.
- -
+

Set up

- -
+

Try it out

- -
+

Try it out

+

Compare location of first paragraph with location of second paragraph

+ +

Compare location of second paragraph with cursor's location

+

+

Move cursor or select text in the document.
+ +

language: html style: @@ -89,15 +117,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/35-ranges/get-pages.yaml b/samples/word/35-ranges/get-pages.yaml new file mode 100644 index 000000000..c4b6584a3 --- /dev/null +++ b/samples/word/35-ranges/get-pages.yaml @@ -0,0 +1,288 @@ +order: 4 +id: word-ranges-get-pages +name: Work with pages, panes, and windows +description: Shows how to work with pages, panes, and windows. +author: yilin4 +host: WORD +api_set: + WordApiDesktop: '1.2' +script: + content: | + document.getElementById("get-pages-selected-range").addEventListener("click", () => tryCatch(getPagesOfSelectedRange)); + document + .getElementById("get-pages-third-paragraph") + .addEventListener("click", () => tryCatch(getPagesOfThirdParagraph)); + document + .getElementById("get-pages-enclosing-viewport") + .addEventListener("click", () => tryCatch(getPagesEnclosingViewport)); + document.getElementById("get-all-pages").addEventListener("click", () => tryCatch(getAllPages)); + document.getElementById("get-all-panes").addEventListener("click", () => tryCatch(getAllPanes)); + document.getElementById("get-all-windows").addEventListener("click", () => tryCatch(getAllWindows)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + async function getPagesOfSelectedRange() { + await Word.run(async (context) => { + // Gets pages of the selection. + const pages: Word.PageCollection = context.document.getSelection().pages; + pages.load(); + await context.sync(); + + // Log info for pages included in selection. + console.log(pages); + const pagesIndexes = []; + const pagesText = []; + for (let i = 0; i < pages.items.length; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); + + const range = page.getRange(); + range.load("text"); + pagesText.push(range); + } + + await context.sync(); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Index info for page ${i + 1} in the selection: ${pagesIndexes[i].index}`); + console.log("Text of that page in the selection:", pagesText[i].text); + } + }); + } + + async function getPagesOfThirdParagraph() { + await Word.run(async (context) => { + // Gets the pages that contain the third paragraph. + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load(); + await context.sync(); + + const paraThree = paragraphs.items[2]; + const rangeOfParagraph = paraThree.getRange(); + const pages: Word.PageCollection = rangeOfParagraph.pages; + pages.load(); + await context.sync(); + + // Log info for pages in range. + console.log(pages); + const pagesIndexes = []; + const pagesText = []; + for (let i = 0; i < pages.items.length; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); + + const range = page.getRange(); + range.load("text"); + pagesText.push(range); + } + + await context.sync(); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Index of page ${i + 1} that contains the third paragraph: ${pagesIndexes[i].index}`); + console.log("Text of that page:", pagesText[i].text); + } + }); + } + + async function getPagesEnclosingViewport() { + await Word.run(async (context) => { + // Gets the pages enclosing the viewport. + + // Get the active window. + const activeWindow: Word.Window = context.document.activeWindow; + activeWindow.load(); + + // Get the active pane. + const activePane: Word.Pane = activeWindow.activePane; + activePane.load(); + + // Get pages enclosing the viewport. + const pages: Word.PageCollection = activePane.pagesEnclosingViewport; + pages.load(); + + await context.sync(); + + // Log the number of pages. + const pageCount = pages.items.length; + console.log(`Number of pages enclosing the viewport: ${pageCount}`); + + // Log index info of these pages. + const pagesIndexes = []; + for (let i = 0; i < pageCount; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); + } + + await context.sync(); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Page index: ${pagesIndexes[i].index}`); + } + }); + } + + async function getAllPages() { + await Word.run(async (context) => { + // Gets the first paragraph of each page. + console.log("Getting first paragraph of each page..."); + + // Get the active window. + const activeWindow: Word.Window = context.document.activeWindow; + activeWindow.load(); + + // Get the active pane. + const activePane: Word.Pane = activeWindow.activePane; + activePane.load(); + + // Get all pages. + const pages: Word.PageCollection = activePane.pages; + pages.load(); + + await context.sync(); + + // Get page index and paragraphs of each page. + const pagesIndexes = []; + const pagesNumberOfParagraphs = []; + const pagesFirstParagraphText = []; + for (let i = 0; i < pages.items.length; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); + + const paragraphs = page.getRange().paragraphs; + paragraphs.load("items/length"); + pagesNumberOfParagraphs.push(paragraphs); + + const firstParagraph = paragraphs.getFirst(); + firstParagraph.load("text"); + pagesFirstParagraphText.push(firstParagraph); + } + + await context.sync(); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Page index: ${pagesIndexes[i].index}`); + console.log(`Number of paragraphs: ${pagesNumberOfParagraphs[i].items.length}`); + console.log("First paragraph's text:", pagesFirstParagraphText[i].text); + } + }); + } + + async function getAllPanes() { + await Word.run(async (context) => { + // Gets all the panes in the active document window. + + // Get the active window. + const activeWindow: Word.Window = context.document.activeWindow; + activeWindow.load("panes/items/length"); + + await context.sync(); + + const panes: Word.PaneCollection = activeWindow.panes; + console.log(`Number of panes in the current document window: ${panes.items.length}`); + }); + } + + async function getAllWindows() { + await Word.run(async (context) => { + // Gets the document windows. + const windows: Word.WindowCollection = context.document.windows; + windows.load("windows/items/length"); + + await context.sync(); + + console.log(`Number of windows for this document: ${windows.items.length}`); + }); + } + + async function setup() { + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.clear(); + body.insertBreak(Word.BreakType.page, Word.InsertLocation.end); + body.insertParagraph( + "Themes and styles also help keep your document coordinated. When you click design and choose a new Theme, the pictures, charts, and SmartArt graphics change to match your new theme. When you apply styles, your headings change to match the new theme.", + "End" + ); + body.insertText( + "Save time in Word with new buttons that show up where you need them. To change the way a picture fits in your document, click it and a button for layout options appears next to it. When you work on a table, click where you want to add a row or a column, and then click the plus sign.", + "Start" + ); + body.insertParagraph( + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", + "Start" + ); + body.paragraphs + .getLast() + .insertText( + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", + "Replace" + ); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+ This sample demonstrates how to work with pages, panes, and windows. +
+
+

Set up

+ +
+
+

Try it out

+ + + + + + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: | + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/35-ranges/scroll-to-range.yaml b/samples/word/35-ranges/scroll-to-range.yaml index 6726a96f7..0bea961dd 100644 --- a/samples/word/35-ranges/scroll-to-range.yaml +++ b/samples/word/35-ranges/scroll-to-range.yaml @@ -7,10 +7,10 @@ host: WORD api_set: WordApi: '1.2' script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#scroll").click(() => tryCatch(scroll)); - $("#scroll-end").click(() => tryCatch(scrollEnd)); + content: |- + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("scroll").addEventListener("click", () => tryCatch(scroll)); + document.getElementById("scroll-end").addEventListener("click", () => tryCatch(scrollEnd)); async function scroll() { await Word.run(async (context) => { @@ -32,23 +32,23 @@ script: async function setup() { await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.clear(); - const firstSentence = body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", + const firstSentence: Word.Paragraph = body.insertParagraph( + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", "Start" ); firstSentence.insertBreak(Word.BreakType.page, "After"); body.paragraphs .getLast() .insertText( - "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching Online cover page, header, and sidebar. Click Insert and then choose the Online elements you want from the different Online galleries.", + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", "Replace" ); }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -60,18 +60,16 @@ script: language: typescript template: content: |- -
+
This sample demonstrates how to scroll to a range.
- -
+

Set up

- -
+

Try it out

- -
+

Try it out

+

Use custom style

+ + +

+ +

+ +

+
+

Update custom style

+ +
Note: Mixed and Unknown aren't valid when setting.
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+

Delete custom style

+ + +
+ +
+
+

Import styles from JSON string

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + + .margin { + margin-top: 5px; + margin-bottom: 5px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/40-tables/manage-formatting.yaml b/samples/word/40-tables/manage-formatting.yaml index eff2be977..4031cf690 100644 --- a/samples/word/40-tables/manage-formatting.yaml +++ b/samples/word/40-tables/manage-formatting.yaml @@ -1,58 +1,52 @@ order: 2 id: word-tables-manage-formatting name: Table formatting -description: 'Gets the formatting details of a table, a table row, and a table cell, including borders, alignment, and cell padding.' +description: Gets the formatting details of a table, a table row, and a table cell, including borders, alignment, and cell padding. author: OfficeDev host: WORD api_set: WordApi: '1.3' script: - content: | - $("#get-table-alignment").click(() => tryCatch(getTableAlignment)); - $("#get-table-border").click(() => tryCatch(getTableBorder)); - $("#get-table-cell-padding").click(() => tryCatch(getTableCellPadding)); - $("#get-table-row-alignment").click(() => tryCatch(getTableRowAlignment)); - $("#get-table-row-border").click(() => tryCatch(getTableRowBorder)); - $("#get-table-row-cell-padding").click(() => tryCatch(getTableRowCellPadding)); - $("#get-table-cell-alignment").click(() => tryCatch(getTableCellAlignment)); - $("#get-table-cell-border").click(() => tryCatch(getTableCellBorder)); - $("#get-table-cell-cell-padding").click(() => tryCatch(getTableCellCellPadding)); - $("#setup").click(() => tryCatch(insertTable)); + content: |- + document.getElementById("get-table-alignment").addEventListener("click", () => tryCatch(getTableAlignment)); + document.getElementById("get-table-border").addEventListener("click", () => tryCatch(getTableBorder)); + document.getElementById("get-table-cell-padding").addEventListener("click", () => tryCatch(getTableCellPadding)); + document.getElementById("get-table-row-alignment").addEventListener("click", () => tryCatch(getTableRowAlignment)); + document.getElementById("get-table-row-border").addEventListener("click", () => tryCatch(getTableRowBorder)); + document.getElementById("get-table-row-cell-padding").addEventListener("click", () => tryCatch(getTableRowCellPadding)); + document.getElementById("get-table-cell-alignment").addEventListener("click", () => tryCatch(getTableCellAlignment)); + document.getElementById("get-table-cell-border").addEventListener("click", () => tryCatch(getTableCellBorder)); + document.getElementById("get-table-cell-cell-padding").addEventListener("click", () => tryCatch(getTableCellCellPadding)); + document.getElementById("setup").addEventListener("click", () => tryCatch(insertTable)); async function getTableAlignment() { // Gets alignment details about the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); + const firstTable: Word.Table = context.document.body.tables.getFirst(); firstTable.load(["alignment", "horizontalAlignment", "verticalAlignment"]); await context.sync(); - console.log(`Details about the alignment of the first table:`); - console.log(`- Alignment of the table within the containing page column: ${firstTable.alignment}`); - console.log(`- Horizontal alignment of every cell in the table: ${firstTable.horizontalAlignment}`); - console.log(`- Vertical alignment of every cell in the table: ${firstTable.verticalAlignment}`); + console.log(`Details about the alignment of the first table:`, `- Alignment of the table within the containing page column: ${firstTable.alignment}`, `- Horizontal alignment of every cell in the table: ${firstTable.horizontalAlignment}`, `- Vertical alignment of every cell in the table: ${firstTable.verticalAlignment}`); }); } async function getTableBorder() { // Gets border details about the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); + const firstTable: Word.Table = context.document.body.tables.getFirst(); const borderLocation = Word.BorderLocation.top; - const border = firstTable.getBorder(borderLocation); + const border: Word.TableBorder = firstTable.getBorder(borderLocation); border.load(["type", "color", "width"]); await context.sync(); - console.log(`Details about the ${borderLocation} border of the first table:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + console.log(`Details about the ${borderLocation} border of the first table:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); } async function getTableCellPadding() { // Gets cell padding details about the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); + const firstTable: Word.Table = context.document.body.tables.getFirst(); const cellPaddingLocation = Word.CellPaddingLocation.right; const cellPadding = firstTable.getCellPadding(cellPaddingLocation); await context.sync(); @@ -66,39 +60,34 @@ script: async function getTableRowAlignment() { // Gets content alignment details about the first row of the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstTableRow = firstTable.rows.getFirst(); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); firstTableRow.load(["horizontalAlignment", "verticalAlignment"]); await context.sync(); - console.log(`Details about the alignment of the first table's first row:`); - console.log(`- Horizontal alignment of every cell in the row: ${firstTableRow.horizontalAlignment}`); - console.log(`- Vertical alignment of every cell in the row: ${firstTableRow.verticalAlignment}`); + console.log(`Details about the alignment of the first table's first row:`, `- Horizontal alignment of every cell in the row: ${firstTableRow.horizontalAlignment}`, `- Vertical alignment of every cell in the row: ${firstTableRow.verticalAlignment}`); }); } async function getTableRowBorder() { // Gets border details about the first row of the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstTableRow = firstTable.rows.getFirst(); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); const borderLocation = Word.BorderLocation.bottom; - const border = firstTableRow.getBorder(borderLocation); + const border: Word.TableBorder = firstTableRow.getBorder(borderLocation); border.load(["type", "color", "width"]); await context.sync(); - console.log(`Details about the ${borderLocation} border of the first table's first row:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + console.log(`Details about the ${borderLocation} border of the first table's first row:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); } async function getTableRowCellPadding() { // Gets cell padding details about the first row of the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstTableRow = firstTable.rows.getFirst(); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); const cellPaddingLocation = Word.CellPaddingLocation.bottom; const cellPadding = firstTableRow.getCellPadding(cellPaddingLocation); await context.sync(); @@ -112,39 +101,35 @@ script: async function getTableCellAlignment() { // Gets content alignment details about the first cell of the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstCell = firstTable.getCell(0, 0); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + const firstCell: Word.TableCell = firstTableRow.cells.getFirst(); firstCell.load(["horizontalAlignment", "verticalAlignment"]); await context.sync(); - console.log(`Details about the alignment of the first table's first cell:`); - console.log(`- Horizontal alignment of the cell's content: ${firstCell.horizontalAlignment}`); - console.log(`- Vertical alignment of the cell's content: ${firstCell.verticalAlignment}`); + console.log(`Details about the alignment of the first table's first cell:`, `- Horizontal alignment of the cell's content: ${firstCell.horizontalAlignment}`, `- Vertical alignment of the cell's content: ${firstCell.verticalAlignment}`); }); } async function getTableCellBorder() { // Gets border details about the first of the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstCell = firstTable.getCell(0, 0); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstCell: Word.TableCell = firstTable.getCell(0, 0); const borderLocation = "Left"; - const border = firstCell.getBorder(borderLocation); + const border: Word.TableBorder = firstCell.getBorder(borderLocation); border.load(["type", "color", "width"]); await context.sync(); - console.log(`Details about the ${borderLocation} border of the first table's first cell:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + console.log(`Details about the ${borderLocation} border of the first table's first cell:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); } async function getTableCellCellPadding() { // Gets cell padding details about the first cell of the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstCell = firstTable.getCell(0, 0); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstCell: Word.TableCell = firstTable.getCell(0, 0); const cellPaddingLocation = "Left"; const cellPadding = firstCell.getCellPadding(cellPaddingLocation); await context.sync(); @@ -170,7 +155,7 @@ script: }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -182,18 +167,17 @@ script: language: typescript template: content: |- -
+
This sample shows how to get various formatting details about a table, a table row, and a table cell, including borders, alignment, and cell padding.
- -
+

Set up

-
+

Try it out

Table formatting

@@ -248,13 +232,7 @@ style: language: css libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/40-tables/table-cell-access.yaml b/samples/word/40-tables/table-cell-access.yaml index 1f4e33a49..283c41753 100644 --- a/samples/word/40-tables/table-cell-access.yaml +++ b/samples/word/40-tables/table-cell-access.yaml @@ -8,13 +8,13 @@ api_set: WordApi: '1.3' script: content: |- - $("#run").click(() => tryCatch(getTableCell)); - $("#setup").click(() => tryCatch(insertTable)); + document.getElementById("run").addEventListener("click", () => tryCatch(getTableCell)); + document.getElementById("setup").addEventListener("click", () => tryCatch(insertTable)); async function getTableCell() { // Gets the content of the first cell in the first table. await Word.run(async (context) => { - const firstCell = context.document.body.tables.getFirst().getCell(0, 0).body; + const firstCell: Word.Body = context.document.body.tables.getFirst().getCell(0, 0).body; firstCell.load("text"); await context.sync(); @@ -29,7 +29,7 @@ script: ["Tokyo", "Beijing", "Seattle"], ["Apple", "Orange", "Pineapple"] ]; - const table = context.document.body.insertTable(2, 3, "Start", data); + const table: Word.Table = context.document.body.insertTable(2, 3, "Start", data); table.styleBuiltIn = Word.BuiltInStyleName.gridTable5Dark_Accent2; table.styleFirstColumn = false; @@ -37,30 +37,28 @@ script: }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); } catch (error) { - // Note: In a production add-in, you'd want to notify the user through your add-in's UI. - console.error(error); + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); } } language: typescript template: content: |- -

+
This sample demonstrates how to get a cell from a table.
- -
+

Set up

- -
+

Try it out

+ + + + + + + +

Header

+ + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/50-document/compare-documents.yaml b/samples/word/50-document/compare-documents.yaml new file mode 100644 index 000000000..368c7dc05 --- /dev/null +++ b/samples/word/50-document/compare-documents.yaml @@ -0,0 +1,74 @@ +order: 16 +id: word-document-compare-documents +name: Compare documents +description: Compares two documents (the current one and a specified external one). +author: YijunMS +host: WORD +api_set: + WordApiDesktop: '1.1' +script: + content: |- + document.getElementById("run").addEventListener("click", () => tryCatch(run)); + + async function run() { + // Compares the current document with a specified external document. + await Word.run(async (context) => { + // Absolute path of an online or local document. + const filePath = (document.getElementById("filePath") as HTMLInputElement).value; + // Options that configure the compare operation. + const options: Word.DocumentCompareOptions = { + compareTarget: Word.CompareTarget.compareTargetCurrent, + detectFormatChanges: false + // Other options you choose... + }; + context.document.compare(filePath, options); + + await context.sync(); + + console.log("Differences shown in the current document."); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+

This sample shows how to compare two documents: the current one and a specified external one.

+
+
+

Try it out

+ + + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/50-document/get-external-styles.yaml b/samples/word/50-document/get-external-styles.yaml new file mode 100644 index 000000000..86aa2117b --- /dev/null +++ b/samples/word/50-document/get-external-styles.yaml @@ -0,0 +1,85 @@ +order: 13 +id: word-document-get-external-styles +name: Get styles from external document +description: This sample shows how to get styles from an external document. +host: WORD +api_set: + WordApi: '1.5' +script: + content: |- + document.getElementById("file").addEventListener("change", getBase64); + document.getElementById("get-external-styles").addEventListener("click", () => tryCatch(getExternalStyles)); + + let externalDocument; + + async function getExternalStyles() { + // Gets style info from another document passed in as a Base64-encoded string. + await Word.run(async (context) => { + const retrievedStyles = context.application.retrieveStylesFromBase64(externalDocument); + await context.sync(); + + console.log("Styles from the other document:", retrievedStyles.value); + }); + } + + function getBase64() { + // Retrieve the file and set up an HTML FileReader element. + const myFile = document.getElementById("file") as HTMLInputElement; + const reader = new FileReader(); + + reader.onload = (event) => { + // Remove the metadata before the Base64-encoded string. + const startIndex = reader.result.toString().indexOf("base64,"); + externalDocument = reader.result.toString().substr(startIndex + 7); + }; + + // Read the file as a data URL so that we can parse the Base64-encoded string. + reader.readAsDataURL(myFile.files[0]); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+ This sample demonstrates how to get styles from an external document. +
+
+

Try it out

+

Select a Word document to get its style info.

+ + + +
+

Get style info from the selected document.

+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/50-document/insert-external-document.yaml b/samples/word/50-document/insert-external-document.yaml index 04d8ee21f..126961451 100644 --- a/samples/word/50-document/insert-external-document.yaml +++ b/samples/word/50-document/insert-external-document.yaml @@ -1,14 +1,15 @@ -order: 2 +order: 3 id: word-document-insert-external-document name: Insert an external document -description: Inserts the text of an external document into the current document. +description: Inserts the content (with or without settings) of an external document into the current document. Settings include formatting, change-tracking mode, custom properties, and XML parts. host: WORD api_set: - WordApi: '1.3' + WordApi: '1.7' script: - content: | - $("#file").change(getBase64); - $("#insert-document").click(() => tryCatch(insertDocument)); + content: |- + document.getElementById("file").addEventListener("change", getBase64); + document.getElementById("insert-document").addEventListener("click", () => tryCatch(insertDocument)); + document.getElementById("insert-document-with-settings").addEventListener("click", () => tryCatch(insertDocumentWithSettings)); let externalDocument; @@ -16,24 +17,47 @@ script: // Updates the text of the current document with the text from another document passed in as a Base64-encoded string. await Word.run(async (context) => { // Use the Base64-encoded string representation of the selected .docx file. - const externalDoc = context.application.createDocument(externalDocument); + const externalDoc: Word.DocumentCreated = context.application.createDocument(externalDocument); await context.sync(); - const externalDocBody = externalDoc.body; + if (!Office.context.requirements.isSetSupported("WordApiHiddenDocument", "1.3")) { + console.warn("The WordApiHiddenDocument 1.3 requirement set isn't supported on this client so can't proceed. Try this action on a platform that supports this requirement set."); + return; + } + + const externalDocBody: Word.Body = externalDoc.body; externalDocBody.load("text"); await context.sync(); // Insert the external document's text at the beginning of the current document's body. const externalDocBodyText = externalDocBody.text; - const currentDocBody = context.document.body; + const currentDocBody: Word.Body = context.document.body; currentDocBody.insertText(externalDocBodyText, Word.InsertLocation.start); await context.sync(); }); } + async function insertDocumentWithSettings() { + // Inserts content (applying selected settings) from another document passed in as a Base64-encoded string. + await Word.run(async (context) => { + // Use the Base64-encoded string representation of the selected .docx file. + context.document.insertFileFromBase64(externalDocument, "Replace", { + importTheme: true, + importStyles: true, + importParagraphSpacing: true, + importPageColor: true, + importChangeTrackingMode: true, + importCustomProperties: true, + importCustomXmlParts: true, + importDifferentOddEvenPages: true + }); + await context.sync(); + }); + } + function getBase64() { // Retrieve the file and set up an HTML FileReader element. - const myFile = document.getElementById("file"); + const myFile = document.getElementById("file") as HTMLInputElement; const reader = new FileReader(); reader.onload = (event) => { @@ -46,7 +70,7 @@ script: reader.readAsDataURL(myFile.files[0]); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -58,20 +82,24 @@ script: language: typescript template: content: |- -
+

This sample shows how to insert the body text from an external document into the current document.

- -
+

Try it out

-

Select a Word document to copy its body text into the current document.

+

Select a Word document.


Insert the body text from the selected document.

+
+

Insert the body text with settings applied from the selected document.

+
language: html @@ -88,15 +116,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/50-document/insert-section-breaks.yaml b/samples/word/50-document/insert-section-breaks.yaml index 3e9359d19..b870d7865 100644 --- a/samples/word/50-document/insert-section-breaks.yaml +++ b/samples/word/50-document/insert-section-breaks.yaml @@ -1,4 +1,4 @@ -order: 1 +order: 2 id: word-document-insert-section-breaks name: Add a section description: Shows how to insert section breaks in the document. @@ -6,79 +6,79 @@ host: WORD api_set: WordApi: '1.1' script: - content: | - $("#add-sectionNext").click(() => tryCatch(addNext)); - $("#add-sectionEven").click(() => tryCatch(addEven)); - $("#add-sectionOdd").click(() => tryCatch(addOdd)); - $("#add-sectionContinuous").click(() => tryCatch(addContinuous)); - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("add-sectionNext").addEventListener("click", () => tryCatch(addNext)); + document.getElementById("add-sectionEven").addEventListener("click", () => tryCatch(addEven)); + document.getElementById("add-sectionOdd").addEventListener("click", () => tryCatch(addOdd)); + document.getElementById("add-sectionContinuous").addEventListener("click", () => tryCatch(addContinuous)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); async function addNext() { // Inserts a section break on the next page. await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.insertBreak(Word.BreakType.sectionNext, Word.InsertLocation.end); await context.sync(); - console.log("Inserted section break on next page"); + console.log("Inserted section break on next page."); }); } async function addEven() { // Inserts a section break on the next even page. await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.insertBreak(Word.BreakType.sectionEven, Word.InsertLocation.end); await context.sync(); - console.log("Inserted section break on next even page"); + console.log("Inserted section break on next even page."); }); } async function addOdd() { // Inserts a section break on the next odd page. await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.insertBreak(Word.BreakType.sectionOdd, Word.InsertLocation.end); await context.sync(); - console.log("Inserted section break on next odd page"); + console.log("Inserted section break on next odd page."); }); } async function addContinuous() { // Inserts a section without an associated page break. await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.insertBreak(Word.BreakType.sectionContinuous, Word.InsertLocation.end); await context.sync(); - console.log("Inserted section without an associated page break"); + console.log("Inserted section without an associated page break."); }); } async function setup() { await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.clear(); body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", "Start" ); body.paragraphs .getLast() .insertText( - "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching Online cover page, header, and sidebar. Click Insert and then choose the Online elements you want from the different Online galleries.", + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", "Replace" ); }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -90,19 +90,17 @@ script: language: typescript template: content: |- -
+
This sample shows how to insert sections in the document.
- -
+

Set up

You should also show the formatting marks to see the section indicators. To learn more, refer to Show or hide tab marks in Word

- -
+

Try it out

+
+
+

Try it out

+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/50-document/manage-body.yaml b/samples/word/50-document/manage-body.yaml new file mode 100644 index 000000000..c92791dab --- /dev/null +++ b/samples/word/50-document/manage-body.yaml @@ -0,0 +1,415 @@ +order: 1 +id: word-document-manage-body +name: Manage body +description: Shows how to manage the document body. +author: OfficeDev +host: WORD +api_set: + WordApi: '1.2' +script: + content: |- + document.getElementById("get-font-props").addEventListener("click", () => tryCatch(getFontProperties)); + document.getElementById("get-html").addEventListener("click", () => tryCatch(getHTML)); + document.getElementById("get-ooxml").addEventListener("click", () => tryCatch(getOOXML)); + document.getElementById("get-text").addEventListener("click", () => tryCatch(getText)); + document.getElementById("insert-content-control").addEventListener("click", () => tryCatch(insertContentControl)); + document.getElementById("insert-page-break").addEventListener("click", () => tryCatch(insertPageBreak)); + document.getElementById("file").addEventListener("change", getBase64); + document.getElementById("insert-external-body").addEventListener("click", () => tryCatch(insertExternalBody)); + document.getElementById("insert-html").addEventListener("click", () => tryCatch(insertHTML)); + document.getElementById("insert-image-inline").addEventListener("click", () => tryCatch(insertImageInline)); + document.getElementById("insert-ooxml").addEventListener("click", () => tryCatch(insertOOXML)); + document.getElementById("insert-text").addEventListener("click", () => tryCatch(insertText)); + document.getElementById("select").addEventListener("click", () => tryCatch(select)); + document.getElementById("clear").addEventListener("click", () => tryCatch(clear)); + document.getElementById("insert-paragraph").addEventListener("click", () => tryCatch(insertParagraph)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + async function getFontProperties() { + // Gets the style and the font size, font name, and font color properties on the body object. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to load font and style information for the document body. + body.load("font/size, font/name, font/color, style"); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + // Show font-related property values on the body object. + const results = + "Font size: " + + body.font.size + + "; Font name: " + + body.font.name + + "; Font color: " + + body.font.color + + "; Body style: " + + body.style; + + console.log(results); + }); + } + + async function getHTML() { + // Gets the HTML that represents the content of the body. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to get the HTML contents of the body. + const bodyHTML = body.getHtml(); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Body contents (HTML): " + bodyHTML.value); + }); + } + + async function getOOXML() { + // Gets the OOXML that represents the content of the body. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to get the OOXML contents of the body. + const bodyOOXML = body.getOoxml(); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Body contents (OOXML): " + bodyOOXML.value); + }); + } + + async function getText() { + // Gets the text content of the body. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to load the text in document body. + body.load("text"); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Body contents (text): " + body.text); + }); + } + + async function insertContentControl() { + // Creates a content control using the document body. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to wrap the body in a content control. + body.insertContentControl(); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Wrapped the body in a content control."); + }); + } + + async function insertPageBreak() { + // Inserts a page break at the beginning of the document. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to insert a page break at the start of the document body. + body.insertBreak(Word.BreakType.page, Word.InsertLocation.start); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Added a page break at the start of the document body."); + }); + } + + let externalDocument; + + function getBase64() { + // Retrieve the file and set up an HTML FileReader element. + const myFile = document.getElementById("file") as HTMLInputElement; + const reader = new FileReader(); + + reader.onload = (event) => { + // Remove the metadata before the Base64-encoded string. + const startIndex = reader.result.toString().indexOf("base64,"); + externalDocument = reader.result.toString().substr(startIndex + 7); + }; + + // Read the file as a data URL so that we can parse the Base64-encoded string. + reader.readAsDataURL(myFile.files[0]); + } + + async function insertExternalBody() { + // Inserts the body from the external document at the beginning of this document. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to insert the Base64-encoded string representation of the body of the selected .docx file at the beginning of the current document. + body.insertFileFromBase64(externalDocument, Word.InsertLocation.start); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Added Base64-encoded text to the beginning of the document body."); + }); + } + + async function insertHTML() { + // Inserts the HTML at the beginning of this document. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to insert HTML at the beginning of the document. + body.insertHtml("This is text inserted with body.insertHtml()", Word.InsertLocation.start); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("HTML added to the beginning of the document body."); + }); + } + + async function insertImageInline() { + // Inserts an image inline at the beginning of this document. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Base64-encoded image to insert inline. + const base64EncodedImg = + "iVBORw0KGgoAAAANSUhEUgAAAB4AAAANCAIAAAAxEEnAAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACFSURBVDhPtY1BEoQwDMP6/0+XgIMTBAeYoTqso9Rkx1zG+tNj1H94jgGzeNSjteO5vtQQuG2seO0av8LzGbe3anzRoJ4ybm/VeKEerAEbAUpW4aWQCmrGFWykRzGBCnYy2ha3oAIq2MloW9yCCqhgJ6NtcQsqoIKdjLbFLaiACnYyf2fODbrjZcXfr2F4AAAAAElFTkSuQmCC"; + + // Queue a command to insert a Base64-encoded image at the beginning of the current document. + body.insertInlinePictureFromBase64(base64EncodedImg, Word.InsertLocation.start); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Added a Base64-encoded image to the beginning of the document body."); + }); + } + + async function insertOOXML() { + // Inserts OOXML at the beginning of this document. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to insert OOXML at the beginning of the body. + body.insertOoxml( + "This text has formatting directly applied to achieve its font size, color, line spacing, and paragraph spacing.", + Word.InsertLocation.start + ); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Added OOXML to the beginning of the document body."); + }); + + // Read "Understand when and how to use Office Open XML in your Word add-in" for guidance on working with OOXML. + // https://learn.microsoft.com/office/dev/add-ins/word/create-better-add-ins-for-word-with-office-open-xml + + // The Word-Add-in-DocumentAssembly sample shows how you can use this API to assemble a document. + // https://github.com/OfficeDev/Word-Add-in-DocumentAssembly + } + + async function insertText() { + // Inserts text at the beginning of this document. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to insert text at the beginning of the current document. + body.insertText('This is text inserted with body.insertText()', Word.InsertLocation.start); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Text added to the beginning of the document body."); + }); + } + + async function select() { + // Selects the entire body. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to select the document body. + // The Word UI will move to the selected document body. + body.select(); + + console.log("Selected the document body."); + }); + } + + async function clear() { + // Clears out the content from the document body. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to clear the contents of the body. + body.clear(); + + console.log("Cleared the body contents."); + }); + + // The Silly stories add-in sample shows how the clear method can be used to clear the contents of a document. + // https://aka.ms/sillystorywordaddin + } + + async function insertParagraph() { + // Inserts a paragraph at the end of this document. + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to insert a paragraph at the end of the current document. + body.insertParagraph("Content of a new paragraph", Word.InsertLocation.end); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Paragraph added at the end of the document body."); + }); + + // The Word-Add-in-DocumentAssembly sample shows how you can use the insertParagraph method to assemble a document. + // https://github.com/OfficeDev/Word-Add-in-DocumentAssembly + } + + async function setup() { + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph( + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", + "Start" + ); + body.paragraphs + .getLast() + .insertText( + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", + "Replace" + ); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+ This sample shows how to manage the content of the document body. +
+
+

Set up

+ +
+
+

Try it out

+ + + + + + +

Choose a Word document to copy its body into the current document.

+
+ +
+
+ + + + + + + + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/50-document/manage-change-tracking.yaml b/samples/word/50-document/manage-change-tracking.yaml index fea7222e8..fa7f17120 100644 --- a/samples/word/50-document/manage-change-tracking.yaml +++ b/samples/word/50-document/manage-change-tracking.yaml @@ -1,4 +1,4 @@ -order: 3 +order: 4 id: word-document-manage-change-tracking name: Track changes description: This sample shows how to get and set the change tracking mode and get the before and after of reviewed text. @@ -6,16 +6,16 @@ host: WORD api_set: WordApi: '1.4' script: - content: | - $("#get-change-tracking-mode").click(() => tryCatch(getChangeTrackingMode)); - $("#set-change-tracking-mode").click(() => tryCatch(setChangeTrackingMode)); - $("#get-reviewed-text").click(() => tryCatch(getReviewedText)); - $("#setup").click(() => tryCatch(setup)); + content: |- + document.getElementById("get-change-tracking-mode").addEventListener("click", () => tryCatch(getChangeTrackingMode)); + document.getElementById("set-change-tracking-mode").addEventListener("click", () => tryCatch(setChangeTrackingMode)); + document.getElementById("get-reviewed-text").addEventListener("click", () => tryCatch(getReviewedText)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); async function getChangeTrackingMode() { // Gets the current change tracking mode. await Word.run(async (context) => { - const document = context.document; + const document: Word.Document = context.document; document.load("changeTrackingMode"); await context.sync(); @@ -32,7 +32,7 @@ script: async function setChangeTrackingMode() { // Sets the change tracking mode. await Word.run(async (context) => { - const mode = $("input[name='mode']:checked").val(); + const mode = (document.querySelector("input[name='mode']:checked") as HTMLInputElement).value; if (mode === "Track only my changes") { context.document.changeTrackingMode = Word.ChangeTrackingMode.trackMineOnly; } else if (mode === "Track everyone's changes") { @@ -50,35 +50,34 @@ script: async function getReviewedText() { // Gets the reviewed text. await Word.run(async (context) => { - const range = context.document.getSelection(); + const range: Word.Range = context.document.getSelection(); const before = range.getReviewedText(Word.ChangeTrackingVersion.original); const after = range.getReviewedText(Word.ChangeTrackingVersion.current); await context.sync(); - console.log(`Reviewed text (before):\n${before.value}`); - console.log(`Reviewed text (after):\n${after.value}`); + console.log("Reviewed text (before):", before.value, "Reviewed text (after):", after.value); }); } async function setup() { await Word.run(async (context) => { - const body = context.document.body; + const body: Word.Body = context.document.body; body.clear(); body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", "Start" ); body.paragraphs .getLast() .insertText( - "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching Online cover page, header, and sidebar. Click Insert and then choose the Online elements you want from the different Online galleries.", + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", "Replace" ); }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -90,18 +89,16 @@ script: language: typescript template: content: |- -
+

This sample shows basic operations of the Track Changes feature.

- -
+

Set up

- -
+

Try it out

Get current change tracking mode

- -
+

Try it out

-

First, select content in document body.

+

Manage comments in selection

+

Select content in document body before proceeding.

@@ -207,42 +233,43 @@ template:

-

-

-

+

+ +

-

+

Manage comments in document body

- @@ -262,15 +289,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/50-document/manage-custom-xml-part-ns.yaml b/samples/word/50-document/manage-custom-xml-part-ns.yaml index 3a309aaba..4f9b9c5f4 100644 --- a/samples/word/50-document/manage-custom-xml-part-ns.yaml +++ b/samples/word/50-document/manage-custom-xml-part-ns.yaml @@ -1,19 +1,20 @@ -order: 8 +order: 10 id: word-document-manage-custom-xml-part-ns name: Manage a CustomXmlPart with the namespace -description: 'This sample shows how to add, query, replace, edit, and delete a custom XML part in a document.' +description: This sample shows how to add, query, replace, edit, and delete a custom XML part in a document. host: WORD api_set: WordApi: '1.4' script: - content: | - $("#add-custom-xml-part").click(() => tryCatch(addCustomXmlPart)); - $("#query").click(() => tryCatch(query)); - $("#get-namespace").click(() => tryCatch(getNamespace)); - $("#replace-custom-xml-part").click(() => tryCatch(replace)); - $("#insert-attribute").click(() => tryCatch(insertAttribute)); - $("#insert-element").click(() => tryCatch(insertElement)); - $("#delete-custom-xml-part").click(() => tryCatch(deleteCustomXmlPart)); + content: |- + document.getElementById("add-custom-xml-part").addEventListener("click", () => tryCatch(addCustomXmlPart)); + document.getElementById("query").addEventListener("click", () => tryCatch(query)); + document.getElementById("get-namespace").addEventListener("click", () => tryCatch(getNamespace)); + document.getElementById("get-by-namespace").addEventListener("click", () => tryCatch(getByNamespaceUri)); + document.getElementById("replace-custom-xml-part").addEventListener("click", () => tryCatch(replace)); + document.getElementById("insert-attribute").addEventListener("click", () => tryCatch(insertAttribute)); + document.getElementById("insert-element").addEventListener("click", () => tryCatch(insertElement)); + document.getElementById("delete-custom-xml-part").addEventListener("click", () => tryCatch(deleteCustomXmlPart)); async function addCustomXmlPart() { // Adds a custom XML part. @@ -28,11 +29,10 @@ script: await context.sync(); const readableXml = addLineBreaksToXML(xmlBlob.value); - console.log(`Added custom XML part with namespace URI ${customXmlPart.namespaceUri}:`); - console.log(readableXml); + console.log(`Added custom XML part with namespace URI ${customXmlPart.namespaceUri}:`, readableXml); // Store the XML part's ID in a setting so the ID is available to other functions. - const settings = context.document.settings; + const settings: Word.SettingCollection = context.document.settings; settings.add("ContosoReviewXmlPartIdNS", customXmlPart.id); await context.sync(); @@ -40,15 +40,17 @@ script: } async function query() { + // Original XML: JuanHongSally + // Queries a custom XML part for elements matching the search terms. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); await context.sync(); if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); const xpathToQueryFor = "/contoso:Reviewers"; const clientResult = customXmlPart.query(xpathToQueryFor, { contoso: "http://schemas.contoso.com/review/1.0" @@ -61,47 +63,66 @@ script: console.log(clientResult.value[i]); } } else { - console.warn("Didn't find custom XML part to query"); + console.warn("Didn't find custom XML part to query."); } }); } async function getNamespace() { + // Original XML: JuanHongSally + // Gets the namespace URI from a custom XML part. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); await context.sync(); if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); customXmlPart.load("namespaceUri"); await context.sync(); const namespaceUri = customXmlPart.namespaceUri; console.log(`Namespace URI: ${JSON.stringify(namespaceUri)}`); } else { - console.warn("Didn't find custom XML part"); + console.warn("Didn't find custom XML part."); } }); } + async function getByNamespaceUri() { + // Original XML: JuanHongSally + + // Gets the custom XML parts with the specified namespace URI. + await Word.run(async (context) => { + const namespaceUri = "http://schemas.contoso.com/review/1.0"; + console.log(`Specified namespace URI: ${namespaceUri}`); + const scopedCustomXmlParts: Word.CustomXmlPartScopedCollection = + context.document.customXmlParts.getByNamespace(namespaceUri); + scopedCustomXmlParts.load("items"); + await context.sync(); + + console.log(`Number of custom XML parts found with this namespace: ${!scopedCustomXmlParts.items ? 0 : scopedCustomXmlParts.items.length}`); + }); + } + async function replace() { + // Original XML: JuanHongSally + // Replaces a custom XML part. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); await context.sync(); if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); const originalXmlBlob = customXmlPart.getXml(); await context.sync(); let readableXml = addLineBreaksToXML(originalXmlBlob.value); - console.log("Original custom XML part:"); - console.log(readableXml); + console.log("Original custom XML part:", readableXml); // The setXml method replaces the entire XML part. customXmlPart.setXml( @@ -111,23 +132,24 @@ script: await context.sync(); readableXml = addLineBreaksToXML(updatedXmlBlob.value); - console.log("Replaced custom XML part:"); - console.log(readableXml); + console.log("Replaced custom XML part:", readableXml); } else { - console.warn("Didn't find custom XML part to replace"); + console.warn("Didn't find custom XML part to replace."); } }); } async function insertAttribute() { + // Original XML: JuanHongSally + // Inserts an attribute into a custom XML part. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); await context.sync(); if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); // The insertAttribute method inserts an attribute with the given name and value into the element identified by the xpath parameter. customXmlPart.insertAttribute( @@ -140,23 +162,24 @@ script: await context.sync(); const readableXml = addLineBreaksToXML(xmlBlob.value); - console.log("Successfully inserted attribute:"); - console.log(readableXml); + console.log("Successfully inserted attribute:", readableXml); } else { - console.warn("Didn't find custom XML part to insert attribute into"); + console.warn("Didn't find custom XML part to insert attribute into."); } }); } async function insertElement() { + // Original XML: JuanHongSally + // Inserts an element into a custom XML part. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); await context.sync(); if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); // The insertElement method inserts the given XML under the parent element identified by the xpath parameter at the provided child position index. customXmlPart.insertElement( @@ -169,23 +192,24 @@ script: await context.sync(); const readableXml = addLineBreaksToXML(xmlBlob.value); - console.log("Successfully inserted element:"); - console.log(readableXml); + console.log("Successfully inserted element:", readableXml); } else { - console.warn("Didn't find custom XML part to insert element into"); + console.warn("Didn't find custom XML part to insert element into."); } }); } async function deleteCustomXmlPart() { + // Original XML: JuanHongSally + // Deletes a custom XML part. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); await context.sync(); if (xmlPartIDSetting.value) { - let customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + let customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); const xmlBlob = customXmlPart.getXml(); customXmlPart.delete(); customXmlPart = context.document.customXmlParts.getItemOrNullObject(xmlPartIDSetting.value); @@ -193,7 +217,7 @@ script: await context.sync(); if (customXmlPart.isNullObject) { - console.log(`The XML part with the ID ${xmlPartIDSetting.value} has been deleted`); + console.log(`The XML part with the ID ${xmlPartIDSetting.value} has been deleted.`); // Delete the associated setting too. xmlPartIDSetting.delete(); @@ -201,11 +225,13 @@ script: await context.sync(); } else { const readableXml = addLineBreaksToXML(xmlBlob.value); - const strangeMessage = `This is strange. The XML part with the id ${xmlPartIDSetting.value} wasn't deleted:\n${readableXml}`; - console.error(strangeMessage); + console.error( + `This is strange. The XML part with the id ${xmlPartIDSetting.value} wasn't deleted:`, + readableXml + ); } } else { - console.warn("Didn't find custom XML part to delete"); + console.warn("Didn't find custom XML part to delete."); } }); } @@ -215,7 +241,7 @@ script: return xmlBlob.replace(/> <"); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -227,28 +253,30 @@ script: language: typescript template: content: |- -

+

This sample shows how to add, query, replace, edit, and delete a custom XML part in a document.

Note: For your production add-in, make sure to create and host your own XML schema.

- -
+

Try it out

+ + + + Insert attribute + @@ -270,15 +298,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/50-document/manage-custom-xml-part.yaml b/samples/word/50-document/manage-custom-xml-part.yaml index 602513686..12f1de659 100644 --- a/samples/word/50-document/manage-custom-xml-part.yaml +++ b/samples/word/50-document/manage-custom-xml-part.yaml @@ -1,35 +1,34 @@ -order: 9 +order: 11 id: word-document-manage-custom-xml-part name: Manage a CustomXmlPart without the namespace -description: 'This sample shows how to add, query, edit, and delete a custom XML part in a document.' +description: This sample shows how to add, query, edit, and delete a custom XML part in a document. host: WORD api_set: WordApi: '1.4' script: - content: | - $("#add-custom-xml-part").click(() => tryCatch(addCustomXmlPart)); - $("#query").click(() => tryCatch(query)); - $("#insert-attribute").click(() => tryCatch(insertAttribute)); - $("#insert-element").click(() => tryCatch(insertElement)); - $("#delete-custom-xml-part").click(() => tryCatch(deleteCustomXmlPart)); + content: |- + document.getElementById("add-custom-xml-part").addEventListener("click", () => tryCatch(addCustomXmlPart)); + document.getElementById("query").addEventListener("click", () => tryCatch(query)); + document.getElementById("insert-attribute").addEventListener("click", () => tryCatch(insertAttribute)); + document.getElementById("insert-element").addEventListener("click", () => tryCatch(insertElement)); + document.getElementById("delete-custom-xml-part").addEventListener("click", () => tryCatch(deleteCustomXmlPart)); async function addCustomXmlPart() { // Adds a custom XML part. await Word.run(async (context) => { const originalXml = "JuanHongSally"; - const customXmlPart = context.document.customXmlParts.add(originalXml); + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.add(originalXml); customXmlPart.load("id"); const xmlBlob = customXmlPart.getXml(); await context.sync(); const readableXml = addLineBreaksToXML(xmlBlob.value); - console.log("Added custom XML part:"); - console.log(readableXml); + console.log("Added custom XML part:", readableXml); // Store the XML part's ID in a setting so the ID is available to other functions. - const settings = context.document.settings; + const settings: Word.SettingCollection = context.document.settings; settings.add("ContosoReviewXmlPartId", customXmlPart.id); await context.sync(); @@ -37,15 +36,17 @@ script: } async function query() { + // Original XML: JuanHongSally + // Queries a custom XML part for elements matching the search terms. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); await context.sync(); if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); const xpathToQueryFor = "/Reviewers/Reviewer"; const clientResult = customXmlPart.query(xpathToQueryFor, { contoso: "http://schemas.contoso.com/review/1.0" @@ -58,20 +59,22 @@ script: console.log(clientResult.value[i]); } } else { - console.warn("Didn't find custom XML part to query"); + console.warn("Didn't find custom XML part to query."); } }); } async function insertAttribute() { + // Original XML: JuanHongSally + // Inserts an attribute into a custom XML part. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); await context.sync(); if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); // The insertAttribute method inserts an attribute with the given name and value into the element identified by the xpath parameter. customXmlPart.insertAttribute("/Reviewers", { contoso: "http://schemas.contoso.com/review/1.0" }, "Nation", "US"); @@ -79,23 +82,24 @@ script: await context.sync(); const readableXml = addLineBreaksToXML(xmlBlob.value); - console.log("Successfully inserted attribute:"); - console.log(readableXml); + console.log("Successfully inserted attribute:", readableXml); } else { - console.warn("Didn't find custom XML part to insert attribute into"); + console.warn("Didn't find custom XML part to insert attribute into."); } }); } async function insertElement() { + // Original XML: JuanHongSally + // Inserts an element into a custom XML part. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); await context.sync(); if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); // The insertElement method inserts the given XML under the parent element identified by the xpath parameter at the provided child position index. customXmlPart.insertElement( @@ -108,23 +112,24 @@ script: await context.sync(); const readableXml = addLineBreaksToXML(xmlBlob.value); - console.log("Successfully inserted element:"); - console.log(readableXml); + console.log("Successfully inserted element:", readableXml); } else { - console.warn("Didn't find custom XML part to insert element into"); + console.warn("Didn't find custom XML part to insert element into."); } }); } async function deleteCustomXmlPart() { + // Original XML: JuanHongSally + // Deletes a custom XML part. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); await context.sync(); if (xmlPartIDSetting.value) { - let customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + let customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); const xmlBlob = customXmlPart.getXml(); customXmlPart.delete(); customXmlPart = context.document.customXmlParts.getItemOrNullObject(xmlPartIDSetting.value); @@ -132,7 +137,7 @@ script: await context.sync(); if (customXmlPart.isNullObject) { - console.log(`The XML part with the ID ${xmlPartIDSetting.value} has been deleted`); + console.log(`The XML part with the ID ${xmlPartIDSetting.value} has been deleted.`); // Delete the associated setting too. xmlPartIDSetting.delete(); @@ -140,11 +145,10 @@ script: await context.sync(); } else { const readableXml = addLineBreaksToXML(xmlBlob.value); - const strangeMessage = `This is strange. The XML part with the id ${xmlPartIDSetting.value} wasn't deleted:\n${readableXml}`; - console.error(strangeMessage); + console.error(`This is strange. The XML part with the id ${xmlPartIDSetting.value} wasn't deleted:`, readableXml); } } else { - console.warn("Didn't find custom XML part to delete"); + console.warn("Didn't find custom XML part to delete."); } }); } @@ -154,7 +158,7 @@ script: return xmlBlob.replace(/> <"); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -166,12 +170,11 @@ script: language: typescript template: content: |- -
+

This sample shows how to add, query, edit, and delete a custom XML part in a document.

Note: For your production add-in, make sure to create and host your own XML schema.

- -
+

Try it out

- -
+

Try it out

Insert fields

First, select some text.

@@ -207,7 +195,6 @@ template: Insert Date field

-

Get and update fields

-

Delete fields

- -
+

Try it out

Insert footnote

1. Select text in the document.

@@ -247,15 +234,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/50-document/manage-settings.yaml b/samples/word/50-document/manage-settings.yaml index 33c496f41..5c5b6a95d 100644 --- a/samples/word/50-document/manage-settings.yaml +++ b/samples/word/50-document/manage-settings.yaml @@ -1,52 +1,45 @@ -order: 7 +order: 9 id: word-document-manage-settings name: Manage settings -description: 'This sample shows how to add, edit, get, and delete custom settings on a document.' +description: This sample shows how to add, edit, get, and delete custom settings on a document. host: WORD api_set: WordApi: '1.4' script: - content: | - $("#add-edit-setting").click(() => tryCatch(addEditSetting)); - $("#get-all-settings").click(() => tryCatch(getAllSettings)); - $("#delete-all-settings").click(() => tryCatch(deleteAllSettings)); + content: |- + document.getElementById("add-edit-setting").addEventListener("click", () => tryCatch(addEditSetting)); + document.getElementById("get-all-settings").addEventListener("click", () => tryCatch(getAllSettings)); + document.getElementById("delete-all-settings").addEventListener("click", () => tryCatch(deleteAllSettings)); async function addEditSetting() { // Adds a new custom setting or // edits the value of an existing one. await Word.run(async (context) => { - const key = $("#key") - .val() - .toString(); - + const key = (document.getElementById("key") as HTMLInputElement).value; if (key == "") { - console.error("Key shouldn't be empty"); + console.error("Key shouldn't be empty."); return; } - const value = $("#value") - .val() - .toString(); - - const settings = context.document.settings; - const setting = settings.add(key, value); + const value = (document.getElementById("value") as HTMLInputElement).value; + const settings: Word.SettingCollection = context.document.settings; + const setting: Word.Setting = settings.add(key, value); setting.load(); await context.sync(); - console.log("Setting added or edited:"); - console.log(setting); + console.log("Setting added or edited:", setting); }); } async function getAllSettings() { // Gets all custom settings this add-in set on this document. await Word.run(async (context) => { - const settings = context.document.settings; + const settings: Word.SettingCollection = context.document.settings; settings.load("items"); await context.sync(); if (settings.items.length == 0) { - console.log("There are no settings"); + console.log("There are no settings."); } else { console.log("All settings:"); for (let i = 0; i < settings.items.length; i++) { @@ -59,14 +52,14 @@ script: async function deleteAllSettings() { // Deletes all custom settings this add-in had set on this document. await Word.run(async (context) => { - const settings = context.document.settings; + const settings: Word.SettingCollection = context.document.settings; settings.deleteAll(); await context.sync(); - console.log("All settings deleted"); + console.log("All settings deleted."); }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -78,13 +71,12 @@ script: language: typescript template: content: |- -
+

This sample shows how to add, edit, get, and delete custom settings on a document. Settings created by an add-in can only be managed by that add-in.

- -
+

Try it out

Add a new setting, or edit an existing one

@@ -121,15 +113,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/50-document/manage-styles.yaml b/samples/word/50-document/manage-styles.yaml index 64294c4ee..4c0347195 100644 --- a/samples/word/50-document/manage-styles.yaml +++ b/samples/word/50-document/manage-styles.yaml @@ -1,26 +1,26 @@ -order: 10 +order: 12 id: word-document-manage-styles name: Manage styles description: This sample shows how to perform operations on the styles in the current document and how to add and delete custom styles. host: WORD api_set: - WordApi: '1.5' + WordApiDesktop: '1.1' script: - content: | - $("#count").click(() => tryCatch(getCount)); - $("#add-style").click(() => tryCatch(addStyle)); - $("#properties").click(() => tryCatch(getProperties)); - $("#apply-style").click(() => tryCatch(applyStyle)); - $("#font-properties").click(() => tryCatch(setFontProperties)); - $("#paragraph-format").click(() => tryCatch(setParagraphFormat)); - $("#delete-style").click(() => tryCatch(deleteStyle)); - $("#file").change(getBase64); - $("#get-external-styles").click(() => tryCatch(getExternalStyles)); + content: |- + document.getElementById("count").addEventListener("click", () => tryCatch(getCount)); + document.getElementById("add-style").addEventListener("click", () => tryCatch(addStyle)); + document.getElementById("properties").addEventListener("click", () => tryCatch(getProperties)); + document.getElementById("apply-style").addEventListener("click", () => tryCatch(applyStyle)); + document.getElementById("font-properties").addEventListener("click", () => tryCatch(setFontProperties)); + document.getElementById("paragraph-format").addEventListener("click", () => tryCatch(setParagraphFormat)); + document.getElementById("border-properties").addEventListener("click", () => tryCatch(setBorderProperties)); + document.getElementById("shading-properties").addEventListener("click", () => tryCatch(setShadingProperties)); + document.getElementById("delete-style").addEventListener("click", () => tryCatch(deleteStyle)); async function getCount() { - // Gets the number of styles. + // Gets the number of available styles stored with the document. await Word.run(async (context) => { - const styles = context.document.getStyles(); + const styles: Word.StyleCollection = context.document.getStyles(); const count = styles.getCount(); await context.sync(); @@ -31,13 +31,13 @@ script: async function addStyle() { // Adds a new style. await Word.run(async (context) => { - const newStyleName = $("#new-style-name").val() as string; + const newStyleName = (document.getElementById("new-style-name") as HTMLInputElement).value; if (newStyleName == "") { console.warn("Enter a style name to add."); return; } - const style = context.document.getStyles().getByNameOrNullObject(newStyleName); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(newStyleName); style.load(); await context.sync(); @@ -48,10 +48,10 @@ script: return; } - const newStyleType = ($("#new-style-type").val() as unknown) as Word.StyleType; + const newStyleType = ((document.getElementById("new-style-type") as HTMLSelectElement).value as unknown) as Word.StyleType; context.document.addStyle(newStyleName, newStyleType); await context.sync(); - + console.log(newStyleName + " has been added to the style list."); }); } @@ -59,13 +59,13 @@ script: async function getProperties() { // Gets the properties of the specified style. await Word.run(async (context) => { - const styleName = $("#style-name-to-use").val() as string; + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; if (styleName == "") { console.warn("Enter a style name to get properties."); return; } - const style = context.document.getStyles().getByNameOrNullObject(styleName); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); style.load(); await context.sync(); @@ -76,8 +76,7 @@ script: style.paragraphFormat.load(); await context.sync(); - console.log(`Properties of the '${styleName}' style:`); - console.log(style); + console.log(`Properties of the '${styleName}' style:`, style); } }); } @@ -85,13 +84,13 @@ script: async function applyStyle() { // Applies the specified style to a paragraph. await Word.run(async (context) => { - const styleName = $("#style-name-to-use").val() as string; + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; if (styleName == "") { console.warn("Enter a style name to apply."); return; } - const style = context.document.getStyles().getByNameOrNullObject(styleName); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); style.load(); await context.sync(); @@ -100,13 +99,13 @@ script: } else if (style.type != Word.StyleType.paragraph) { console.log(`The '${styleName}' style isn't a paragraph style.`); } else { - const body = context.document.body; + const body: Word.Body = context.document.body; body.clear(); body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", "Start" ); - const paragraph = body.paragraphs.getFirst(); + const paragraph: Word.Paragraph = body.paragraphs.getFirst(); paragraph.style = style.nameLocal; console.log(`'${styleName}' style applied to first paragraph.`); } @@ -116,20 +115,20 @@ script: async function setFontProperties() { // Updates font properties (e.g., color, size) of the specified style. await Word.run(async (context) => { - const styleName = $("#style-name").val() as string; + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; if (styleName == "") { console.warn("Enter a style name to update font properties."); return; } - const style = context.document.getStyles().getByNameOrNullObject(styleName); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); style.load(); await context.sync(); if (style.isNullObject) { console.warn(`There's no existing style with the name '${styleName}'.`); } else { - const font = style.font; + const font: Word.Font = style.font; font.color = "#FF0000"; font.size = 20; console.log(`Successfully updated font properties of the '${styleName}' style.`); @@ -140,13 +139,13 @@ script: async function setParagraphFormat() { // Sets certain aspects of the specified style's paragraph format e.g., the left indent size and the alignment. await Word.run(async (context) => { - const styleName = $("#style-name").val() as string; + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; if (styleName == "") { console.warn("Enter a style name to update its paragraph format."); return; } - const style = context.document.getStyles().getByNameOrNullObject(styleName); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); style.load(); await context.sync(); @@ -160,57 +159,86 @@ script: }); } - async function deleteStyle() { - // Deletes the custom style. + async function setBorderProperties() { + // Updates border properties (e.g., type, width, color) of the specified style. await Word.run(async (context) => { - const styleName = $("#style-name-to-delete").val() as string; + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; if (styleName == "") { - console.warn("Enter a style name to delete."); + console.warn("Enter a style name to update border properties."); return; } - const style = context.document.getStyles().getByNameOrNullObject(styleName); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); style.load(); await context.sync(); if (style.isNullObject) { console.warn(`There's no existing style with the name '${styleName}'.`); } else { - style.delete(); - console.log(`Successfully deleted custom style '${styleName}'.`); + const borders: Word.BorderCollection = style.borders; + borders.load("items"); + await context.sync(); + + borders.outsideBorderType = Word.BorderType.dashed; + borders.outsideBorderWidth = Word.BorderWidth.pt025; + borders.outsideBorderColor = "green"; + console.log("Updated outside borders."); } }); } - let externalDocument; - - async function getExternalStyles() { - // Gets style info from another document passed in as a Base64-encoded string. + async function setShadingProperties() { + // Updates shading properties (e.g., texture, pattern colors) of the specified style. await Word.run(async (context) => { - const retrievedStyles = context.application.retrieveStylesFromBase64(externalDocument); + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update shading properties."); + return; + } + + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); await context.sync(); - console.log("Styles from the other document:"); - console.log(retrievedStyles.value); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + const shading: Word.Shading = style.shading; + shading.load(); + await context.sync(); + + shading.backgroundPatternColor = "blue"; + shading.foregroundPatternColor = "yellow"; + shading.texture = Word.ShadingTextureType.darkTrellis; + + console.log("Updated shading."); + } }); } - function getBase64() { - // Retrieve the file and set up an HTML FileReader element. - const myFile = document.getElementById("file"); - const reader = new FileReader(); + async function deleteStyle() { + // Deletes the custom style. + await Word.run(async (context) => { + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to delete."); + return; + } - reader.onload = (event) => { - // Remove the metadata before the Base64-encoded string. - const startIndex = reader.result.toString().indexOf("base64,"); - externalDocument = reader.result.toString().substr(startIndex + 7); - }; + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); + await context.sync(); - // Read the file as a data URL so that we can parse the Base64-encoded string. - reader.readAsDataURL(myFile.files[0]); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + style.delete(); + console.log(`Successfully deleted custom style '${styleName}'.`); + } + }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -222,21 +250,19 @@ script: language: typescript template: content: |- -
+
This sample demonstrates how to manage styles.
- -
+

Try it out

Get current number of styles

+ Get count +

- -

Add a new style

-
Name the style using letters. Can include digits. Examples: NewName, newname1
+

Add a custom style

+
Give the style an alphanumeric name. Must start with a letter. Examples: NewName, newname1

@@ -253,7 +279,6 @@ template: -

Use custom style

@@ -265,7 +290,6 @@ template: -

Update custom style

@@ -279,7 +303,16 @@ template: - +

+

Set outside border type to dashed, width to pt. 0.25, and color to green.
+ +

+

Set texture to DarkTrellis, foreground pattern color to yellow, and background pattern color to blue.
+

Delete custom style

@@ -287,17 +320,6 @@ template: -

-

Get style info from external document

-

Select a Word document to get its style info.

-
- -
-
-

Get style info from the selected document.

-
language: html style: @@ -315,10 +337,6 @@ style: language: css libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - core-js@2.4.1/client/core.min.js - @types/core-js - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/50-document/manage-tracked-changes.yaml b/samples/word/50-document/manage-tracked-changes.yaml new file mode 100644 index 000000000..3099bf706 --- /dev/null +++ b/samples/word/50-document/manage-tracked-changes.yaml @@ -0,0 +1,210 @@ +order: 5 +id: word-document-manage-tracked-changes +name: Manage tracked changes +description: This samples shows how to manage tracked changes, including accepting and rejecting changes. +host: WORD +api_set: + WordApi: '1.6' +script: + content: |- + document.getElementById("get-all-tracked-changes").addEventListener("click", () => tryCatch(getAllTrackedChanges)); + document.getElementById("get-first-tracked-change-range").addEventListener("click", () => tryCatch(getFirstTrackedChangeRange)); + document.getElementById("get-next-tracked-change").addEventListener("click", () => tryCatch(getNextTrackedChange)); + document.getElementById("accept-first-tracked-change").addEventListener("click", () => tryCatch(acceptFirstTrackedChange)); + document.getElementById("reject-first-tracked-change").addEventListener("click", () => tryCatch(rejectFirstTrackedChange)); + document.getElementById("accept-all-tracked-changes").addEventListener("click", () => tryCatch(acceptAllTrackedChanges)); + document.getElementById("reject-all-tracked-changes").addEventListener("click", () => tryCatch(rejectAllTrackedChanges)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + async function getAllTrackedChanges() { + // Gets all tracked changes. + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + trackedChanges.load(); + await context.sync(); + + console.log(trackedChanges); + }); + } + + async function getFirstTrackedChangeRange() { + // Gets the range of the first tracked change. + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); + await context.sync(); + + const range: Word.Range = trackedChange.getRange(); + range.load(); + await context.sync(); + + console.log("range.text: " + range.text); + }); + } + + async function getNextTrackedChange() { + // Gets the next (second) tracked change. + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + await context.sync(); + + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); + await context.sync(); + + const nextTrackedChange: Word.TrackedChange = trackedChange.getNext(); + await context.sync(); + + nextTrackedChange.load(["author", "date", "text", "type"]); + await context.sync(); + + console.log(nextTrackedChange); + }); + } + + async function acceptFirstTrackedChange() { + // Accepts the first tracked change. + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); + trackedChange.load(); + await context.sync(); + + console.log("First tracked change:", trackedChange); + trackedChange.accept(); + console.log("Accepted the first tracked change."); + }); + } + + async function rejectFirstTrackedChange() { + // Rejects the first tracked change. + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); + trackedChange.load(); + await context.sync(); + + console.log("First tracked change:", trackedChange); + trackedChange.reject(); + console.log("Rejected the first tracked change."); + }); + } + + async function acceptAllTrackedChanges() { + // Accepts all tracked changes. + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + trackedChanges.acceptAll(); + console.log("Accepted all tracked changes."); + }); + } + + async function rejectAllTrackedChanges() { + // Rejects all tracked changes. + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + trackedChanges.rejectAll(); + console.log("Rejected all tracked changes."); + }); + } + + async function setup() { + // Updates the text and sets the font color to red. + await Word.run(async (context) => { + context.document.changeTrackingMode = Word.ChangeTrackingMode.off; + + context.document.body.insertText("AAA BBB CCC DDD EEE FFF", "Replace"); + + context.document.changeTrackingMode = Word.ChangeTrackingMode.trackAll; + context.document.body + .search("BBB") + .getFirst() + .insertText("WWW", "Replace"); + context.document.body + .search("DDD ") + .getFirst() + .delete(); + context.document.body + .search("FFF") + .getFirst() + .insertText("XXX ", "Start"); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+ This sample shows how to manage tracked changes. +
+
+

Set up

+ +
+
+

Try it out

+ + + + + +
+
+

First, choose the Add sample text button. + +

+

First, choose the Add sample text button. + +

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/50-document/save-close.yaml b/samples/word/50-document/save-close.yaml index 4a4672679..67ec5b4c8 100644 --- a/samples/word/50-document/save-close.yaml +++ b/samples/word/50-document/save-close.yaml @@ -1,4 +1,4 @@ -order: 11 +order: 14 id: word-document-save-close name: Manage document save and close description: Shows how to manage saving and closing document. @@ -6,22 +6,20 @@ host: WORD api_set: WordApi: '1.5' script: - content: | - $("#save-no-prompt").click(() => tryCatch(saveNoPrompt)); - $("#save-after-prompt").click(() => tryCatch(saveAfterPrompt)); - $("#close-after-save").click(() => tryCatch(closeAfterSave)); - $("#close-no-save").click(() => tryCatch(closeWithoutSave)); - $("#save").click(() => tryCatch(save)); - $("#close").click(() => tryCatch(close)); + content: |- + document.getElementById("save-no-prompt").addEventListener("click", () => tryCatch(saveNoPrompt)); + document.getElementById("save-after-prompt").addEventListener("click", () => tryCatch(saveAfterPrompt)); + document.getElementById("close-after-save").addEventListener("click", () => tryCatch(closeAfterSave)); + document.getElementById("close-no-save").addEventListener("click", () => tryCatch(closeWithoutSave)); + document.getElementById("save").addEventListener("click", () => tryCatch(save)); + document.getElementById("close").addEventListener("click", () => tryCatch(close)); async function saveNoPrompt() { // Saves the document with the provided file name // if it hasn't been saved before. await Word.run(async (context) => { - const text = $("#fileName-text") - .val() - .toString(); - context.document.save("Save", text); + const text = (document.getElementById("fileName-text") as HTMLInputElement).value; + context.document.save(Word.SaveBehavior.save, text); await context.sync(); }); } @@ -30,7 +28,7 @@ script: // If the document hasn't been saved before, prompts // user with options for if or how they want to save. await Word.run(async (context) => { - context.document.save("Prompt"); + context.document.save(Word.SaveBehavior.prompt); await context.sync(); }); } @@ -38,14 +36,14 @@ script: async function closeAfterSave() { // Closes the document after saving. await Word.run(async (context) => { - context.document.close("Save"); + context.document.close(Word.CloseBehavior.save); }); } async function closeWithoutSave() { // Closes the document without saving any changes. await Word.run(async (context) => { - context.document.close("SkipSave"); + context.document.close(Word.CloseBehavior.skipSave); await context.sync(); }); } @@ -67,7 +65,7 @@ script: }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -79,11 +77,10 @@ script: language: typescript template: content: |- -
-

This sample shows how use the options for saving and closing the current document.

+
+

This sample shows how to use the options for saving and closing the current document.

- -
+

Try it out

@@ -132,15 +129,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/90-scenarios/correlated-objects-pattern.yaml b/samples/word/90-scenarios/correlated-objects-pattern.yaml new file mode 100644 index 000000000..7f2817061 --- /dev/null +++ b/samples/word/90-scenarios/correlated-objects-pattern.yaml @@ -0,0 +1,166 @@ +order: 3 +id: word-scenarios-correlated-objects-pattern +name: Correlated objects pattern +description: Shows the performance benefits of avoiding `context.sync` calls in a loop. +author: OfficeDev +host: WORD +api_set: + WordApi: '1.4' +script: + content: |- + document.getElementById("replace-placeholders").addEventListener("click", () => tryCatch(replacePlaceholders)); + document.getElementById("replace-placeholders-slow").addEventListener("click", () => tryCatch(replacePlaceholdersSlow)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + document.getElementById("add-lots-of-text").addEventListener("click", () => tryCatch(addLotsOfText)); + const jobMapping = [ + { job: "{Coordinator}", person: "Sally" }, + { job: "{Deputy}", person: "Bob" }, + { job: "{Manager}", person: "Kim" } + ]; + async function replacePlaceholders() { + Word.run(async (context) => { + const startTime = Date.now(); + let count = 0; + + // Find the locations of all the placeholder strings. + const allSearchResults = []; + for (let i = 0; i < jobMapping.length; i++) { + let options = Word.SearchOptions.newObject(context); + options.matchWildcards = false; + let searchResults = context.document.body.search(jobMapping[i].job, options); + searchResults.load('items'); + let correlatedSearchResult = { + rangesMatchingJob: searchResults, + personAssignedToJob: jobMapping[i].person + } + allSearchResults.push(correlatedSearchResult); + } + + // Sync to load those locations in the add-in. + await context.sync() + + // Replace the placeholder text at the known locations. + for (let i = 0; i < allSearchResults.length; i++) { + let correlatedObject = allSearchResults[i]; + + for (let j = 0; j < correlatedObject.rangesMatchingJob.items.length; j++) { + let targetRange = correlatedObject.rangesMatchingJob.items[j]; + let name = correlatedObject.personAssignedToJob; + targetRange.insertText(name, Word.InsertLocation.replace); + count++; + } + } + + await context.sync(); + console.log(`Replacing ${count} placeholders with the correlated objects pattern took ${Date.now() - startTime} milliseconds.`); + console.log() + }); + } + async function replacePlaceholdersSlow() { + Word.run(async (context) => { + const startTime = Date.now(); + let count = 0; + + // 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; + let searchResults = context.document.body.search(jobMapping[i].job, options); + searchResults.load('items'); + + await context.sync(); + + for (let j = 0; j < searchResults.items.length; j++) { + searchResults.items[j].insertText(jobMapping[i].person, Word.InsertLocation.replace); + count++; + await context.sync(); + } + } + console.log(`Replacing ${count} placeholders with in-loop sync statements took ${Date.now() - startTime} milliseconds.`); + }); + } + async function setup(timesToAddText: number = 1) { + await Word.run(async (context) => { + console.log("Setup beginning..."); + const body: Word.Body = context.document.body; + body.clear(); + while (timesToAddText > 0) { + body.insertParagraph( + "This defines the roles of {Coordinator}, {Deputy}, {Manager}.", + Word.InsertLocation.end + ); + body.insertParagraph( + "{Coordinator}: Oversees daily operations and ensures projects run smoothly by coordinating between different teams and resources.", + Word.InsertLocation.end + ); + body.insertParagraph( + "{Deputy}: Assists and supports senior management, often stepping in to make decisions or manage tasks in {Manager}'s absence.", + Word.InsertLocation.end + ); + body.insertParagraph( + "{Manager}: Leads the team, setting goals, planning strategies, and making decisions to achieve organizational objectives.", + Word.InsertLocation.end + ); + timesToAddText--; + } + await context.sync(); + console.log("Setup complete."); + }); + } + async function addLotsOfText() { + // Add the setup text 100 times. + setup(100); + } + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +

+

This sample demonstrates the performance optimization gained from the correlated objects pattern. For more information, see Avoid using the context.sync method in loops.

+
+
+

Setup

+

Use Setup to create a basic text block with some placeholders. Use More text to create a longer text block to better see performance distinctions.

+ +
+
+

Replace placeholder text

+ + +
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/1/hosted/office.js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/samples/word/90-scenarios/doc-assembly.yaml b/samples/word/90-scenarios/doc-assembly.yaml index bf3bc9926..302701358 100644 --- a/samples/word/90-scenarios/doc-assembly.yaml +++ b/samples/word/90-scenarios/doc-assembly.yaml @@ -8,15 +8,15 @@ api_set: WordApi: '1.1' script: content: |- - $("#insert-header").click(() => tryCatch(insertHeader)); - $("#add-paragraphs").click(() => tryCatch(addParagraphs)); - $("#add-content-controls").click(() => tryCatch(addContentControls)); - $("#change-customer").click(() => tryCatch(changeCustomer)); - $("#add-footer").click(() => tryCatch(addFooter)); + document.getElementById("insert-header").addEventListener("click", () => tryCatch(insertHeader)); + document.getElementById("add-paragraphs").addEventListener("click", () => tryCatch(addParagraphs)); + document.getElementById("add-content-controls").addEventListener("click", () => tryCatch(addContentControls)); + document.getElementById("change-customer").addEventListener("click", () => tryCatch(changeCustomer)); + document.getElementById("add-footer").addEventListener("click", () => tryCatch(addFooter)); async function insertHeader() { await Word.run(async (context) => { - const header = context.document.body.insertText("This is a sample Heading 1 Title!!\n", + const header: Word.Range = context.document.body.insertText("This is a sample Heading 1 Title!!\n", "Start" /*this means at the beginning of the body */); header.styleBuiltIn = Word.BuiltInStyleName.heading1; @@ -26,28 +26,28 @@ script: async function addParagraphs() { await Word.run(async (context) => { - const paragraph = context.document.body.insertParagraph("Timeline", "End"); + const paragraph: Word.Paragraph = context.document.body.insertParagraph("Timeline", "End"); paragraph.styleBuiltIn = "Heading2"; - const paragraph2 = context.document.body.insertParagraph("The Services shall commence on July 31, 2015, and shall continue through July 29, 2015.", "End"); + const paragraph2: Word.Paragraph = context.document.body.insertParagraph("The Services shall commence on July 31, 2015, and shall continue through July 29, 2015.", "End"); paragraph2.styleBuiltIn = "Normal"; - const paragraph3 = context.document.body.insertParagraph("Project Costs by Phase", "End"); + const paragraph3: Word.Paragraph = context.document.body.insertParagraph("Project Costs by Phase", "End"); paragraph3.styleBuiltIn = "Heading2"; // Note a content control with the title of "ProjectCosts" is added. Content will be replaced later. - const paragraph4 = context.document.body.insertParagraph("", "End"); + const paragraph4: Word.Paragraph = context.document.body.insertParagraph("", "End"); paragraph4.styleBuiltIn = "Normal"; paragraph4.font.highlightColor = "#FFFF00"; - const contentControl = paragraph4.insertContentControl(); + const contentControl: Word.ContentControl = paragraph4.insertContentControl(); contentControl.title = "ProjectCosts"; - const paragraph5 = context.document.body.insertParagraph("Project Team", "End"); + const paragraph5: Word.Paragraph = context.document.body.insertParagraph("Project Team", "End"); paragraph5.styleBuiltIn = "Heading2"; paragraph5.font.highlightColor = "#FFFFFF"; - const paragraph6 = context.document.body.insertParagraph("Terms of Work", "End"); + const paragraph6: Word.Paragraph = context.document.body.insertParagraph("Terms of Work", "End"); paragraph6.styleBuiltIn = "Heading1"; - const paragraph7 = context.document.body.insertParagraph("Contractor shall provide the Services and Deliverable(s) as follows:", "End"); + const paragraph7: Word.Paragraph = context.document.body.insertParagraph("Contractor shall provide the Services and Deliverable(s) as follows:", "End"); paragraph7.styleBuiltIn = "Normal"; - const paragraph8 = context.document.body.insertParagraph("Out-of-Pocket Expenses / Invoice Procedures", "End"); + const paragraph8: Word.Paragraph = context.document.body.insertParagraph("Out-of-Pocket Expenses / Invoice Procedures", "End"); paragraph8.styleBuiltIn = "Heading2"; - const paragraph9 = context.document.body.insertParagraph("Client will be invoiced monthly for the consulting services and T&L expenses. Standard Contractor invoicing is assumed to be acceptable. Invoices are due upon receipt. client will be invoiced all costs associated with out-of-pocket expenses (including, without limitation, costs and expenses associated with meals, lodging, local transportation and any other applicable business expenses) listed on the invoice as a separate line item. Reimbursement for out-of-pocket expenses in connection with performance of this SOW, when authorized and up to the limits set forth in this SOW, shall be in accordance with Client's then-current published policies governing travel and associated business expenses, which information shall be provided by the Client Project Manager.", "End"); + const paragraph9 : Word.Paragraph= context.document.body.insertParagraph("Client will be invoiced monthly for the consulting services and T&L expenses. Standard Contractor invoicing is assumed to be acceptable. Invoices are due upon receipt. client will be invoiced all costs associated with out-of-pocket expenses (including, without limitation, costs and expenses associated with meals, lodging, local transportation and any other applicable business expenses) listed on the invoice as a separate line item. Reimbursement for out-of-pocket expenses in connection with performance of this SOW, when authorized and up to the limits set forth in this SOW, shall be in accordance with Client's then-current published policies governing travel and associated business expenses, which information shall be provided by the Client Project Manager.", "End"); paragraph9.styleBuiltIn = "Normal"; // Insert a page break at the end of the document. context.document.body.insertBreak("Page", "End"); @@ -62,18 +62,18 @@ script: // then wraps each search result within a content control, // finally sets a tag and title property on each content control. await Word.run(async (context) => { - const results = context.document.body.search("Contractor"); + const results: Word.RangeCollection = context.document.body.search("Contractor"); results.load("font/bold"); // Check to make sure these content controls haven't been added yet. - const customerContentControls = context.document.contentControls.getByTag("customer"); + const customerContentControls: Word.ContentControlCollection = context.document.contentControls.getByTag("customer"); customerContentControls.load("text"); await context.sync(); if (customerContentControls.items.length === 0) { for (let i = 0; i < results.items.length; i++) { results.items[i].font.bold = true; - let cc = results.items[i].insertContentControl(); + let cc: Word.ContentControl = results.items[i].insertContentControl(); cc.tag = "customer"; // This value is used in the next step of this sample. cc.title = "Customer Name " + i; } @@ -84,7 +84,7 @@ script: async function changeCustomer() { await Word.run(async (context) => { - const contentControls = context.document.contentControls.getByTag("customer"); + const contentControls: Word.ContentControlCollection = context.document.contentControls.getByTag("customer"); contentControls.load("text"); await context.sync(); @@ -106,7 +106,7 @@ script: }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -119,12 +119,11 @@ script: language: typescript template: content: |- -
+
This sample demonstrates how to use the basic document assembly objects. It creates a sample document, searches for text, creates a template, and adds paragraphs and footers.
- -
+

Try it out

- -
+

Try it out

Set the styling of the first paragraph.

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/beta/hosted/office.js + https://appsforoffice.microsoft.com/lib/beta/hosted/office.d.ts + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/99-preview-apis/insert-and-change-content-controls.yaml b/samples/word/99-preview-apis/insert-and-change-content-controls.yaml new file mode 100644 index 000000000..70ace5471 --- /dev/null +++ b/samples/word/99-preview-apis/insert-and-change-content-controls.yaml @@ -0,0 +1,201 @@ +id: word-insert-and-change-content-controls +name: Content control basics +description: Inserts, updates, and retrieves content controls. +author: OfficeDev +host: WORD +api_set: + WordApi: '1.10' +script: + content: | + document.getElementById("insert-controls").addEventListener("click", () => tryCatch(insertContentControls)); + document.getElementById("change-controls").addEventListener("click", () => tryCatch(modifyContentControls)); + document.getElementById("set-state").addEventListener("click", () => tryCatch(setState)); + document.getElementById("reset-state").addEventListener("click", () => tryCatch(resetState)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + async function insertContentControls() { + // Traverses each paragraph of the document and wraps a content control on each with either a even or odd tags. + await Word.run(async (context) => { + let paragraphs = context.document.body.paragraphs; + paragraphs.load("$none"); // Don't need any properties; just wrap each paragraph with a content control. + + await context.sync(); + + for (let i = 0; i < paragraphs.items.length; i++) { + let contentControl = paragraphs.items[i].insertContentControl(); + // For even, tag "even". + if (i % 2 === 0) { + contentControl.tag = "even"; + } else { + contentControl.tag = "odd"; + } + } + console.log("Content controls inserted: " + paragraphs.items.length); + + await context.sync(); + }); + } + + async function modifyContentControls() { + // Adds title and colors to odd and even content controls and changes their appearance. + await Word.run(async (context) => { + // Get the complete sentence (as range) associated with the insertion point. + let evenContentControls = context.document.contentControls.getByTag("even"); + let oddContentControls = context.document.contentControls.getByTag("odd"); + evenContentControls.load("length"); + oddContentControls.load("length"); + + await context.sync(); + + for (let i = 0; i < evenContentControls.items.length; i++) { + // Change a few properties and append a paragraph. + evenContentControls.items[i].set({ + color: "red", + title: "Odd ContentControl #" + (i + 1), + appearance: Word.ContentControlAppearance.tags + }); + evenContentControls.items[i].insertParagraph("This is an odd content control", "End"); + } + + for (let j = 0; j < oddContentControls.items.length; j++) { + // Change a few properties and append a paragraph. + oddContentControls.items[j].set({ + color: "green", + title: "Even ContentControl #" + (j + 1), + appearance: "Tags" + }); + oddContentControls.items[j].insertHtml("This is an even content control", "End"); + } + + await context.sync(); + }); + } + + async function setState() { + // Sets the state of the first content control. + await Word.run(async (context) => { + const state = ((document.getElementById("state-to-set") as HTMLSelectElement) + .value as unknown) as Word.ContentControlState; + let firstContentControl = context.document.contentControls.getFirstOrNullObject(); + await context.sync(); + + if (firstContentControl.isNullObject) { + console.warn("There are no content controls in this document."); + return; + } + + firstContentControl.setState(state); + firstContentControl.load("id"); + await context.sync(); + + console.log(`Set state of first content control with ID ${firstContentControl.id} to ${state}.`); + }); + } + + async function resetState() { + // Resets the state of the first content control. + await Word.run(async (context) => { + let firstContentControl = context.document.contentControls.getFirstOrNullObject(); + await context.sync(); + + if (firstContentControl.isNullObject) { + console.warn("There are no content controls in this document."); + return; + } + + firstContentControl.resetState(); + firstContentControl.load("id"); + await context.sync(); + + console.log(`Reset state of first content control with ID: ${firstContentControl.id}`); + }); + } + + async function setup() { + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph("One more paragraph.", "Start"); + body.insertParagraph("Inserting another paragraph.", "Start"); + body.insertParagraph( + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", + "Start" + ); + body.paragraphs + .getLast() + .insertText( + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", + "Replace" + ); + }); + } + + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+ This sample demonstrates how to insert content controls and change their properties. +
+
+

Set up

+ +
+
+

Try it out

+ Insert content controls on each paragraph. + +

+ Modify content control appearance and content. + +

Preview features

+ Set state of first content control. +
+ + + +

+ Reset state of first content control. + +

+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/beta/hosted/office.js + @types/office-js-preview + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/99-preview-apis/insert-and-get-pictures.yaml b/samples/word/99-preview-apis/insert-and-get-pictures.yaml deleted file mode 100644 index 4d2a75b8e..000000000 --- a/samples/word/99-preview-apis/insert-and-get-pictures.yaml +++ /dev/null @@ -1,121 +0,0 @@ -id: word-insert-and-get-pictures -name: Use inline pictures -description: Inserts and gets inline pictures. -author: OfficeDev -host: WORD -api_set: - WordApi: '1.1' -script: - content: | - $("#setup").click(() => tryCatch(setup)); - $("#insert").click(() => tryCatch(insertImage)); - $("#get").click(() => tryCatch(getImage)); - - async function insertImage() { - // Inserts an image anchored to the last paragraph. - await Word.run(async (context) => { - context.document.body.paragraphs - .getLast() - .insertParagraph("", "After") - .insertInlinePictureFromBase64(base64Image, "End"); - - await context.sync(); - }); - } - - async function getImage() { - // Gets the first image in the document. - await Word.run(async (context) => { - const firstPicture = context.document.body.inlinePictures.getFirst(); - firstPicture.load("width, height, imageFormat"); - - await context.sync(); - console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`); - console.log(`Image format: ${firstPicture.imageFormat}`); - // Get the image encoded as Base64. - const base64 = firstPicture.getBase64ImageSrc(); - - await context.sync(); - console.log(base64.value); - }); - } - - async function setup() { - // Sets up by adding a dummy paragraph. - await Word.run(async (context) => { - const body = context.document.body; - body.clear(); - body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document. ", - "End" - ); - body.paragraphs - .getLast() - .insertText( - "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching Online cover page, header, and sidebar. Click Insert and then choose the elements you want from the different Online galleries.", - "End" - ); - }); - } - - /** Default helper for invoking an action and handling errors. */ - async function tryCatch(callback) { - try { - await callback(); - } catch (error) { - // Note: In a production add-in, you'd want to notify the user through your add-in's UI. - console.error(error); - } - } - - const base64Image = - "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"; - language: typescript -template: - content: |- -
- This sample demonstrates how to insert and get inline pictures in a document. -
- -
-

Set up

- -
- -
-

Try it out

-

- -

- language: html -style: - content: |- - section.samples { - margin-top: 20px; - } - - section.samples .ms-Button, section.setup .ms-Button { - display: block; - margin-bottom: 5px; - margin-left: 20px; - min-width: 80px; - } - language: css -libraries: | - https://appsforoffice.microsoft.com/lib/beta/hosted/office.js - @types/office-js-preview - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js - - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file diff --git a/samples/word/99-preview-apis/manage-comments.yaml b/samples/word/99-preview-apis/manage-comments.yaml new file mode 100644 index 000000000..bdff83be1 --- /dev/null +++ b/samples/word/99-preview-apis/manage-comments.yaml @@ -0,0 +1,362 @@ +id: word-manage-comments +name: Manage comments +description: This sample shows how to perform operations on comments (including insert, reply, get, edit, resolve, and delete) and use comment events. +host: WORD +api_set: + WordApi: '1.10' +script: + content: |- + document.getElementById("register-event-handlers").addEventListener("click", () => tryCatch(registerEventHandlers)); + document.getElementById("insert").addEventListener("click", () => tryCatch(insertComment)); + document.getElementById("edit").addEventListener("click", () => tryCatch(editFirstCommentInSelection)); + document.getElementById("reply").addEventListener("click", () => tryCatch(replyToFirstActiveCommentInSelection)); + document.getElementById("resolve").addEventListener("click", () => tryCatch(toggleResolvedStatusOfFirstCommentInSelection)); + document.getElementById("range").addEventListener("click", () => tryCatch(getFirstCommentRangeInSelection)); + document.getElementById("get-comments-in-selection").addEventListener("click", () => tryCatch(getCommentsInSelection)); + document.getElementById("get-replies-to-first-comment-in-selection").addEventListener("click", () => tryCatch(getRepliesToFirstCommentInSelection)); + document.getElementById("delete").addEventListener("click", () => tryCatch(deleteFirstCommentInSelection)); + document.getElementById("get-comments").addEventListener("click", () => tryCatch(getComments)); + document.getElementById("deregister-event-handlers").addEventListener("click", () => tryCatch(deregisterEventHandlers)); + document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); + + let eventContexts = []; + + async function registerEventHandlers() { + // Registers event handlers. + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.track(); + await context.sync(); + + eventContexts[0] = body.onCommentAdded.add(onEventHandler); + eventContexts[1] = body.onCommentChanged.add(onChangedHandler); + eventContexts[2] = body.onCommentDeleted.add(onEventHandler); + eventContexts[3] = body.onCommentDeselected.add(onEventHandler); + eventContexts[4] = body.onCommentSelected.add(onEventHandler); + await context.sync(); + + console.log("Event handlers registered."); + }); + } + + async function insertComment() { + // Sets a comment on the selected content. + await Word.run(async (context) => { + const text = (document.getElementById("comment-text") as HTMLInputElement).value; + const comment: Word.Comment = context.document.getSelection().insertComment(text); + + // Load object to log in the console. + comment.load(); + await context.sync(); + + console.log("Comment inserted:", comment); + }); + } + + async function editFirstCommentInSelection() { + // Edits the first active comment in the selected content. + await Word.run(async (context) => { + const text = (document.getElementById("edit-comment-text") as HTMLInputElement).value; + const comments: Word.CommentCollection = context.document.getSelection().getComments(); + comments.load("items"); + await context.sync(); + + const firstActiveComment: Word.Comment = comments.items.find((item) => item.resolved !== true); + if (!firstActiveComment) { + console.warn("No active comment was found in the selection, so couldn't edit."); + return; + } + + firstActiveComment.content = text; + + // Load object to log in the console. + firstActiveComment.load(); + await context.sync(); + + console.log("Comment content changed:", firstActiveComment); + }); + } + + async function replyToFirstActiveCommentInSelection() { + // Replies to the first active comment in the selected content. + await Word.run(async (context) => { + const text = (document.getElementById("reply-text") as HTMLInputElement).value; + const comments: Word.CommentCollection = context.document.getSelection().getComments(); + comments.load("items"); + await context.sync(); + + const firstActiveComment: Word.Comment = comments.items.find((item) => item.resolved !== true); + if (firstActiveComment) { + const reply: Word.CommentReply = firstActiveComment.reply(text); + console.log("Reply added."); + } else { + console.warn("No active comment was found in the selection, so couldn't reply."); + } + }); + } + + async function toggleResolvedStatusOfFirstCommentInSelection() { + // Toggles Resolved status of the first comment in the selected content. + await Word.run(async (context) => { + const comment: Word.Comment = context.document + .getSelection() + .getComments() + .getFirstOrNullObject(); + comment.load("resolved"); + await context.sync(); + + if (comment.isNullObject) { + console.warn("No comments in the selection, so nothing to toggle."); + return; + } + + // Toggle resolved status. + // If the comment is active, set as resolved. + // If it's resolved, set resolved to false. + const resolvedBefore = comment.resolved; + console.log(`Comment Resolved status (before): ${resolvedBefore}`); + comment.resolved = !resolvedBefore; + comment.load("resolved"); + await context.sync(); + + console.log(`Comment Resolved status (after): ${comment.resolved}`); + }); + } + + async function getFirstCommentRangeInSelection() { + // Gets the range of the first comment in the selected content. + await Word.run(async (context) => { + const comment: Word.Comment = context.document.getSelection().getComments().getFirstOrNullObject(); + comment.load("contentRange"); + const range: Word.Range = comment.getRange(); + range.load("text"); + await context.sync(); + + if (comment.isNullObject) { + console.warn("No comments in the selection, so no range to get."); + return; + } + + console.log(`Comment location: ${range.text}`); + const contentRange: Word.CommentContentRange = comment.contentRange; + console.log("Comment content range:", contentRange); + }); + } + + async function getCommentsInSelection() { + // Gets the comments in the selected content. + await Word.run(async (context) => { + const comments: Word.CommentCollection = context.document.getSelection().getComments(); + + // Load objects to log in the console. + comments.load(); + await context.sync(); + + console.log("Comments:", comments); + }); + } + + async function getRepliesToFirstCommentInSelection() { + // Gets the replies to the first comment in the selected content. + await Word.run(async (context) => { + const comment: Word.Comment = context.document.getSelection().getComments().getFirstOrNullObject(); + comment.load("replies"); + await context.sync(); + + if (comment.isNullObject) { + console.warn("No comments in the selection, so no replies to get."); + return; + } + + const replies: Word.CommentReplyCollection = comment.replies; + console.log("Replies to the first comment:", replies); + }); + } + + async function deleteFirstCommentInSelection() { + // Deletes the first comment in the selected content. + await Word.run(async (context) => { + const comment: Word.Comment = context.document.getSelection().getComments().getFirstOrNullObject(); + comment.delete(); + await context.sync(); + + if (comment.isNullObject) { + console.warn("No comments in the selection, so nothing to delete."); + return; + } + + console.log("Comment deleted."); + }); + } + + async function getComments() { + // Gets the comments in the document body. + await Word.run(async (context) => { + const comments: Word.CommentCollection = context.document.body.getComments(); + + // Load objects to log in the console. + comments.load(); + await context.sync(); + + console.log("All comments:", comments); + }); + } + + async function deregisterEventHandlers() { + // Deregisters event handlers. + await Word.run(async (context) => { + for (let i = 0; i < eventContexts.length; i++) { + await Word.run(eventContexts[i].context, async (context) => { + eventContexts[i].remove(); + }); + } + + await context.sync(); + + eventContexts = []; + console.log("Removed event handlers."); + }); + } + + async function onEventHandler(event: Word.CommentEventArgs) { + // Handler for all events except onCommentChanged. + await Word.run(async (context) => { + console.log(`${event.type} event detected. Event source: ${event.source}. Comment info:`, event.commentDetails); + }); + } + + async function onChangedHandler(event: Word.CommentEventArgs) { + await Word.run(async (context) => { + console.log( + `${event.type} event detected. ${event.changeType} change made. Event source: ${event.source}. Comment info:`, event.commentDetails + ); + }); + } + + async function setup() { + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph( + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", + "Start" + ); + body.paragraphs + .getLast() + .insertText( + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", + "Replace" + ); + }); + } + // Default helper for invoking an action and handling errors. + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + console.error(error); + } + } + language: typescript +template: + content: |- +
+

This sample shows operations on comments and how to use comment events.

+

Important: Comment events APIs are currently in preview. If this snippet doesn't work, try using + Word + on a different platform.

+
+
+

Set up

+ +
+
+

Try it out

+

+ +

+

Manage comments in selection

+

Select content in document body before proceeding.

+

+ + + +

+

+ + + +

+

+ + + +

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

Manage comments in document body

+

+ +

+

+ +

+
+ language: html +style: + content: |- + section.samples { + margin-top: 20px; + } + + section.samples .ms-Button, section.setup .ms-Button { + display: block; + margin-bottom: 5px; + margin-left: 20px; + min-width: 80px; + } + language: css +libraries: |- + https://appsforoffice.microsoft.com/lib/beta/hosted/office.js + @types/office-js-preview + + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css \ No newline at end of file diff --git a/samples/word/default.yaml b/samples/word/default.yaml index 27169b905..e7bc04740 100644 --- a/samples/word/default.yaml +++ b/samples/word/default.yaml @@ -6,8 +6,8 @@ host: WORD api_set: WordApi: '1.1' script: - content: | - $("#run").click(() => tryCatch(run)); + content: |- + document.getElementById("run").addEventListener("click", () => tryCatch(run)); async function run() { await Word.run(async (context) => { @@ -19,7 +19,7 @@ script: }); } - /** Default helper for invoking an action and handling errors. */ + // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); @@ -31,7 +31,7 @@ script: } language: typescript template: - content: | + content: |- @@ -49,15 +49,9 @@ style: min-width: 80px; } language: css -libraries: | +libraries: |- https://appsforoffice.microsoft.com/lib/1/hosted/office.js - @types/office-js - - office-ui-fabric-js@1.4.0/dist/css/fabric.min.css - office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css - - core-js@2.4.1/client/core.min.js - @types/core-js + https://appsforoffice.microsoft.com/lib/1/hosted/office.d.ts - jquery@3.1.1 - @types/jquery@3.3.1 \ No newline at end of file + https://unpkg.com/office-ui-fabric-core@11.1.0/dist/css/fabric.min.css + https://unpkg.com/office-ui-fabric-js@1.5.0/dist/css/fabric.components.min.css diff --git a/snippet-extractor-metadata/excel.xlsx b/snippet-extractor-metadata/excel.xlsx index 1b2f497d0..60920aee9 100644 Binary files a/snippet-extractor-metadata/excel.xlsx and b/snippet-extractor-metadata/excel.xlsx differ diff --git a/snippet-extractor-metadata/outlook.xlsx b/snippet-extractor-metadata/outlook.xlsx index dff1cd06f..e7f1f77f9 100644 Binary files a/snippet-extractor-metadata/outlook.xlsx and b/snippet-extractor-metadata/outlook.xlsx differ diff --git a/snippet-extractor-metadata/powerpoint.xlsx b/snippet-extractor-metadata/powerpoint.xlsx index 82bf34ad0..d4a1aa15c 100644 Binary files a/snippet-extractor-metadata/powerpoint.xlsx and b/snippet-extractor-metadata/powerpoint.xlsx differ diff --git a/snippet-extractor-metadata/word.xlsx b/snippet-extractor-metadata/word.xlsx index ae40237c6..0785001fa 100644 Binary files a/snippet-extractor-metadata/word.xlsx and b/snippet-extractor-metadata/word.xlsx differ diff --git a/snippet-extractor-output/snippets.yaml b/snippet-extractor-output/snippets.yaml index 63f063afd..de9e20842 100644 --- a/snippet-extractor-output/snippets.yaml +++ b/snippet-extractor-output/snippets.yaml @@ -1,8 +1,9 @@ -'Excel.AggregationFunction:enum': +Excel.AggregationFunction:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-filters-and-summaries.yaml + async function genericFunctionSwitch(functionType: Excel.AggregationFunction) { await Excel.run(async (context) => { @@ -15,19 +16,12 @@ await context.sync(); }); } -'Excel.Application#calculate:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/90-scenarios/performance-optimization.yaml - - await Excel.run(async (context) => { - context.application.calculate(Excel.CalculationType.full); - }); -'Excel.Application#decimalSeparator:member': +Excel.Application#decimalSeparator:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/culture-info.yaml + await Excel.run(async (context) => { context.application.load("decimalSeparator,thousandsSeparator"); context.application.cultureInfo.numberFormat.load("numberDecimalSeparator,numberGroupSeparator"); @@ -51,11 +45,21 @@ await context.sync(); }); -'Excel.Application#suspendScreenUpdatingUntilNextSync:member(1)': +Excel.Application#calculate:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/90-scenarios/performance-optimization.yaml + + + await Excel.run(async (context) => { + context.application.calculate(Excel.CalculationType.full); + }); +Excel.Application#suspendScreenUpdatingUntilNextSync:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/90-scenarios/performance-optimization.yaml + await Excel.run(async (context) => { // Recreate the data in the worksheet with random data. const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -85,11 +89,12 @@ console.log(`Ending. Adding ${ROW_COUNT * COLUMN_COUNT} cells took ${Date.now() - startTime} milliseconds`); }); -'Excel.ArrowheadLength:enum': +Excel.ArrowheadLength:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml + await Excel.run(async (context) => { const shapes = context.workbook.worksheets.getItem("Shapes").shapes; const line = shapes.getItem("StraightLine").line; @@ -103,11 +108,12 @@ await context.sync(); }); -'Excel.ArrowheadStyle:enum': +Excel.ArrowheadStyle:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml + await Excel.run(async (context) => { const shapes = context.workbook.worksheets.getItem("Shapes").shapes; const line = shapes.getItem("StraightLine").line; @@ -121,11 +127,12 @@ await context.sync(); }); -'Excel.ArrowheadWidth:enum': +Excel.ArrowheadWidth:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml + await Excel.run(async (context) => { const shapes = context.workbook.worksheets.getItem("Shapes").shapes; const line = shapes.getItem("StraightLine").line; @@ -139,11 +146,12 @@ await context.sync(); }); -'Excel.AutoFillType:enum': +Excel.AutoFillType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-auto-fill.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); const sumCell = sheet.getRange("K4"); @@ -153,11 +161,12 @@ sumCell.format.autofitColumns(); await context.sync(); }); -'Excel.AutoFilter#apply:member(1)': +Excel.AutoFilter#apply:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-auto-filter.yaml + // This function adds a percentage AutoFilter to the active worksheet // and applies the filter to a column of the used range. @@ -175,11 +184,12 @@ await context.sync(); }); -'Excel.AutoFilter#clearColumnCriteria:member(1)': +Excel.AutoFilter#clearColumnCriteria:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-auto-filter.yaml + // This function clears the AutoFilter setting from one column. await Excel.run(async (context) => { @@ -190,11 +200,12 @@ sheet.autoFilter.clearColumnCriteria(3); await context.sync(); }); -'Excel.AutoFilter#reapply:member(1)': +Excel.AutoFilter#reapply:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-auto-filter.yaml + // This function refreshes the AutoFilter to ensure that changes are captured. @@ -206,11 +217,12 @@ sheet.autoFilter.reapply(); await context.sync(); }); -'Excel.AutoFilter#remove:member(1)': +Excel.AutoFilter#remove:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-auto-filter.yaml + // This function removes all AutoFilters from the active worksheet. await Excel.run(async (context) => { @@ -221,11 +233,12 @@ sheet.autoFilter.remove(); await context.sync(); }); -'Excel.Binding#onDataChanged:member': +Excel.Binding#onDataChanged:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/data-changed.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const salesTable = sheet.tables.getItem("SalesTable"); @@ -236,11 +249,12 @@ await context.sync(); }); -'Excel.BindingType:enum': +Excel.BindingType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-disable-events.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const sumRange = sheet.getRange("B20:P20"); @@ -254,11 +268,12 @@ } await context.sync(); }); -'Excel.BorderLineStyle:enum': +Excel.BorderLineStyle:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -330,11 +345,12 @@ sheet.getUsedRange().format.autofitColumns(); await context.sync(); }); -'Excel.BuiltInStyle:enum': +Excel.BuiltInStyle:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -406,11 +422,12 @@ sheet.getUsedRange().format.autofitColumns(); await context.sync(); }); -'Excel.CalculationMode:enum': +Excel.CalculationMode:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-calculation.yaml + await Excel.run(async (context) => { context.application.calculationMode = Excel.CalculationMode.manual; context.application.load("calculationMode"); @@ -418,20 +435,197 @@ console.log("Current calculation mode: " + context.application.calculationMode); }); -'Excel.CalculationType:enum': +Excel.CalculationType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-calculation.yaml + await Excel.run(async (context) => { context.application.calculate(Excel.CalculationType.recalculate); await context.sync(); }); -'Excel.CellPropertiesFill#color:member': +Excel.CardLayoutSection:type: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-entity-attribution.yaml + + + function makeProductEntity(productID: number, productName: string, product?: + any) { + const entity: Excel.EntityCellValue = { + type: Excel.CellValueType.entity, + text: productName, + properties: { /* Excel.EntityPropertyType */ + "Product ID": { + type: Excel.CellValueType.string, + basicValue: productID.toString() || "" + }, + "Product Name": { + type: Excel.CellValueType.string, + basicValue: productName || "" + }, + "Quantity Per Unit": { + type: Excel.CellValueType.string, + basicValue: product.quantityPerUnit || "" + }, + // Add Unit Price as a formatted number. + "Unit Price": { + type: Excel.CellValueType.formattedNumber, + basicValue: product.unitPrice, + numberFormat: "$* #,##0.00" + } + }, + layouts: { /* Excel.EntityViewLayouts */ + card: { /* Excel.EntityCardLayout */ + title: { property: "Product Name" }, + sections: [ /* Excel.CardLayoutSection */ + { + layout: "List", + properties: ["Product ID"] + }, + { + layout: "List", + title: "Quantity and price", + collapsible: true, + collapsed: false, + properties: ["Quantity Per Unit", "Unit Price"] + } + ] + } + }, + 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 clicked. + } + }; + + return entity; + } +Excel.CellBorder:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Creating the SettableCellProperties objects to use for the range. + // In your add-in, these should be created once, outside the function. + const topHeaderProps: Excel.SettableCellProperties = { + // The style property takes a string matching the name of an Excel style. + // Built-in style names are listed in the `BuiltInStyle` enum. + // Note that a style will overwrite any formatting, + // so do not use the format property with the style property. + style: "Heading1" + }; + + const headerProps: Excel.SettableCellProperties = { + // Any subproperties of format that are not set will not be changed when these cell properties are set. + format: { + fill: { + color: "Blue" + }, + font: { + color: "White", + bold: true + } + } + }; + + const nonApplicableProps: Excel.SettableCellProperties = { + format: { + fill: { + pattern: Excel.FillPattern.gray25 + }, + font: { + color: "Gray", + italic: true + } + } + }; + + const matchupScoreProps: Excel.SettableCellProperties = { + format: { + borders: { + bottom: { + style: Excel.BorderLineStyle.continuous + }, + left: { + style: Excel.BorderLineStyle.continuous + }, + right: { + style: Excel.BorderLineStyle.continuous + }, + top: { + style: Excel.BorderLineStyle.continuous + } + } + } + }; + + const range = sheet.getRange("A1:E5"); + + // You can use empty JSON objects to avoid changing a cell's properties. + range.setCellProperties([ + [topHeaderProps, {}, {}, {}, {}], + [{}, {}, headerProps, headerProps, headerProps], + [{}, headerProps, nonApplicableProps, matchupScoreProps, matchupScoreProps], + [{}, headerProps, matchupScoreProps, nonApplicableProps, matchupScoreProps], + [{}, headerProps, matchupScoreProps, matchupScoreProps, nonApplicableProps] + ]); + + sheet.getUsedRange().format.autofitColumns(); + await context.sync(); + }); +Excel.CellControl:type: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml + + + // Add checkboxes to the table. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Get the second column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Change the boolean values to checkboxes. + range.control = { + type: Excel.CellControlType.checkbox + }; + await context.sync(); + }); +Excel.CellControlType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml + + + // Add checkboxes to the table. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Get the second column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Change the boolean values to checkboxes. + range.control = { + type: Excel.CellControlType.checkbox + }; + await context.sync(); + }); +Excel.CellPropertiesFill#color:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -503,11 +697,12 @@ sheet.getUsedRange().format.autofitColumns(); await context.sync(); }); -'Excel.CellPropertiesFillLoadOptions#color:member': +Excel.CellPropertiesFillLoadOptions#color:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + await Excel.run(async (context) => { const cell = context.workbook.getActiveCell(); @@ -531,11 +726,12 @@ console.log( `Address: ${cellProperties.address}\nStyle: ${cellProperties.style}\nFill Color: ${cellProperties.format.fill.color}\nFont Color: ${cellProperties.format.font.color}`); }); -'Excel.CellPropertiesFont#color:member': +Excel.CellPropertiesFont#color:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -607,11 +803,12 @@ sheet.getUsedRange().format.autofitColumns(); await context.sync(); }); -'Excel.CellPropertiesFontLoadOptions#color:member': +Excel.CellPropertiesFontLoadOptions#color:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + await Excel.run(async (context) => { const cell = context.workbook.getActiveCell(); @@ -635,11 +832,12 @@ console.log( `Address: ${cellProperties.address}\nStyle: ${cellProperties.style}\nFill Color: ${cellProperties.format.fill.color}\nFont Color: ${cellProperties.format.font.color}`); }); -'Excel.CellPropertiesLoadOptions#address:member': +Excel.CellPropertiesLoadOptions#address:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + await Excel.run(async (context) => { const cell = context.workbook.getActiveCell(); @@ -663,11 +861,12 @@ console.log( `Address: ${cellProperties.address}\nStyle: ${cellProperties.style}\nFill Color: ${cellProperties.format.fill.color}\nFont Color: ${cellProperties.format.font.color}`); }); -'Excel.CellValueConditionalFormat#format:member': +Excel.CellValueConditionalFormat#format:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B21:E23"); @@ -678,11 +877,12 @@ await context.sync(); }); -'Excel.CellValueConditionalFormat#rule:member': +Excel.CellValueConditionalFormat#rule:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B21:E23"); @@ -693,11 +893,12 @@ await context.sync(); }); -'Excel.CellValueType:enum': +Excel.CellValueType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-error-values.yaml + // This function sets the value of cell A1 to a #BUSY! error using data types. @@ -706,7 +907,7 @@ const sheet = context.workbook.worksheets.getItemOrNullObject("Sample"); const range = sheet.getRange("A1"); - // Get the error data type and set its type to `busy`. + // Get the error data type and set its type to `busy`. const error: Excel.ErrorCellValue = { type: Excel.CellValueType.error, errorType: Excel.ErrorCellValueType.busy @@ -716,11 +917,12 @@ range.valuesAsJson = [[error]]; await context.sync(); }); -'Excel.Chart#getDataTableOrNullObject:member(1)': +Excel.Chart#getDataTableOrNullObject:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-table.yaml + // This function adds a data table to a chart that already exists on the worksheet. @@ -734,11 +936,12 @@ chartDataTable.visible = true; await context.sync(); }); -'Excel.Chart#onActivated:member': +Excel.Chart#onActivated:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-chart-activated.yaml + await Excel.run(async (context) => { const pieChart = context.workbook.worksheets.getActiveWorksheet().charts.getItem("Pie"); @@ -755,6 +958,7 @@ // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-chart-activated.yaml + async function chartActivated(event) { await Excel.run(async (context) => { // Retrieve the worksheet. @@ -769,11 +973,12 @@ console.log(`A chart was activated. ID: ${event.chartId}. Chart name: ${activatedChart.name}.`); }); } -'Excel.Chart#onDeactivated:member': +Excel.Chart#onDeactivated:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-chart-activated.yaml + await Excel.run(async (context) => { const pieChart = context.workbook.worksheets.getActiveWorksheet().charts.getItem("Pie"); @@ -790,17 +995,19 @@ // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-chart-activated.yaml + async function chartDeactivated(event) { await Excel.run(async (context) => { // Callback function for when the chart is deactivated. console.log("The pie chart is NOT active."); }); } -'Excel.ChartAxis#displayUnit:member': +Excel.ChartAxis#displayUnit:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-axis.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); @@ -815,11 +1022,12 @@ console.log("The vertical axis display unit is: " + valueAxis.displayUnit); }); -'Excel.ChartAxis#showDisplayUnitLabel:member': +Excel.ChartAxis#showDisplayUnitLabel:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-axis.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); let chart = sheet.charts.getItemAt(0); @@ -830,11 +1038,12 @@ await context.sync(); }); -'Excel.ChartCollection#onActivated:member': +Excel.ChartCollection#onActivated:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-chart-activated.yaml + await Excel.run(async (context) => { const pieChart = context.workbook.worksheets.getActiveWorksheet().charts.getItem("Pie"); @@ -851,6 +1060,7 @@ // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-chart-activated.yaml + async function chartActivated(event) { await Excel.run(async (context) => { // Retrieve the worksheet. @@ -865,11 +1075,12 @@ console.log(`A chart was activated. ID: ${event.chartId}. Chart name: ${activatedChart.name}.`); }); } -'Excel.ChartCollection#onDeactivated:member': +Excel.ChartCollection#onDeactivated:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-chart-activated.yaml + await Excel.run(async (context) => { const pieChart = context.workbook.worksheets.getActiveWorksheet().charts.getItem("Pie"); @@ -886,17 +1097,62 @@ // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-chart-activated.yaml + async function chartDeactivated(event) { await Excel.run(async (context) => { // Callback function for when the chart is deactivated. console.log("The pie chart is NOT active."); }); } -'Excel.ChartDataTable#format:member': +Excel.ChartDataLabel:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-labels.yaml + + + // This function styles substrings within data label text using font + formatting. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + await context.sync(); + + const series = chart.series.getItemAt(0); + series.load("points"); + await context.sync(); + + series.points.load("items"); + await context.sync(); + + // Style a substring in the first data label. + let searchString = "sports"; + let dataLabel = series.points.getItemAt(dataLabelInfo[0].index).dataLabel.load("text"); + await context.sync(); + let substringStart = dataLabel.text.indexOf(searchString); + let subLabel = dataLabel.getSubstring(substringStart, searchString.length); + subLabel.font.size = 13; + subLabel.font.bold = true; + + // Style a substring in the second data label. + searchString = "'Titanic'"; + dataLabel = series.points.getItemAt(dataLabelInfo[1].index).dataLabel.load("text"); + await context.sync(); + + substringStart = dataLabel.text.indexOf(searchString); + subLabel = dataLabel.getSubstring(substringStart, searchString.length); + subLabel.font.name = "Calibri"; + subLabel.font.size = 13; + subLabel.font.italic = true; + subLabel.font.color = "blue"; + await context.sync(); + }); +Excel.ChartDataTable#format:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-table.yaml + // This function adjusts the display and format of a chart data table that already exists on the worksheet. @@ -921,11 +1177,12 @@ chartDataTableFormat.border.color = "blue"; await context.sync(); }); -'Excel.ChartDataTable#showHorizontalBorder:member': +Excel.ChartDataTable#showHorizontalBorder:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-table.yaml + // This function adjusts the display and format of a chart data table that already exists on the worksheet. @@ -950,11 +1207,12 @@ chartDataTableFormat.border.color = "blue"; await context.sync(); }); -'Excel.ChartDataTable#showLegendKey:member': +Excel.ChartDataTable#showLegendKey:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-table.yaml + // This function adjusts the display and format of a chart data table that already exists on the worksheet. @@ -979,11 +1237,12 @@ chartDataTableFormat.border.color = "blue"; await context.sync(); }); -'Excel.ChartDataTable#showOutlineBorder:member': +Excel.ChartDataTable#showOutlineBorder:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-table.yaml + // This function adjusts the display and format of a chart data table that already exists on the worksheet. @@ -1008,11 +1267,12 @@ chartDataTableFormat.border.color = "blue"; await context.sync(); }); -'Excel.ChartDataTable#showVerticalBorder:member': +Excel.ChartDataTable#showVerticalBorder:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-table.yaml + // This function adjusts the display and format of a chart data table that already exists on the worksheet. @@ -1037,11 +1297,12 @@ chartDataTableFormat.border.color = "blue"; await context.sync(); }); -'Excel.ChartDataTable#visible:member': +Excel.ChartDataTable#visible:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-table.yaml + // This function adds a data table to a chart that already exists on the worksheet. @@ -1055,11 +1316,12 @@ chartDataTable.visible = true; await context.sync(); }); -'Excel.ChartDataTableFormat#border:member': +Excel.ChartDataTableFormat#border:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-table.yaml + // This function adjusts the display and format of a chart data table that already exists on the worksheet. @@ -1084,11 +1346,12 @@ chartDataTableFormat.border.color = "blue"; await context.sync(); }); -'Excel.ChartDataTableFormat#font:member': +Excel.ChartDataTableFormat#font:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-table.yaml + // This function adjusts the display and format of a chart data table that already exists on the worksheet. @@ -1113,11 +1376,12 @@ chartDataTableFormat.border.color = "blue"; await context.sync(); }); -'Excel.ChartFill#setSolidColor:member(1)': +Excel.ChartFill#setSolidColor:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-point.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); @@ -1129,11 +1393,58 @@ await context.sync(); }); -'Excel.ChartLegendFormat#font:member': +Excel.ChartLeaderLines:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml + + + // The following code changes the format of leader lines. It adjusts color, + weight, and line style. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + const series = chart.series.getItemAt(0); + const dataLabels = series.dataLabels; + const lineFormat = dataLabels.leaderLines.format; + + // Set leader line formatting properties. + lineFormat.line.color = "blue"; + lineFormat.line.weight = 2; + lineFormat.line.lineStyle = Excel.ChartLineStyle.dot; + + await context.sync(); + }); +Excel.ChartLeaderLinesFormat:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml + + + // The following code changes the format of leader lines. It adjusts color, + weight, and line style. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + const series = chart.series.getItemAt(0); + const dataLabels = series.dataLabels; + const lineFormat = dataLabels.leaderLines.format; + + // Set leader line formatting properties. + lineFormat.line.color = "blue"; + lineFormat.line.weight = 2; + lineFormat.line.lineStyle = Excel.ChartLineStyle.dot; + + await context.sync(); + }); +Excel.ChartLegendFormat#font:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-legend.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); @@ -1151,57 +1462,172 @@ await context.sync(); }); -'Excel.ChartSeries#delete:member(1)': +Excel.ChartPoint:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-series.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-labels.yaml + + + // This function adds data labels to specific chart points + + // and sets their text and position. await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const seriesCollection = sheet.charts.getItemAt(0).series; - seriesCollection.load("count"); + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); await context.sync(); - if (seriesCollection.count > 0) { - const series = seriesCollection.getItemAt(0); + const series = chart.series.getItemAt(0); + series.points.load("dataLabel"); + await context.sync(); + + // Define properties for data label positioning and shape. + const labelProperties = [ + { + top: 70, + geometricShapeType: Excel.GeometricShapeType.rectangle + }, + { + top: 200, + geometricShapeType: Excel.GeometricShapeType.rectangle + } + ]; - // Delete the first series. - series.delete(); - } + // Add data labels to specific chart points and set their text and properties. + for (let i = 0; i < dataLabelInfo.length; i++) { + const point = series.points.getItemAt(dataLabelInfo[i].index); + point.hasDataLabel = true; + const dataLabel = point.dataLabel; + dataLabel.text = dataLabelInfo[i].news; + dataLabel.set(labelProperties[i]); + } await context.sync(); }); -'Excel.ChartSeries#getDimensionDataSourceString:member(1)': +Excel.ChartPointsCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-source.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-labels.yaml - // This function retrieves the data source information of a chart series in - the Sample worksheet. - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); + // This function adds data labels to specific chart points - // Get the first chart series from the first chart on the worksheet. - const seriesCollection = sheet.charts.getItemAt(0).series; - const series = seriesCollection.getItemAt(0); + // and sets their text and position. - // Get the series data source string and type values. - const dataSourceString = series.getDimensionDataSourceString("Values"); - const dataSourceType = series.getDimensionDataSourceType("Values"); + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + await context.sync(); - series.load("name"); + const series = chart.series.getItemAt(0); + series.points.load("dataLabel"); await context.sync(); - // Log the data source information to the console. - console.log(series.name + " data source string: " + dataSourceString.value); - console.log(series.name + " data source type: " + dataSourceType.value); - }); -'Excel.ChartSeries#getDimensionDataSourceType:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-source.yaml - + // Define properties for data label positioning and shape. + const labelProperties = [ + { + top: 70, + geometricShapeType: Excel.GeometricShapeType.rectangle + }, + { + top: 200, + geometricShapeType: Excel.GeometricShapeType.rectangle + } + ]; + + // Add data labels to specific chart points and set their text and properties. + for (let i = 0; i < dataLabelInfo.length; i++) { + const point = series.points.getItemAt(dataLabelInfo[i].index); + point.hasDataLabel = true; + + const dataLabel = point.dataLabel; + dataLabel.text = dataLabelInfo[i].news; + dataLabel.set(labelProperties[i]); + } + await context.sync(); + }); +Excel.ChartSeries#getDimensionValues:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-bubble-chart.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + + // The sample chart is of type `Excel.ChartType.bubble`. + const bubbleChart = sheet.charts.getItem("Product Chart"); + + // Get the first series in the chart. + const firstSeries = bubbleChart.series.getItemAt(0); + + // Get the values for the dimensions we're interested in. + const bubbleSize = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.bubbleSizes); + const xValues = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.xvalues); + const yValues = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.yvalues); + const category = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.categories); + + await context.sync(); + + // Log the information. + console.log(`Series ${category.value} - X:${xValues.value},Y:${yValues.value},Bubble:${bubbleSize.value}`); + }); +Excel.ChartSeries#setBubbleSizes:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-bubble-chart.yaml + + + await Excel.run(async (context) => { + /* + The table is expected to look like this: + Product, Inventory, Price, Current Market Share + Calamansi, 2000, $2.45, 10% + ... + + We want each bubble to represent a single row. + */ + + // Get the worksheet and table data. + const sheet = context.workbook.worksheets.getItem("Sample"); + const table = sheet.tables.getItem("Sales"); + const dataRange = table.getDataBodyRange(); + + // Get the table data without the row names. + const valueRange = dataRange.getOffsetRange(0, 1).getResizedRange(0, -1); + + // Create the chart. + const bubbleChart = sheet.charts.add(Excel.ChartType.bubble, valueRange); + bubbleChart.name = "Product Chart"; + + // Remove the default series, since we want a unique series for each row. + bubbleChart.series.getItemAt(0).delete(); + + // Load the data necessary to make a chart series. + dataRange.load(["rowCount", "values"]); + await context.sync(); + + // For each row, create a chart series (a bubble). + for (let i = 0; i < dataRange.rowCount; i++) { + const newSeries = bubbleChart.series.add(dataRange.values[i][0], i); + newSeries.setXAxisValues(dataRange.getCell(i, 1)); + newSeries.setValues(dataRange.getCell(i, 2)); + newSeries.setBubbleSizes(dataRange.getCell(i, 3)); + + // Show the product name and market share percentage. + newSeries.dataLabels.showSeriesName = true; + newSeries.dataLabels.showBubbleSize = true; + newSeries.dataLabels.showValue = false; + } + + await context.sync(); + }); +Excel.ChartSeries#getDimensionDataSourceString:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-source.yaml + + // This function retrieves the data source information of a chart series in the Sample worksheet. @@ -1223,36 +1649,207 @@ console.log(series.name + " data source string: " + dataSourceString.value); console.log(series.name + " data source type: " + dataSourceType.value); }); -'Excel.ChartSeries#getDimensionValues:member(1)': +Excel.ChartSeries#getDimensionDataSourceType:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-bubble-chart.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-source.yaml + + + // This function retrieves the data source information of a chart series in + the Sample worksheet. await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); - // The sample chart is of type `Excel.ChartType.bubble`. - const bubbleChart = sheet.charts.getItem("Product Chart"); + // Get the first chart series from the first chart on the worksheet. + const seriesCollection = sheet.charts.getItemAt(0).series; + const series = seriesCollection.getItemAt(0); - // Get the first series in the chart. - const firstSeries = bubbleChart.series.getItemAt(0); + // Get the series data source string and type values. + const dataSourceString = series.getDimensionDataSourceString("Values"); + const dataSourceType = series.getDimensionDataSourceType("Values"); - // Get the values for the dimensions we're interested in. - const bubbleSize = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.bubbleSizes); - const xValues = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.xvalues); - const yValues = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.yvalues); - const category = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.categories); + series.load("name"); + await context.sync(); + + // Log the data source information to the console. + console.log(series.name + " data source string: " + dataSourceString.value); + console.log(series.name + " data source type: " + dataSourceType.value); + }); +Excel.ChartSeries:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml + + + // The following code adds data labels to the chart and positions them to + demonstrate leader lines. + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + const series = chart.series.getItemAt(0); + + // Enable data labels for the series. Leader lines are enabled by default. + series.hasDataLabels = true; + series.points.load("items"); + await context.sync(); + + // Load the top position for each data label. + series.points.items.forEach((point) => point.dataLabel.load("top")); await context.sync(); - // Log the information. - console.log(`Series ${category.value} - X:${xValues.value},Y:${yValues.value},Bubble:${bubbleSize.value}`); + // Move some data labels to create distance from their chart points. + const point1 = series.points.items[1]; + const point2 = series.points.items[2]; + point1.dataLabel.top -= 50; + point2.dataLabel.top += 50; + + // Format the data labels. + series.dataLabels.geometricShapeType = Excel.GeometricShapeType.rectangle; + series.dataLabels.showCategoryName = true; + series.dataLabels.format.border.weight = 1; + + await context.sync(); + }); +Excel.ChartSeries#hasDataLabels:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml + + + // The following code adds data labels to the chart and positions them to + demonstrate leader lines. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + const series = chart.series.getItemAt(0); + + // Enable data labels for the series. Leader lines are enabled by default. + series.hasDataLabels = true; + series.points.load("items"); + await context.sync(); + + // Load the top position for each data label. + series.points.items.forEach((point) => point.dataLabel.load("top")); + await context.sync(); + + // Move some data labels to create distance from their chart points. + const point1 = series.points.items[1]; + const point2 = series.points.items[2]; + point1.dataLabel.top -= 50; + point2.dataLabel.top += 50; + + // Format the data labels. + series.dataLabels.geometricShapeType = Excel.GeometricShapeType.rectangle; + series.dataLabels.showCategoryName = true; + series.dataLabels.format.border.weight = 1; + + await context.sync(); + }); +Excel.ChartSeries#points:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml + + + // The following code adds data labels to the chart and positions them to + demonstrate leader lines. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + const series = chart.series.getItemAt(0); + + // Enable data labels for the series. Leader lines are enabled by default. + series.hasDataLabels = true; + series.points.load("items"); + await context.sync(); + + // Load the top position for each data label. + series.points.items.forEach((point) => point.dataLabel.load("top")); + await context.sync(); + + // Move some data labels to create distance from their chart points. + const point1 = series.points.items[1]; + const point2 = series.points.items[2]; + point1.dataLabel.top -= 50; + point2.dataLabel.top += 50; + + // Format the data labels. + series.dataLabels.geometricShapeType = Excel.GeometricShapeType.rectangle; + series.dataLabels.showCategoryName = true; + series.dataLabels.format.border.weight = 1; + + await context.sync(); + }); +Excel.ChartSeries#showLeaderLines:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml + + + // The following code disables leader lines for chart data labels. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem(sheetName); + const chart = sheet.charts.getItemAt(0); + const series = chart.series.getItemAt(0); + const dataLabels = series.dataLabels; + + // Disable leader lines. + dataLabels.showLeaderLines = false; + + await context.sync(); + }); +Excel.ChartSeries#delete:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-series.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + const seriesCollection = sheet.charts.getItemAt(0).series; + seriesCollection.load("count"); + await context.sync(); + + if (seriesCollection.count > 0) { + const series = seriesCollection.getItemAt(0); + + // Delete the first series. + series.delete(); + } + + await context.sync(); + }); +Excel.ChartSeries#setValues:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-series.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + + let seriesCollection = sheet.charts.getItemAt(0); + let rangeSelection = sheet.getRange("C2:C7"); + let xRangeSelection = sheet.getRange("A1:A7"); + + // Add a series. + let newSeries = seriesCollection.series.add("Qtr2"); + newSeries.setValues(rangeSelection); + newSeries.setXAxisValues(xRangeSelection); + + await context.sync(); }); -'Excel.ChartSeries#markerBackgroundColor:member': +Excel.ChartSeries#markerBackgroundColor:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-series-markers.yaml + await Excel.run(async (context) => { let sheet = context.workbook.worksheets.getItem("Sample"); let salesTable = sheet.tables.getItem("SalesTable"); @@ -1280,11 +1877,12 @@ await context.sync(); }); -'Excel.ChartSeries#markerForegroundColor:member': +Excel.ChartSeries#markerForegroundColor:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-series-markers.yaml + await Excel.run(async (context) => { let sheet = context.workbook.worksheets.getItem("Sample"); let salesTable = sheet.tables.getItem("SalesTable"); @@ -1312,11 +1910,12 @@ await context.sync(); }); -'Excel.ChartSeries#markerSize:member': +Excel.ChartSeries#markerSize:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-series-markers.yaml + await Excel.run(async (context) => { let sheet = context.workbook.worksheets.getItem("Sample"); let salesTable = sheet.tables.getItem("SalesTable"); @@ -1344,11 +1943,12 @@ await context.sync(); }); -'Excel.ChartSeries#markerStyle:member': +Excel.ChartSeries#markerStyle:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-series-markers.yaml + await Excel.run(async (context) => { let sheet = context.workbook.worksheets.getItem("Sample"); let salesTable = sheet.tables.getItem("SalesTable"); @@ -1376,118 +1976,52 @@ await context.sync(); }); -'Excel.ChartSeries#setBubbleSizes:member(1)': +Excel.ChartSeriesBy:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-bubble-chart.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-source.yaml + await Excel.run(async (context) => { - /* - The table is expected to look like this: - Product, Inventory, Price, Current Market Share - Calamansi, 2000, $2.45, 10% - ... + // Create a new worksheet called "Sample" and activate it. + context.workbook.worksheets.getItemOrNullObject("Sample").delete(); + const sheet = context.workbook.worksheets.add("Sample"); + + // Create an a table named SalesTable on the Sample worksheet. + let expensesTable = sheet.tables.add("A1:E1", true); + expensesTable.name = "SalesTable"; - We want each bubble to represent a single row. - */ + expensesTable.getHeaderRowRange().values = [["Product", "Qtr1", "Qtr2", "Qtr3", "Qtr4"]]; + expensesTable.rows.add(null, [ + ["Frames", 5000, 7000, 6544, 4377], + ["Saddles", 400, 323, 276, 651], + ["Brake levers", 12000, 8766, 8456, 9812], + ["Chains", 1550, 1088, 692, 853], + ["Mirrors", 225, 600, 923, 544], + ["Spokes", 6005, 7634, 4589, 8765] + ]); + + sheet.getUsedRange().format.autofitColumns(); + sheet.getUsedRange().format.autofitRows(); + sheet.activate(); - // Get the worksheet and table data. - const sheet = context.workbook.worksheets.getItem("Sample"); - const table = sheet.tables.getItem("Sales"); - const dataRange = table.getDataBodyRange(); + // Create a line chart based on data from SalesTable. + let dataRange = sheet.getRange("A1:E7"); + let chart = sheet.charts.add("Line", dataRange, Excel.ChartSeriesBy.rows); - // Get the table data without the row names. - const valueRange = dataRange.getOffsetRange(0, 1).getResizedRange(0, -1); - - // Create the chart. - const bubbleChart = sheet.charts.add(Excel.ChartType.bubble, valueRange); - bubbleChart.name = "Product Chart"; - - // Remove the default series, since we want a unique series for each row. - bubbleChart.series.getItemAt(0).delete(); - - // Load the data necessary to make a chart series. - dataRange.load(["rowCount", "values"]); - await context.sync(); - - // For each row, create a chart series (a bubble). - for (let i = 0; i < dataRange.rowCount; i++) { - const newSeries = bubbleChart.series.add(dataRange.values[i][0], i); - newSeries.setXAxisValues(dataRange.getCell(i, 1)); - newSeries.setValues(dataRange.getCell(i, 2)); - newSeries.setBubbleSizes(dataRange.getCell(i, 3)); - - // Show the product name and market share percentage. - newSeries.dataLabels.showSeriesName = true; - newSeries.dataLabels.showBubbleSize = true; - newSeries.dataLabels.showValue = false; - } - - await context.sync(); - }); -'Excel.ChartSeries#setValues:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-series.yaml - - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - - let seriesCollection = sheet.charts.getItemAt(0); - let rangeSelection = sheet.getRange("C2:C7"); - let xRangeSelection = sheet.getRange("A1:A7"); - - // Add a series. - let newSeries = seriesCollection.series.add("Qtr2"); - newSeries.setValues(rangeSelection); - newSeries.setXAxisValues(xRangeSelection); - - await context.sync(); - }); -'Excel.ChartSeriesBy:enum': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-source.yaml - - await Excel.run(async (context) => { - // Create a new worksheet called "Sample" and activate it. - context.workbook.worksheets.getItemOrNullObject("Sample").delete(); - const sheet = context.workbook.worksheets.add("Sample"); - - // Create an a table named SalesTable on the Sample worksheet. - let expensesTable = sheet.tables.add("A1:E1", true); - expensesTable.name = "SalesTable"; - - expensesTable.getHeaderRowRange().values = [["Product", "Qtr1", "Qtr2", "Qtr3", "Qtr4"]]; - expensesTable.rows.add(null, [ - ["Frames", 5000, 7000, 6544, 4377], - ["Saddles", 400, 323, 276, 651], - ["Brake levers", 12000, 8766, 8456, 9812], - ["Chains", 1550, 1088, 692, 853], - ["Mirrors", 225, 600, 923, 544], - ["Spokes", 6005, 7634, 4589, 8765] - ]); - - sheet.getUsedRange().format.autofitColumns(); - sheet.getUsedRange().format.autofitRows(); - sheet.activate(); - - // Create a line chart based on data from SalesTable. - let dataRange = sheet.getRange("A1:E7"); - let chart = sheet.charts.add("Line", dataRange, Excel.ChartSeriesBy.rows); - - // Position and style the chart. - chart.setPosition("A15", "E30"); - chart.legend.position = "Right"; - chart.legend.format.fill.setSolidColor("white"); + // Position and style the chart. + chart.setPosition("A15", "E30"); + chart.legend.position = "Right"; + chart.legend.format.fill.setSolidColor("white"); await context.sync(); }); -'Excel.ChartSeriesDimension:enum': +Excel.ChartSeriesDimension:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-bubble-chart.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); @@ -1508,11 +2042,12 @@ // Log the information. console.log(`Series ${category.value} - X:${xValues.value},Y:${yValues.value},Bubble:${bubbleSize.value}`); }); -'Excel.ChartTitle#getSubstring:member(1)': +Excel.ChartTitle#getSubstring:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-title-format.yaml + await Excel.run(async (context) => { let sheet = context.workbook.worksheets.getItem("Sample"); let chart = sheet.charts.getItemAt(0); @@ -1521,11 +2056,12 @@ chart.title.getSubstring(0, 7).font.color = "Yellow"; await context.sync(); }); -'Excel.ChartTitle#textOrientation:member': +Excel.ChartTitle#textOrientation:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-title-format.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const title = sheet.charts.getItemAt(0).title; @@ -1533,11 +2069,12 @@ await context.sync(); }); -'Excel.ChartTrendline#type:member': +Excel.ChartTrendline#type:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-trendlines.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); @@ -1551,11 +2088,12 @@ console.log("The trendline type is:" + trendline.type); }); -'Excel.ChartTrendlineCollection#add:member(1)': +Excel.ChartTrendlineCollection#add:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-trendlines.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); @@ -1566,11 +2104,12 @@ await context.sync(); }); -'Excel.ChartTrendlineFormat#line:member': +Excel.ChartTrendlineFormat#line:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-trendlines.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); @@ -1585,11 +2124,12 @@ console.log("The trendline color has been set to:" + line.color); }); -'Excel.ChartType:enum': +Excel.ChartType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-create-several-charts.yaml + await Excel.run(async (context) => { let sheet = context.workbook.worksheets.getItem("Sample"); let salesTable = sheet.tables.getItem("SalesTable"); @@ -1606,11 +2146,32 @@ await context.sync(); }); -'Excel.ClearApplyTo:enum': +Excel.CheckboxCellControl:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml + + + // Add checkboxes to the table. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Get the second column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Change the boolean values to checkboxes. + range.control = { + type: Excel.CellControlType.checkbox + }; + await context.sync(); + }); +Excel.ClearApplyTo:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Orders"); @@ -1624,7 +2185,7 @@ let cellRange = productsRange.getCell(i, 0); // Clear the hyperlink. - // This eliminates the hyperlink but does not update text format. + // This removes the hyperlink but does not update text format. cellRange.clear(Excel.ClearApplyTo.hyperlinks); // Update text format. @@ -1634,19 +2195,21 @@ await context.sync(); }); -'Excel.CloseBehavior:enum': +Excel.CloseBehavior:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-save-and-close.yaml + await Excel.run(async (context) => { context.workbook.close(Excel.CloseBehavior.skipSave); }); -'Excel.ColorScaleConditionalFormat#criteria:member': +Excel.ColorScaleConditionalFormat#criteria:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B2:M5"); @@ -1661,10 +2224,11 @@ await context.sync(); }); -'Excel.Comment#content:member': +Excel.Comment#content:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-basics.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-basics.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Comments"); @@ -1672,19 +2236,21 @@ comment.content = "PLEASE add headers here."; await context.sync(); }); -'Excel.Comment#delete:member(1)': +Excel.Comment#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-basics.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-basics.yaml + await Excel.run(async (context) => { context.workbook.comments.getItemByCell("Comments!A2").delete(); await context.sync(); }); -'Excel.Comment#load:member(2)': +Excel.Comment#load:member(2): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-basics.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-basics.yaml + await Excel.run(async (context) => { const comment = context.workbook.comments.getItemByCell("Comments!A2"); @@ -1694,20 +2260,22 @@ console.log(`${comment.creationDate.toDateString()}: ${comment.authorName} (${comment.authorEmail})`); await context.sync(); }); -'Excel.Comment#resolved:member': +Excel.Comment#resolved:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-resolution.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-resolution.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Comments"); sheet.comments.getItemAt(0).resolved = true; await context.sync(); }); -'Excel.CommentCollection#add:member(1)': +Excel.CommentCollection#add:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-basics.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-basics.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Comments"); @@ -1716,11 +2284,12 @@ sheet.comments.add("A2", "TODO: add data."); await context.sync(); }); -'Excel.CommentCollection#onAdded:member': +Excel.CommentCollection#onAdded:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-comment-event-handler.yaml + await Excel.run(async (context) => { const comments = context.workbook.worksheets.getActiveWorksheet().comments; @@ -1737,6 +2306,7 @@ // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-comment-event-handler.yaml + async function commentAdded(event: Excel.CommentAddedEventArgs) { // Retrieve the added comment using the comment ID. // Note: This function assumes only a single comment is added at a time. @@ -1756,11 +2326,12 @@ console.log(` Creation date:${addedComment.creationDate}`); }); } -'Excel.CommentCollection#onChanged:member': +Excel.CommentCollection#onChanged:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-comment-event-handler.yaml + await Excel.run(async (context) => { const comments = context.workbook.worksheets.getActiveWorksheet().comments; @@ -1777,6 +2348,7 @@ // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-comment-event-handler.yaml + async function commentChanged(event: Excel.CommentChangedEventArgs) { // Retrieve the changed comment using the comment ID. // Note: This function assumes only a single comment is changed at a time. @@ -1796,11 +2368,12 @@ console.log(` Creation date: ${changedComment.creationDate}`); }); } -'Excel.CommentCollection#onDeleted:member': +Excel.CommentCollection#onDeleted:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-comment-event-handler.yaml + await Excel.run(async (context) => { const comments = context.workbook.worksheets.getActiveWorksheet().comments; @@ -1817,6 +2390,7 @@ // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-comment-event-handler.yaml + async function commentDeleted(event: Excel.CommentDeletedEventArgs) { // Print out the deleted comment's ID. // Note: This function assumes only a single comment is deleted at a time. @@ -1825,10 +2399,11 @@ console.log(` ID: ${event.commentDetails[0].commentId}`); }); } -'Excel.CommentReply#content:member': +Excel.CommentReply#content:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-replies.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-replies.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Comments"); @@ -1842,10 +2417,11 @@ reply.content += " Please!"; await context.sync(); }); -'Excel.CommentReply#delete:member(1)': +Excel.CommentReply#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-replies.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-replies.yaml + await Excel.run(async (context) => { // Remove the first comment reply from this worksheet's first comment. @@ -1854,10 +2430,11 @@ comment.replies.getItemAt(0).delete(); await context.sync(); }); -'Excel.CommentReplyCollection#add:member(1)': +Excel.CommentReplyCollection#add:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-replies.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-replies.yaml + await Excel.run(async (context) => { // Adds a reply to the first comment in this worksheet. @@ -1866,10 +2443,11 @@ comment.replies.add("Add content to this worksheet."); await context.sync(); }); -'Excel.CommentRichContent#mentions:member': +Excel.CommentRichContent#mentions:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-mentions.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-mentions.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Comments"); @@ -1890,11 +2468,12 @@ sheet.comments.add("A1", commentBody, Excel.ContentType.mention); await context.sync(); }); -'Excel.ConditionalCellValueRule#formula1:member': +Excel.ConditionalCellValueRule#formula1:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B21:E23"); @@ -1905,11 +2484,12 @@ await context.sync(); }); -'Excel.ConditionalCellValueRule#operator:member': +Excel.ConditionalCellValueRule#operator:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B21:E23"); @@ -1920,11 +2500,12 @@ await context.sync(); }); -'Excel.ConditionalDataBarDirection:enum': +Excel.ConditionalDataBarDirection:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -1934,11 +2515,12 @@ await context.sync(); }); -'Excel.ConditionalFormat#cellValue:member': +Excel.ConditionalFormat#cellValue:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B21:E23"); @@ -1949,11 +2531,12 @@ await context.sync(); }); -'Excel.ConditionalFormat#colorScale:member': +Excel.ConditionalFormat#colorScale:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B2:M5"); @@ -1968,11 +2551,12 @@ await context.sync(); }); -'Excel.ConditionalFormat#custom:member': +Excel.ConditionalFormat#custom:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -1982,11 +2566,12 @@ await context.sync(); }); -'Excel.ConditionalFormat#dataBar:member': +Excel.ConditionalFormat#dataBar:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -1996,11 +2581,12 @@ await context.sync(); }); -'Excel.ConditionalFormat#getRange:member(1)': +Excel.ConditionalFormat#getRange:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const worksheetRange = sheet.getRange(); @@ -2026,11 +2612,12 @@ console.log("No conditional formats applied."); } }); -'Excel.ConditionalFormat#iconSet:member': +Excel.ConditionalFormat#iconSet:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -2069,11 +2656,12 @@ await context.sync(); }); -'Excel.ConditionalFormat#preset:member': +Excel.ConditionalFormat#preset:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B2:M5"); @@ -2084,11 +2672,12 @@ await context.sync(); }); -'Excel.ConditionalFormat#textComparison:member': +Excel.ConditionalFormat#textComparison:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B16:D18"); @@ -2099,11 +2688,12 @@ await context.sync(); }); -'Excel.ConditionalFormat#type:member': +Excel.ConditionalFormat#type:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const worksheetRange = sheet.getRange(); @@ -2129,11 +2719,12 @@ console.log("No conditional formats applied."); } }); -'Excel.ConditionalFormatCollection#add:member(1)': +Excel.ConditionalFormatCollection#add:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B2:M5"); @@ -2148,11 +2739,12 @@ await context.sync(); }); -'Excel.ConditionalFormatCollection#clearAll:member(1)': +Excel.ConditionalFormatCollection#clearAll:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange(); @@ -2160,13 +2752,16 @@ await context.sync(); - $(".conditional-formats").hide(); + document.querySelectorAll(".conditional-formats").forEach(element => { + element.style.display = "none"; + }); }); -'Excel.ConditionalFormatCollection#getItemAt:member(1)': +Excel.ConditionalFormatCollection#getItemAt:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const worksheetRange = sheet.getRange(); @@ -2192,11 +2787,12 @@ console.log("No conditional formats applied."); } }); -'Excel.ConditionalFormatColorCriterionType:enum': +Excel.ConditionalFormatColorCriterionType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B2:M5"); @@ -2211,11 +2807,12 @@ await context.sync(); }); -'Excel.ConditionalFormatIconRuleType:enum': +Excel.ConditionalFormatIconRuleType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -2254,11 +2851,12 @@ await context.sync(); }); -'Excel.ConditionalFormatPresetCriterion:enum': +Excel.ConditionalFormatPresetCriterion:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-advanced.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); queueCommandsToClearAllConditionalFormats(sheet); @@ -2292,11 +2890,12 @@ await context.sync(); }); -'Excel.ConditionalFormatRule#formula:member': +Excel.ConditionalFormatRule#formula:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -2306,11 +2905,12 @@ await context.sync(); }); -'Excel.ConditionalFormatType:enum': +Excel.ConditionalFormatType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-advanced.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); queueCommandsToClearAllConditionalFormats(sheet); @@ -2344,11 +2944,12 @@ await context.sync(); }); -'Excel.ConditionalIconCriterion#formula:member': +Excel.ConditionalIconCriterion#formula:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -2387,11 +2988,12 @@ await context.sync(); }); -'Excel.ConditionalIconCriterion#operator:member': +Excel.ConditionalIconCriterion#operator:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -2430,11 +3032,12 @@ await context.sync(); }); -'Excel.ConditionalIconCriterion#type:member': +Excel.ConditionalIconCriterion#type:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -2473,11 +3076,12 @@ await context.sync(); }); -'Excel.ConditionalIconCriterionOperator:enum': +Excel.ConditionalIconCriterionOperator:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -2516,11 +3120,12 @@ await context.sync(); }); -'Excel.ConditionalPresetCriteriaRule#criterion:member': +Excel.ConditionalPresetCriteriaRule#criterion:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B2:M5"); @@ -2531,11 +3136,12 @@ await context.sync(); }); -'Excel.ConditionalTextComparisonRule#text:member': +Excel.ConditionalTextComparisonRule#text:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B16:D18"); @@ -2546,11 +3152,12 @@ await context.sync(); }); -'Excel.ConditionalTextOperator:enum': +Excel.ConditionalTextOperator:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B16:D18"); @@ -2561,21 +3168,23 @@ await context.sync(); }); -'Excel.ConnectorType:enum': +Excel.ConnectorType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml + await Excel.run(async (context) => { const shapes = context.workbook.worksheets.getItem("Shapes").shapes; const line = shapes.addLine(200, 50, 300, 150, Excel.ConnectorType.straight); line.name = "StraightLine"; await context.sync(); }); -'Excel.ContentType:enum': +Excel.ContentType:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-mentions.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-mentions.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Comments"); @@ -2596,11 +3205,12 @@ sheet.comments.add("A1", commentBody, Excel.ContentType.mention); await context.sync(); }); -'Excel.CultureInfo#datetimeFormat:member': +Excel.CultureInfo#datetimeFormat:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/culture-info-date-time.yaml + await Excel.run(async (context) => { context.application.cultureInfo.datetimeFormat.load([ "longDatePattern", @@ -2636,11 +3246,12 @@ await context.sync(); }); -'Excel.CustomConditionalFormat#format:member': +Excel.CustomConditionalFormat#format:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -2650,15 +3261,16 @@ await context.sync(); }); -'Excel.CustomPropertyCollection#add:member(1)': +Excel.CustomPropertyCollection#add:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/26-document/custom-properties.yaml + await Excel.run(async (context) => { // Get the key/value pair from the task pane. - const userKey = $("#key").text(); - const userValue = $("#value").text(); + const userKey = document.getElementById("key").textContent; + const userValue = document.getElementById("value").textContent; // Add the custom property. const customDocProperties = context.workbook.properties.custom; @@ -2668,11 +3280,12 @@ console.log(`Successfully set custom document property ${userKey}:${userValue}.`); }); -'Excel.CustomXmlPart#delete:member(1)': +Excel.CustomXmlPart#delete:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/create-set-get-and-delete-custom-xml-parts.yaml + await Excel.run(async (context) => { const settings = context.workbook.settings; const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); @@ -2687,24 +3300,25 @@ await context.sync(); if (customXmlPart.isNullObject) { - $("#display-xml").text(`The XML part with the id ${xmlPartIDSetting.value} has been deleted.`); + document.getElementById("display-xml").textContent = `The XML part with the id ${xmlPartIDSetting.value} has been deleted.`; // Delete the unneeded setting too. xmlPartIDSetting.delete(); } else { const readableXml = addLineBreaksToXML(xmlBlob.value); const strangeMessage = `This is strange. The XML part with the id ${xmlPartIDSetting.value} has not been deleted:\n${readableXml}` - $("#display-xml").text(strangeMessage); + document.getElementById("display-xml").textContent = strangeMessage; } await context.sync(); } }); -'Excel.CustomXmlPart#getXml:member(1)': +Excel.CustomXmlPart#getXml:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/create-set-get-and-delete-custom-xml-parts.yaml + await Excel.run(async (context) => { // You must have the xmlns attribute to populate the // CustomXml.namespaceUri property. @@ -2716,7 +3330,7 @@ await context.sync(); const readableXml = addLineBreaksToXML(xmlBlob.value); - $("#display-xml").text(readableXml); + document.getElementById("display-xml").textContent = readableXml; // Store the XML part's ID in a setting. const settings = context.workbook.settings; @@ -2724,11 +3338,12 @@ await context.sync(); }); -'Excel.CustomXmlPart#id:member': +Excel.CustomXmlPart#id:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/create-set-get-and-delete-custom-xml-parts.yaml + await Excel.run(async (context) => { // You must have the xmlns attribute to populate the // CustomXml.namespaceUri property. @@ -2740,7 +3355,7 @@ await context.sync(); const readableXml = addLineBreaksToXML(xmlBlob.value); - $("#display-xml").text(readableXml); + document.getElementById("display-xml").textContent = readableXml; // Store the XML part's ID in a setting. const settings = context.workbook.settings; @@ -2748,11 +3363,12 @@ await context.sync(); }); -'Excel.CustomXmlPart#setXml:member(1)': +Excel.CustomXmlPart#setXml:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/create-set-get-and-delete-custom-xml-parts.yaml + await Excel.run(async (context) => { const settings = context.workbook.settings; const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); @@ -2768,15 +3384,16 @@ await context.sync(); const readableXml = addLineBreaksToXML(xmlBlob.value); - $("#display-xml").text(readableXml); + document.getElementById("display-xml").textContent = readableXml; await context.sync(); } }); -'Excel.CustomXmlPartCollection#add:member(1)': +Excel.CustomXmlPartCollection#add:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/create-set-get-and-delete-custom-xml-parts.yaml + await Excel.run(async (context) => { // You must have the xmlns attribute to populate the // CustomXml.namespaceUri property. @@ -2788,7 +3405,7 @@ await context.sync(); const readableXml = addLineBreaksToXML(xmlBlob.value); - $("#display-xml").text(readableXml); + document.getElementById("display-xml").textContent = readableXml; // Store the XML part's ID in a setting. const settings = context.workbook.settings; @@ -2796,43 +3413,12 @@ await context.sync(); }); -'Excel.CustomXmlPartCollection#getByNamespace:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/test-xml-for-unique-namespace.yaml - - await Excel.run(async (context) => { - $("#display-xml").text(""); - const contosoNamespace = "http://schemas.contoso.com/review/1.0"; - const customXmlParts = context.workbook.customXmlParts; - const filteredXmlParts = customXmlParts.getByNamespace(contosoNamespace); - const numberOfPartsInNamespace = filteredXmlParts.getCount(); - - await context.sync(); - - if (numberOfPartsInNamespace.value == 1) { - const onlyXmlPartInNamespace = filteredXmlParts.getOnlyItem(); - const xmlBlob = onlyXmlPartInNamespace.getXml(); - - await context.sync(); - - // Make it a bit more readable. - const readableXml = xmlBlob.value.replace(/>\n<"); - - $("#display-xml").text(`The only XML part in the namespace ${contosoNamespace} is: - ${readableXml}`); - - } else { - console.log(`There are ${numberOfPartsInNamespace.value} XML parts with namespace ${contosoNamespace}. There should be exactly 1.`); - } - - await context.sync(); - }); -'Excel.CustomXmlPartCollection#getItem:member(1)': +Excel.CustomXmlPartCollection#getItem:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/create-set-get-and-delete-custom-xml-parts.yaml + await Excel.run(async (context) => { const settings = context.workbook.settings; const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); @@ -2848,17 +3434,18 @@ await context.sync(); const readableXml = addLineBreaksToXML(xmlBlob.value); - $("#display-xml").text(readableXml); + document.getElementById("display-xml").textContent = readableXml; await context.sync(); } }); -'Excel.CustomXmlPartScopedCollection#getCount:member(1)': +Excel.CustomXmlPartCollection#getByNamespace:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/test-xml-for-unique-namespace.yaml + await Excel.run(async (context) => { - $("#display-xml").text(""); + document.getElementById("display-xml").textContent = ""; const contosoNamespace = "http://schemas.contoso.com/review/1.0"; const customXmlParts = context.workbook.customXmlParts; const filteredXmlParts = customXmlParts.getByNamespace(contosoNamespace); @@ -2875,8 +3462,8 @@ // Make it a bit more readable. const readableXml = xmlBlob.value.replace(/>\n<"); - $("#display-xml").text(`The only XML part in the namespace ${contosoNamespace} is: - ${readableXml}`); + document.getElementById("display-xml").textContent = `The only XML part in the namespace ${contosoNamespace} is: + ${readableXml}`; } else { console.log(`There are ${numberOfPartsInNamespace.value} XML parts with namespace ${contosoNamespace}. There should be exactly 1.`); @@ -2884,11 +3471,12 @@ await context.sync(); }); -'Excel.CustomXmlPartScopedCollection#getItemOrNullObject:member(1)': +Excel.CustomXmlPartScopedCollection#getItemOrNullObject:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/create-set-get-and-delete-custom-xml-parts.yaml + await Excel.run(async (context) => { const settings = context.workbook.settings; const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); @@ -2903,26 +3491,27 @@ await context.sync(); if (customXmlPart.isNullObject) { - $("#display-xml").text(`The XML part with the id ${xmlPartIDSetting.value} has been deleted.`); + document.getElementById("display-xml").textContent = `The XML part with the id ${xmlPartIDSetting.value} has been deleted.`; // Delete the unneeded setting too. xmlPartIDSetting.delete(); } else { const readableXml = addLineBreaksToXML(xmlBlob.value); const strangeMessage = `This is strange. The XML part with the id ${xmlPartIDSetting.value} has not been deleted:\n${readableXml}` - $("#display-xml").text(strangeMessage); + document.getElementById("display-xml").textContent = strangeMessage; } await context.sync(); } }); -'Excel.CustomXmlPartScopedCollection#getOnlyItem:member(1)': +Excel.CustomXmlPartScopedCollection#getCount:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/test-xml-for-unique-namespace.yaml + await Excel.run(async (context) => { - $("#display-xml").text(""); + document.getElementById("display-xml").textContent = ""; const contosoNamespace = "http://schemas.contoso.com/review/1.0"; const customXmlParts = context.workbook.customXmlParts; const filteredXmlParts = customXmlParts.getByNamespace(contosoNamespace); @@ -2939,8 +3528,8 @@ // Make it a bit more readable. const readableXml = xmlBlob.value.replace(/>\n<"); - $("#display-xml").text(`The only XML part in the namespace ${contosoNamespace} is: - ${readableXml}`); + document.getElementById("display-xml").textContent = `The only XML part in the namespace ${contosoNamespace} is: + ${readableXml}`; } else { console.log(`There are ${numberOfPartsInNamespace.value} XML parts with namespace ${contosoNamespace}. There should be exactly 1.`); @@ -2948,39 +3537,60 @@ await context.sync(); }); -'Excel.DataBarConditionalFormat#barDirection:member': +Excel.CustomXmlPartScopedCollection#getOnlyItem:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/test-xml-for-unique-namespace.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const range = sheet.getRange("B8:E13"); - const conditionalFormat = range.conditionalFormats - .add(Excel.ConditionalFormatType.dataBar); - conditionalFormat.dataBar.barDirection = Excel.ConditionalDataBarDirection.leftToRight; + document.getElementById("display-xml").textContent = ""; + const contosoNamespace = "http://schemas.contoso.com/review/1.0"; + const customXmlParts = context.workbook.customXmlParts; + const filteredXmlParts = customXmlParts.getByNamespace(contosoNamespace); + const numberOfPartsInNamespace = filteredXmlParts.getCount(); + + await context.sync(); + + if (numberOfPartsInNamespace.value == 1) { + const onlyXmlPartInNamespace = filteredXmlParts.getOnlyItem(); + const xmlBlob = onlyXmlPartInNamespace.getXml(); + + await context.sync(); + + // Make it a bit more readable. + const readableXml = xmlBlob.value.replace(/>\n<"); + + document.getElementById("display-xml").textContent = `The only XML part in the namespace ${contosoNamespace} is: + ${readableXml}`; + + } else { + console.log(`There are ${numberOfPartsInNamespace.value} XML parts with namespace ${contosoNamespace}. There should be exactly 1.`); + } await context.sync(); }); -'Excel.DataPivotHierarchy#name:member': +Excel.DataBarConditionalFormat#barDirection:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-create-and-modify.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { - const dataHierarchies = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales").dataHierarchies - dataHierarchies.load("no-properties-needed"); - await context.sync(); + const sheet = context.workbook.worksheets.getItem("Sample"); + const range = sheet.getRange("B8:E13"); + const conditionalFormat = range.conditionalFormats + .add(Excel.ConditionalFormatType.dataBar); + conditionalFormat.dataBar.barDirection = Excel.ConditionalDataBarDirection.leftToRight; - dataHierarchies.items[0].name = "Farm Sales"; - dataHierarchies.items[1].name = "Wholesale"; await context.sync(); }); -'Excel.DataPivotHierarchy#showAs:member': +Excel.DataPivotHierarchy#showAs:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-calculations.yaml + await Excel.run(async (context) => { const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); const farmDataHierarchy: Excel.DataPivotHierarchy = pivotTable.dataHierarchies.getItem("Sum of Crates Sold at Farm"); @@ -3002,28 +3612,81 @@ wholesaleDataHierarchy.showAs = wholesaleShowAs; await context.sync(); }); -'Excel.DataValidation#errorAlert:member': +Excel.DataPivotHierarchy#name:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-create-and-modify.yaml + + + await Excel.run(async (context) => { + const dataHierarchies = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales").dataHierarchies + dataHierarchies.load("no-properties-needed"); + await context.sync(); + + dataHierarchies.items[0].name = "Farm Sales"; + dataHierarchies.items[1].name = "Wholesale"; + await context.sync(); + }); +Excel.DataValidationErrorAlert:interface: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/22-data-validation/data-validation.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Decision"); - const commentsRange = - sheet.tables.getItem("NameOptionsTable").columns.getItem("Comments").getDataBodyRange(); + const rankingRange = sheet.tables.getItem("NameOptionsTable").columns.getItem("Ranking").getDataBodyRange(); // When you are developing, it is a good practice to // clear the dataValidation object with each run of your code. - commentsRange.dataValidation.clear(); + rankingRange.dataValidation.clear(); - // If the value of A2 is contained in the value of C2, then - // SEARCH(A2,C2) returns the number where it begins. Otherwise, - // it does not return a number. - let redundantStringRule = { - custom: { - formula: "=NOT(ISNUMBER(SEARCH(A2,C2)))" - } - }; + let greaterThanZeroRule = { + wholeNumber: { + formula1: 0, + operator: Excel.DataValidationOperator.greaterThan + } + }; + rankingRange.dataValidation.rule = greaterThanZeroRule; + + rankingRange.dataValidation.prompt = { + message: "Please enter a positive number.", + showPrompt: true, + title: "Positive numbers only." + }; + + rankingRange.dataValidation.errorAlert = { + message: "Sorry, only positive numbers are allowed", + showAlert: true, + style: "Stop", + title: "Negative Number Entered" + }; + + await context.sync(); + }); +Excel.DataValidation#errorAlert:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/22-data-validation/data-validation.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Decision"); + const commentsRange = + sheet.tables.getItem("NameOptionsTable").columns.getItem("Comments").getDataBodyRange(); + + // When you are developing, it is a good practice to + // clear the dataValidation object with each run of your code. + commentsRange.dataValidation.clear(); + + // If the value of A2 is contained in the value of C2, then + // SEARCH(A2,C2) returns the number where it begins. Otherwise, + // it does not return a number. + let redundantStringRule = { + custom: { + formula: "=NOT(ISNUMBER(SEARCH(A2,C2)))" + } + }; commentsRange.dataValidation.rule = redundantStringRule; commentsRange.dataValidation.errorAlert = { message: "It is redundant to include the baby name in the comment.", @@ -3034,11 +3697,12 @@ await context.sync(); }); -'Excel.DataValidation#prompt:member': +Excel.DataValidation#prompt:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/22-data-validation/data-validation.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Decision"); const rankingRange = sheet.tables.getItem("NameOptionsTable").columns.getItem("Ranking").getDataBodyRange(); @@ -3070,11 +3734,12 @@ await context.sync(); }); -'Excel.DataValidation#rule:member': +Excel.DataValidation#rule:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/22-data-validation/data-validation.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Decision"); const nameRange = @@ -3096,11 +3761,12 @@ await context.sync(); }); -'Excel.DataValidationOperator:enum': +Excel.DataValidationOperator:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/22-data-validation/data-validation.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Decision"); const rankingRange = sheet.tables.getItem("NameOptionsTable").columns.getItem("Ranking").getDataBodyRange(); @@ -3132,11 +3798,12 @@ await context.sync(); }); -'Excel.DataValidationRule#list:member': +Excel.DataValidationRule#list:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/22-data-validation/data-validation.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Decision"); const nameRange = @@ -3158,11 +3825,12 @@ await context.sync(); }); -'Excel.DataValidationRule#wholeNumber:member': +Excel.DataValidationRule#wholeNumber:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/22-data-validation/data-validation.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Decision"); const rankingRange = sheet.tables.getItem("NameOptionsTable").columns.getItem("Ranking").getDataBodyRange(); @@ -3194,11 +3862,12 @@ await context.sync(); }); -'Excel.DateFilterCondition:enum': +Excel.DateFilterCondition:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotfilters.yaml + await Excel.run(async (context) => { // Add a date-based PivotFilter. @@ -3226,11 +3895,12 @@ await context.sync(); }); -'Excel.DeleteShiftDirection:enum': +Excel.DeleteShiftDirection:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet.yaml + // This function deletes data from a range and sets the delete shift direction to "up". @@ -3239,11 +3909,12 @@ const range = sheet.getRange("A5:F5"); range.delete(Excel.DeleteShiftDirection.up); }); -'Excel.DocumentProperties#custom:member': +Excel.DocumentProperties#custom:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/26-document/custom-properties.yaml + await Excel.run(async (context) => { // Load the keys and values of all custom properties. const customDocProperties = context.workbook.properties.custom; @@ -3256,11 +3927,67 @@ console.log(`${property.key}:${property.value}`); }); }); -'Excel.DynamicFilterCriteria:enum': +Excel.DoubleCellValue#numberFormat:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-formatted-number.yaml + + + // This function creates a double data type, + + // and sets the format of this data type as a currency. + + await Excel.run(async (context) => { + // Get the Sample worksheet and a range on that sheet. + const sheet = context.workbook.worksheets.getItemOrNullObject("Sample"); + const currencyRange = sheet.getRange("A2"); + + // Write a number formatted as currency to cell A2. + currencyRange.valuesAsJson = [ + [ + { + type: Excel.CellValueType.double, + basicValue: 12.34, + numberFormat: "$* #,##0.00" + } + ] + ]; + + await context.sync(); + }); +Excel.DoubleCellValue#type:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-formatted-number.yaml + + + // This function creates a double data type, + + // and sets the format of this data type as a date. + + await Excel.run(async (context) => { + // Get the Sample worksheet and a range on that sheet. + const sheet = context.workbook.worksheets.getItemOrNullObject("Sample"); + const dateRange = sheet.getRange("A1"); + + // Write a number formatted as a date to cell A1. + dateRange.valuesAsJson = [ + [ + { + type: Excel.CellValueType.double, + basicValue: 32889.0, + numberFormat: "m/d/yyyy" + } + ] + ]; + await context.sync(); + }); +Excel.DynamicFilterCriteria:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/46-table/filter-data.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); @@ -3280,11 +4007,70 @@ await context.sync(); }); -'Excel.EntityCompactLayoutIcons:enum': +Excel.EntityCardLayout:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-entity-attribution.yaml + + + function makeProductEntity(productID: number, productName: string, product?: + any) { + const entity: Excel.EntityCellValue = { + type: Excel.CellValueType.entity, + text: productName, + properties: { /* Excel.EntityPropertyType */ + "Product ID": { + type: Excel.CellValueType.string, + basicValue: productID.toString() || "" + }, + "Product Name": { + type: Excel.CellValueType.string, + basicValue: productName || "" + }, + "Quantity Per Unit": { + type: Excel.CellValueType.string, + basicValue: product.quantityPerUnit || "" + }, + // Add Unit Price as a formatted number. + "Unit Price": { + type: Excel.CellValueType.formattedNumber, + basicValue: product.unitPrice, + numberFormat: "$* #,##0.00" + } + }, + layouts: { /* Excel.EntityViewLayouts */ + card: { /* Excel.EntityCardLayout */ + title: { property: "Product Name" }, + sections: [ /* Excel.CardLayoutSection */ + { + layout: "List", + properties: ["Product ID"] + }, + { + layout: "List", + title: "Quantity and price", + collapsible: true, + collapsed: false, + properties: ["Quantity Per Unit", "Unit Price"] + } + ] + } + }, + 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 clicked. + } + }; + + return entity; + } +Excel.EntityCompactLayoutIcons:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-entity-icons.yaml + function createEntitiesWithIcons(icons): Excel.EntityCellValue[][] { /* This method creates an entity data type for each * icon in the `EntityCompactLayoutIcons` enum, @@ -3308,11 +4094,128 @@ }); return entities; } -'Excel.ErrorCellValue:type': +Excel.EntityPropertyType:type: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-entity-attribution.yaml + + + function makeProductEntity(productID: number, productName: string, product?: + any) { + const entity: Excel.EntityCellValue = { + type: Excel.CellValueType.entity, + text: productName, + properties: { /* Excel.EntityPropertyType */ + "Product ID": { + type: Excel.CellValueType.string, + basicValue: productID.toString() || "" + }, + "Product Name": { + type: Excel.CellValueType.string, + basicValue: productName || "" + }, + "Quantity Per Unit": { + type: Excel.CellValueType.string, + basicValue: product.quantityPerUnit || "" + }, + // Add Unit Price as a formatted number. + "Unit Price": { + type: Excel.CellValueType.formattedNumber, + basicValue: product.unitPrice, + numberFormat: "$* #,##0.00" + } + }, + layouts: { /* Excel.EntityViewLayouts */ + card: { /* Excel.EntityCardLayout */ + title: { property: "Product Name" }, + sections: [ /* Excel.CardLayoutSection */ + { + layout: "List", + properties: ["Product ID"] + }, + { + layout: "List", + title: "Quantity and price", + collapsible: true, + collapsed: false, + properties: ["Quantity Per Unit", "Unit Price"] + } + ] + } + }, + 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 clicked. + } + }; + + return entity; + } +Excel.EntityViewLayouts:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-entity-attribution.yaml + + + function makeProductEntity(productID: number, productName: string, product?: + any) { + const entity: Excel.EntityCellValue = { + type: Excel.CellValueType.entity, + text: productName, + properties: { /* Excel.EntityPropertyType */ + "Product ID": { + type: Excel.CellValueType.string, + basicValue: productID.toString() || "" + }, + "Product Name": { + type: Excel.CellValueType.string, + basicValue: productName || "" + }, + "Quantity Per Unit": { + type: Excel.CellValueType.string, + basicValue: product.quantityPerUnit || "" + }, + // Add Unit Price as a formatted number. + "Unit Price": { + type: Excel.CellValueType.formattedNumber, + basicValue: product.unitPrice, + numberFormat: "$* #,##0.00" + } + }, + layouts: { /* Excel.EntityViewLayouts */ + card: { /* Excel.EntityCardLayout */ + title: { property: "Product Name" }, + sections: [ /* Excel.CardLayoutSection */ + { + layout: "List", + properties: ["Product ID"] + }, + { + layout: "List", + title: "Quantity and price", + collapsible: true, + collapsed: false, + properties: ["Quantity Per Unit", "Unit Price"] + } + ] + } + }, + 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 clicked. + } + }; + + return entity; + } +Excel.ErrorCellValue:type: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-error-values.yaml + // This function sets the value of cell A1 to a #BUSY! error using data types. @@ -3321,7 +4224,7 @@ const sheet = context.workbook.worksheets.getItemOrNullObject("Sample"); const range = sheet.getRange("A1"); - // Get the error data type and set its type to `busy`. + // Get the error data type and set its type to `busy`. const error: Excel.ErrorCellValue = { type: Excel.CellValueType.error, errorType: Excel.ErrorCellValueType.busy @@ -3331,11 +4234,12 @@ range.valuesAsJson = [[error]]; await context.sync(); }); -'Excel.ErrorCellValueType:enum': +Excel.ErrorCellValueType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-error-values.yaml + // This function sets the value of cell A1 to a #BUSY! error using data types. @@ -3344,7 +4248,7 @@ const sheet = context.workbook.worksheets.getItemOrNullObject("Sample"); const range = sheet.getRange("A1"); - // Get the error data type and set its type to `busy`. + // Get the error data type and set its type to `busy`. const error: Excel.ErrorCellValue = { type: Excel.CellValueType.error, errorType: Excel.ErrorCellValueType.busy @@ -3354,11 +4258,12 @@ range.valuesAsJson = [[error]]; await context.sync(); }); -'Excel.FillPattern:enum': +Excel.FillPattern:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -3430,11 +4335,12 @@ sheet.getUsedRange().format.autofitColumns(); await context.sync(); }); -'Excel.FilterCriteria#filterOn:member': +Excel.FilterCriteria#filterOn:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-auto-filter.yaml + // This function adds a percentage AutoFilter to the active worksheet // and applies the filter to a column of the used range. @@ -3452,11 +4358,12 @@ await context.sync(); }); -'Excel.FilterDatetimeSpecificity:enum': +Excel.FilterDatetimeSpecificity:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotfilters.yaml + await Excel.run(async (context) => { // Add a date-based PivotFilter. @@ -3484,64 +4391,69 @@ await context.sync(); }); -'Excel.FormattedNumberCellValue#numberFormat:member': +Excel.Functions:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-formatted-number.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-built-in-functions.yaml - // This function creates a formatted number data type, - - // and sets the format of this data type as a currency. await Excel.run(async (context) => { - // Get the Sample worksheet and a range on that sheet. - const sheet = context.workbook.worksheets.getItemOrNullObject("Sample"); - const currencyRange = sheet.getRange("A2"); + // This function uses VLOOKUP to find data in the "Wrench" row on the worksheet. + let range = context.workbook.worksheets.getItem("Sample").getRange("A1:D4"); - // Write a number formatted as currency to cell A2. - currencyRange.valuesAsJson = [ - [ - { - type: Excel.CellValueType.formattedNumber, - basicValue: 12.34, - numberFormat: "$* #,##0.00" - } - ] - ]; + // Get the value in the second column in the "Wrench" row. + let unitSoldInNov = context.workbook.functions.vlookup("Wrench", range, 2, false); + unitSoldInNov.load("value"); await context.sync(); + console.log(" Number of wrenches sold in November = " + unitSoldInNov.value); }); -'Excel.FormattedNumberCellValue#type:member': +Excel.Functions#vlookup:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-formatted-number.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-built-in-functions.yaml - // This function creates a formatted number data type, - // and sets the format of this data type as a date. + await Excel.run(async (context) => { + // This function uses VLOOKUP to find data in the "Wrench" row on the worksheet. + let range = context.workbook.worksheets.getItem("Sample").getRange("A1:D4"); + + // Get the value in the second column in the "Wrench" row. + let unitSoldInNov = context.workbook.functions.vlookup("Wrench", range, 2, false); + unitSoldInNov.load("value"); + + await context.sync(); + console.log(" Number of wrenches sold in November = " + unitSoldInNov.value); + }); +Excel.Functions#sum:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-built-in-functions.yaml + await Excel.run(async (context) => { - // Get the Sample worksheet and a range on that sheet. - const sheet = context.workbook.worksheets.getItemOrNullObject("Sample"); - const dateRange = sheet.getRange("A1"); + // This function uses VLOOKUP to find data in the "Wrench" row + // on the worksheet, and then it uses SUM to combine the values. + let range = context.workbook.worksheets.getItem("Sample").getRange("A1:D4"); + + // Get the values in the second, third, and fourth columns in the "Wrench" row, + // and combine those values with SUM. + let sumOfTwoLookups = context.workbook.functions.sum( + context.workbook.functions.vlookup("Wrench", range, 2, false), + context.workbook.functions.vlookup("Wrench", range, 3, false), + context.workbook.functions.vlookup("Wrench", range, 4, false) + ); + sumOfTwoLookups.load("value"); - // Write a number formatted as a date to cell A1. - dateRange.valuesAsJson = [ - [ - { - type: Excel.CellValueType.formattedNumber, - basicValue: 32889.0, - numberFormat: "m/d/yyyy" - } - ] - ]; await context.sync(); + console.log(" Number of wrenches sold in November, December, and January = " + sumOfTwoLookups.value); }); -'Excel.GeometricShapeType:enum': +Excel.GeometricShapeType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-create-and-delete.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Shapes"); const shape = sheet.shapes.addGeometricShape(Excel.GeometricShapeType.hexagon); @@ -3551,11 +4463,12 @@ shape.width = 200; await context.sync(); }); -'Excel.GroupOption:enum': +Excel.GroupOption:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/outline.yaml + Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -3569,11 +4482,12 @@ sheet.getRange("7:8").group(Excel.GroupOption.byRows); await context.sync(); }); -'Excel.HorizontalAlignment:enum': +Excel.HorizontalAlignment:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-merged-ranges.yaml + await Excel.run(async (context) => { // Retrieve the worksheet and the table in that worksheet. const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -3588,11 +4502,12 @@ await context.sync(); }); -'Excel.IconSet:enum': +Excel.IconSet:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -3631,11 +4546,12 @@ await context.sync(); }); -'Excel.IconSetConditionalFormat#criteria:member': +Excel.IconSetConditionalFormat#criteria:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -3674,11 +4590,12 @@ await context.sync(); }); -'Excel.IconSetConditionalFormat#style:member': +Excel.IconSetConditionalFormat#style:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B8:E13"); @@ -3717,11 +4634,12 @@ await context.sync(); }); -'Excel.Image#format:member': +Excel.Image#format:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-images.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Shapes"); const image = sheet.shapes.getItem("Image").image; @@ -3731,11 +4649,12 @@ console.log("The image's format is: " + image.format); await context.sync(); }); -'Excel.InsertShiftDirection:enum': +Excel.InsertShiftDirection:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/insert-delete-clear-range.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B4:E4"); @@ -3744,11 +4663,12 @@ await context.sync(); }); -'Excel.KeyboardDirection:enum': +Excel.KeyboardDirection:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-get-range-edge.yaml + await Excel.run(async (context) => { // Get the selected range. const range = context.workbook.getSelectedRange(); @@ -3769,11 +4689,12 @@ await context.sync(); }); -'Excel.LabelFilterCondition:enum': +Excel.LabelFilterCondition:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotfilters.yaml + await Excel.run(async (context) => { // Add a PivotFilter to filter based on the strings of item labels. @@ -3795,11 +4716,12 @@ await context.sync(); }); -'Excel.Line#connectBeginShape:member(1)': +Excel.Line#connectBeginShape:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml + await Excel.run(async (context) => { const shapes = context.workbook.worksheets.getItem("Shapes").shapes; const line = shapes.getItem("StraightLine").line; @@ -3807,11 +4729,12 @@ line.connectEndShape(shapes.getItem("Right"), 0); await context.sync(); }); -'Excel.Line#connectEndShape:member(1)': +Excel.Line#connectEndShape:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml + await Excel.run(async (context) => { const shapes = context.workbook.worksheets.getItem("Shapes").shapes; const line = shapes.getItem("StraightLine").line; @@ -3819,11 +4742,12 @@ line.connectEndShape(shapes.getItem("Right"), 0); await context.sync(); }); -'Excel.Line#disconnectBeginShape:member(1)': +Excel.Line#disconnectBeginShape:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml + await Excel.run(async (context) => { const shapes = context.workbook.worksheets.getItem("Shapes").shapes; const line = shapes.getItem("StraightLine").line; @@ -3831,11 +4755,12 @@ line.disconnectEndShape(); await context.sync(); }); -'Excel.Line#disconnectEndShape:member(1)': +Excel.Line#disconnectEndShape:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml + await Excel.run(async (context) => { const shapes = context.workbook.worksheets.getItem("Shapes").shapes; const line = shapes.getItem("StraightLine").line; @@ -3843,11 +4768,32 @@ line.disconnectEndShape(); await context.sync(); }); -'Excel.NamedItem#delete:member(1)': +Excel.NamedItem:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/34-named-item/create-and-remove-named-item.yaml + + + await Excel.run(async (context) => { + // Log all the named items in the active worksheet. + const namedItems = context.workbook.worksheets.getActiveWorksheet().names.load(); + await context.sync(); + + console.log("This worksheet contains " + namedItems.items.length + " named items."); + + for (let i = 0; i < namedItems.items.length; i++) { + const namedItem : Excel.NamedItem = namedItems.items[i]; + console.log(JSON.stringify(namedItem)) + "\n"; + } + + await context.sync(); + }); +Excel.NamedItem#delete:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/34-named-item/create-and-remove-named-item.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const totalName = sheet.names.getItemOrNullObject("TotalAmount"); @@ -3865,11 +4811,12 @@ await context.sync(); }); -'Excel.NamedItem#formula:member': +Excel.NamedItem#formula:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/34-named-item/update-named-item.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); @@ -3889,11 +4836,12 @@ console.log(`Just updated the named item "${myNamedItem.name}" -- it's now located here: ${myNamedItem.formula}`); } }); -'Excel.NamedItemCollection#add:member(1)': +Excel.NamedItemCollection#add:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/34-named-item/create-and-remove-named-item.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const headerRange = sheet.getRange("A1:D1"); @@ -3903,33 +4851,186 @@ await context.sync(); }); -'Excel.NumberFormatInfo#numberDecimalSeparator:member': +Excel.Note:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/culture-info.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml - // This will convert a number like "14,37" to "14.37" - // (assuming the system decimal separator is "."). - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); + // This function changes the height and width of the first note. - const decimalSource = sheet.getRange("B2"); + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const note = sheet.notes.getItemAt(0); + note.height = 200; + note.width = 400; + await context.sync(); + }); +Excel.Note#content:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml - decimalSource.load("values"); - context.application.cultureInfo.numberFormat.load("numberDecimalSeparator"); + // This function changes the content in the first note. - await context.sync(); + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const note = sheet.notes.getItemAt(0); + note.content = "Changing the content of the first note."; + await context.sync(); + }); +Excel.Note#height:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml - const systemDecimalSeparator = - context.application.cultureInfo.numberFormat.numberDecimalSeparator; + // This function changes the height and width of the first note. - const oldDecimalString: string = decimalSource.values[0][0]; + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const note = sheet.notes.getItemAt(0); + note.height = 200; + note.width = 400; + await context.sync(); + }); +Excel.Note#visible:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml - // This assumes the input column is standardized to use "," as the decimal + // This function sets the note on cell A1 to visible. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const firstNote = sheet.notes.getItem("A1"); + + firstNote.load(); + await context.sync(); + + firstNote.visible = true; + }); +Excel.Note#width:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml + + + // This function changes the height and width of the first note. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const note = sheet.notes.getItemAt(0); + note.height = 200; + note.width = 400; + await context.sync(); + }); +Excel.Note#delete:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml + + + // This function deletes the note from cell A2. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const note = sheet.notes.getItem("A2"); + note.delete(); + + await context.sync(); + }); +Excel.NoteCollection:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml + + + // This function adds a note to the selected cell. + + await Excel.run(async (context) => { + 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(); + }); +Excel.NoteCollection#add:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml + + + // This function adds a note to the selected cell. + + await Excel.run(async (context) => { + 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(); + }); +Excel.NoteCollection#getItem:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml + + + // This function sets the note on cell A1 to visible. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const firstNote = sheet.notes.getItem("A1"); + + firstNote.load(); + await context.sync(); + + firstNote.visible = true; + }); +Excel.NoteCollection#getItemAt:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml + + + // This function changes the content in the first note. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Notes"); + const note = sheet.notes.getItemAt(0); + note.content = "Changing the content of the first note."; + await context.sync(); + }); +Excel.NumberFormatInfo#numberDecimalSeparator:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/culture-info.yaml + + + // This will convert a number like "14,37" to "14.37" + + // (assuming the system decimal separator is "."). + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + + const decimalSource = sheet.getRange("B2"); + + decimalSource.load("values"); + + context.application.cultureInfo.numberFormat.load("numberDecimalSeparator"); + + await context.sync(); + + + const systemDecimalSeparator = + context.application.cultureInfo.numberFormat.numberDecimalSeparator; + + const oldDecimalString: string = decimalSource.values[0][0]; + + + // This assumes the input column is standardized to use "," as the decimal separator. const newDecimalString = oldDecimalString.replace(",", @@ -3944,11 +5045,12 @@ await context.sync(); }); -'Excel.NumberFormatInfo#numberGroupSeparator:member': +Excel.NumberFormatInfo#numberGroupSeparator:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/culture-info.yaml + await Excel.run(async (context) => { // This will convert a number like "123-456-789" to "123,456,789" // (assuming the system thousands separator is ","). @@ -3969,93 +5071,102 @@ resultRange.format.autofitColumns(); await context.sync(); }); -'Excel.PageBreakCollection#add:member(1)': +Excel.PageBreakCollection#add:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-page-layout.yaml + await Excel.run(async (context) => { const farmSheet = context.workbook.worksheets.getItem("Print"); farmSheet.horizontalPageBreaks.add("A21:E21"); await context.sync(); }); -'Excel.PageLayout#centerHorizontally:member': +Excel.PageLayout#centerHorizontally:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-page-layout.yaml + await Excel.run(async (context) => { const farmSheet = context.workbook.worksheets.getItem("Print"); farmSheet.pageLayout.centerHorizontally = true; farmSheet.pageLayout.centerVertically = true; await context.sync(); }); -'Excel.PageLayout#centerVertically:member': +Excel.PageLayout#centerVertically:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-page-layout.yaml + await Excel.run(async (context) => { const farmSheet = context.workbook.worksheets.getItem("Print"); farmSheet.pageLayout.centerHorizontally = true; farmSheet.pageLayout.centerVertically = true; await context.sync(); }); -'Excel.PageLayout#orientation:member': +Excel.PageLayout#orientation:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-page-layout.yaml + await Excel.run(async (context) => { const farmSheet = context.workbook.worksheets.getItem("Print"); farmSheet.pageLayout.orientation = Excel.PageOrientation.landscape; await context.sync(); }); -'Excel.PageLayout#setPrintArea:member(1)': +Excel.PageLayout#setPrintArea:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-page-layout.yaml + await Excel.run(async (context) => { const farmSheet = context.workbook.worksheets.getItem("Print"); farmSheet.pageLayout.setPrintArea("A1:D41"); await context.sync(); }); -'Excel.PageLayout#setPrintTitleRows:member(1)': +Excel.PageLayout#setPrintTitleRows:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-page-layout.yaml + await Excel.run(async (context) => { const farmSheet = context.workbook.worksheets.getItem("Print"); farmSheet.pageLayout.setPrintTitleRows("$1:$1"); await context.sync(); }); -'Excel.PageLayout#zoom:member': +Excel.PageLayout#zoom:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-page-layout.yaml + await Excel.run(async (context) => { const farmSheet = context.workbook.worksheets.getItem("Print"); farmSheet.pageLayout.zoom = { scale: 200 }; await context.sync(); }); -'Excel.PageOrientation:enum': +Excel.PageOrientation:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-page-layout.yaml + await Excel.run(async (context) => { const farmSheet = context.workbook.worksheets.getItem("Print"); farmSheet.pageLayout.orientation = Excel.PageOrientation.landscape; await context.sync(); }); -'Excel.PictureFormat:enum': +Excel.PictureFormat:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-images.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Shapes"); const shape = sheet.shapes.getItem("Image"); @@ -4066,11 +5177,12 @@ // Your add-in would save this string as a .png file. console.log("The image's Base64-encoded string: " + imageString); }); -'Excel.PivotField#clearAllFilters:member(1)': +Excel.PivotField#clearAllFilters:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotfilters.yaml + await Excel.run(async (context) => { // Clear all the PivotFilters. @@ -4085,11 +5197,12 @@ }); await context.sync(); }); -'Excel.PivotFilters#dateFilter:member': +Excel.PivotFilters#dateFilter:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotfilters.yaml + await Excel.run(async (context) => { // Add a date-based PivotFilter. @@ -4117,11 +5230,12 @@ await context.sync(); }); -'Excel.PivotFilters#labelFilter:member': +Excel.PivotFilters#labelFilter:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotfilters.yaml + await Excel.run(async (context) => { // Add a PivotFilter to filter based on the strings of item labels. @@ -4143,11 +5257,12 @@ await context.sync(); }); -'Excel.PivotFilters#manualFilter:member': +Excel.PivotFilters#manualFilter:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotfilters.yaml + await Excel.run(async (context) => { // Add a PivotFilter to filter on manually-selected items. @@ -4169,11 +5284,12 @@ await context.sync(); }); -'Excel.PivotFilters#valueFilter:member': +Excel.PivotFilters#valueFilter:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotfilters.yaml + await Excel.run(async (context) => { // Add a PivotFilter to filter on the values correlated with a row. @@ -4195,11 +5311,12 @@ await context.sync(); }); -'Excel.PivotHierarchy#fields:member': +Excel.PivotHierarchy#fields:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotfilters.yaml + await Excel.run(async (context) => { // Add a PivotFilter to filter on the values correlated with a row. @@ -4221,11 +5338,34 @@ await context.sync(); }); -'Excel.PivotLayout#altTextDescription:member': +Excel.PivotLayout#getDataBodyRange:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-filters-and-summaries.yaml + + + await Excel.run(async (context) => { + const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); + + // The layout controls the ranges used by the PivotTable. + const range = pivotTable.layout.getDataBodyRange(); + + // Get all the data hierarchy totals. + const grandTotalRange = range.getLastRow(); + grandTotalRange.load("address"); + await context.sync(); + + // Use the wholesale and farm sale totals to make a final sum. + const masterTotalRange = context.workbook.worksheets.getActiveWorksheet().getRange("B27:C27"); + masterTotalRange.formulas = [["All Crates", "=SUM(" + grandTotalRange.address + ")"]]; + await context.sync(); + }); +Excel.PivotLayout#altTextDescription:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotlayout.yaml + await Excel.run(async (context) => { // Set the alt text for the displayed PivotTable. const pivotTable = context.workbook.pivotTables.getItem("Farm Sales"); @@ -4237,11 +5377,12 @@ await context.sync(); }); -'Excel.PivotLayout#displayBlankLineAfterEachItem:member(1)': +Excel.PivotLayout#displayBlankLineAfterEachItem:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotlayout.yaml + await Excel.run(async (context) => { // Add a blank row after each PivotItem in the row hierarchy. const pivotTable = context.workbook.pivotTables.getItem("Farm Sales"); @@ -4252,11 +5393,12 @@ await context.sync(); }); -'Excel.PivotLayout#emptyCellText:member': +Excel.PivotLayout#emptyCellText:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotlayout.yaml + await Excel.run(async (context) => { // Set a default value for an empty cell in the PivotTable. This doesn't include cells left blank by the layout. const pivotTable = context.workbook.pivotTables.getItem("Farm Sales"); @@ -4268,11 +5410,12 @@ pivotLayout.getDataBodyRange().format.horizontalAlignment = Excel.HorizontalAlignment.right; await context.sync(); }); -'Excel.PivotLayout#fillEmptyCells:member': +Excel.PivotLayout#fillEmptyCells:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotlayout.yaml + await Excel.run(async (context) => { // Toggle whether empty cells are filled with a default value. const pivotTable = context.workbook.pivotTables.getItem("Farm Sales"); @@ -4287,32 +5430,12 @@ pivotLayout.fillEmptyCells = fillToSet; await context.sync(); }); -'Excel.PivotLayout#getDataBodyRange:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-filters-and-summaries.yaml - - await Excel.run(async (context) => { - const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); - - // The layout controls the ranges used by the PivotTable. - const range = pivotTable.layout.getDataBodyRange(); - - // Get all the data hierarchy totals. - const grandTotalRange = range.getLastRow(); - grandTotalRange.load("address"); - await context.sync(); - - // Use the wholesale and farm sale totals to make a final sum. - const masterTotalRange = context.workbook.worksheets.getActiveWorksheet().getRange("B27:C27"); - masterTotalRange.formulas = [["All Crates", "=SUM(" + grandTotalRange.address + ")"]]; - await context.sync(); - }); -'Excel.PivotLayout#layoutType:member': +Excel.PivotLayout#layoutType:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotlayout.yaml + await Excel.run(async (context) => { // Change the PivotLayout.type to a new type. const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); @@ -4331,11 +5454,12 @@ await context.sync(); console.log("Pivot layout is now " + pivotTable.layout.layoutType); }); -'Excel.PivotLayout#preserveFormatting:member': +Excel.PivotLayout#preserveFormatting:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotlayout.yaml + await Excel.run(async (context) => { // Set whether the PivotTable keeps the established format after it is refreshed and recalculated. const pivotTable = context.workbook.pivotTables.getItem("Farm Sales"); @@ -4350,11 +5474,12 @@ pivotLayout.preserveFormatting = preserveFormattingToSet; await context.sync(); }); -'Excel.PivotLayout#repeatAllItemLabels:member(1)': +Excel.PivotLayout#repeatAllItemLabels:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotlayout.yaml + await Excel.run(async (context) => { // Repeat the PivotItem labels for each row used by another level of the row hierarchy. const pivotTable = context.workbook.pivotTables.getItem("Farm Sales"); @@ -4365,11 +5490,12 @@ await context.sync(); }); -'Excel.PivotLayout#showColumnGrandTotals:member': +Excel.PivotLayout#showColumnGrandTotals:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotlayout.yaml + await Excel.run(async (context) => { // Turn the grand totals on and off for the rows and columns. const pivotTable = context.workbook.pivotTables.getItem("Farm Sales"); @@ -4388,11 +5514,12 @@ await context.sync(); }); -'Excel.PivotLayout#showFieldHeaders:member': +Excel.PivotLayout#showFieldHeaders:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotlayout.yaml + await Excel.run(async (context) => { // Turn the field headers on and off for the row and column hierarchies. const pivotTable = context.workbook.pivotTables.getItem("Farm Sales"); @@ -4405,11 +5532,12 @@ pivotLayout.showFieldHeaders = showHeaders; await context.sync(); }); -'Excel.PivotLayout#showRowGrandTotals:member': +Excel.PivotLayout#showRowGrandTotals:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotlayout.yaml + await Excel.run(async (context) => { // Turn the grand totals on and off for the rows and columns. const pivotTable = context.workbook.pivotTables.getItem("Farm Sales"); @@ -4428,11 +5556,12 @@ await context.sync(); }); -'Excel.PivotTable#columnHierarchies:member': +Excel.PivotTable#columnHierarchies:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-create-and-modify.yaml + await Excel.run(async (context) => { const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); @@ -4450,11 +5579,12 @@ await context.sync(); }); -'Excel.PivotTable#dataHierarchies:member': +Excel.PivotTable#dataHierarchies:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-create-and-modify.yaml + await Excel.run(async (context) => { const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); pivotTable.dataHierarchies.add(pivotTable.hierarchies.getItem("Crates Sold at Farm")); @@ -4462,41 +5592,45 @@ await context.sync(); }); -'Excel.PivotTable#delete:member(1)': +Excel.PivotTable#delete:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-create-and-modify.yaml + await Excel.run(async (context) => { context.workbook.worksheets.getItem("Pivot").pivotTables.getItem("Farm Sales").delete(); await context.sync(); }); -'Excel.PivotTable#filterHierarchies:member': +Excel.PivotTable#layout:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-filters-and-summaries.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-create-and-modify.yaml - async function filter(functionType: Excel.AggregationFunction) { - await Excel.run(async (context) => { - const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); - const filters = pivotTable.filterHierarchies; - const filter = filters.getItemOrNullObject("Classification"); - filter.load(); - await context.sync(); - // Add the Classification hierarchy to the filter, if it's not already there. - if (filter.isNullObject) { - filters.add(pivotTable.hierarchies.getItem("Classification")); - await context.sync(); - } - }); - } -'Excel.PivotTable#getDataSourceString:member(1)': + await Excel.run(async (context) => { + const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); + pivotTable.layout.load("layoutType"); + await context.sync(); + + // Cycle between the three layout types. + if (pivotTable.layout.layoutType === "Compact") { + pivotTable.layout.layoutType = "Outline"; + } else if (pivotTable.layout.layoutType === "Outline") { + pivotTable.layout.layoutType = "Tabular"; + } else { + pivotTable.layout.layoutType = "Compact"; + } + await context.sync(); + console.log("Pivot layout is now " + pivotTable.layout.layoutType); + }); +Excel.PivotTable#getDataSourceString:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-source-data.yaml + // This function logs information about the data source of a PivotTable. await Excel.run(async (context) => { @@ -4512,11 +5646,12 @@ console.log("Data source: " + pivotTableDataSourceString.value); console.log("Source type: " + pivotTableDataSourceType.value); }); -'Excel.PivotTable#getDataSourceType:member(1)': +Excel.PivotTable#getDataSourceType:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-source-data.yaml + // This function logs information about the data source of a PivotTable. await Excel.run(async (context) => { @@ -4532,32 +5667,33 @@ console.log("Data source: " + pivotTableDataSourceString.value); console.log("Source type: " + pivotTableDataSourceType.value); }); -'Excel.PivotTable#layout:member': +Excel.PivotTable#filterHierarchies:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-create-and-modify.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-filters-and-summaries.yaml - await Excel.run(async (context) => { - const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); - pivotTable.layout.load("layoutType"); - await context.sync(); - // Cycle between the three layout types. - if (pivotTable.layout.layoutType === "Compact") { - pivotTable.layout.layoutType = "Outline"; - } else if (pivotTable.layout.layoutType === "Outline") { - pivotTable.layout.layoutType = "Tabular"; - } else { - pivotTable.layout.layoutType = "Compact"; - } - await context.sync(); - console.log("Pivot layout is now " + pivotTable.layout.layoutType); - }); -'Excel.PivotTable#refresh:member(1)': + async function filter(functionType: Excel.AggregationFunction) { + await Excel.run(async (context) => { + const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); + const filters = pivotTable.filterHierarchies; + const filter = filters.getItemOrNullObject("Classification"); + filter.load(); + await context.sync(); + + // Add the Classification hierarchy to the filter, if it's not already there. + if (filter.isNullObject) { + filters.add(pivotTable.hierarchies.getItem("Classification")); + await context.sync(); + } + }); + } +Excel.PivotTable#refresh:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-refresh.yaml + // This function refreshes the "Farm Sales" PivotTable, // which updates the PivotTable with changes made to the source table. @@ -4567,11 +5703,12 @@ pivotTable.refresh(); await context.sync(); }); -'Excel.PivotTableCollection#add:member(1)': +Excel.PivotTableCollection#add:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-create-and-modify.yaml + await Excel.run(async (context) => { const rangeToAnalyze = context.workbook.worksheets.getItem("Data").getRange("A1:E21"); const rangeToPlacePivot = context.workbook.worksheets.getItem("Pivot").getRange("A2"); @@ -4579,11 +5716,12 @@ await context.sync(); }); -'Excel.PivotTableCollection#getItem:member(1)': +Excel.PivotTableCollection#getItem:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-refresh.yaml + // This function refreshes the "Farm Sales" PivotTable, // which updates the PivotTable with changes made to the source table. @@ -4593,11 +5731,12 @@ pivotTable.refresh(); await context.sync(); }); -'Excel.PresetCriteriaConditionalFormat#rule:member': +Excel.PresetCriteriaConditionalFormat#rule:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B2:M5"); @@ -4608,143 +5747,92 @@ await context.sync(); }); -'Excel.Range#autoFill:member(1)': +Excel.Range#clearOrResetContents:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-auto-fill.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml + + + // Remove all content from the Analysis column. await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); - const sumCell = sheet.getRange("P4"); - - // Copy everything. The formulas will be contextually updated based on their new locations. - sumCell.autoFill("P4:P7", Excel.AutoFillType.fillCopy); - sumCell.format.autofitColumns(); + + // Get the second column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Clear all the data from the second column. + range.clearOrResetContents(); await context.sync(); }); -'Excel.Range#copyFrom:member(1)': +Excel.Range#control:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-copyfrom.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml + + + // Add checkboxes to the table. await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - // Place a label in front of the copied data. - sheet.getRange("F2").values = [["Copied Formula"]]; + const sheet = context.workbook.worksheets.getActiveWorksheet(); - // Copy a range preserving the formulas. - // Note: non-formula values are copied over as is. - sheet.getRange("G2").copyFrom("A1:E1", Excel.RangeCopyType.formulas); - await context.sync(); + // Get the second column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Change the boolean values to checkboxes. + range.control = { + type: Excel.CellControlType.checkbox + }; + await context.sync(); }); -'Excel.Range#find:member(1)': +Excel.Range#values:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-find.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const table = sheet.tables.getItem("ExpensesTable"); - const searchRange = table.getRange(); - // NOTE: If no match is found, an ItemNotFound error - // is thrown when Range.find is evaluated. - const foundRange = searchRange.find($("#searchText").val().toString(), { - completeMatch: isCompleteMatchToggle, - matchCase: isMatchCaseToggle, - searchDirection: searchDirectionToggle - }); - - foundRange.load("address"); - await context.sync(); - - - console.log(foundRange.address); - }); -'Excel.Range#findOrNullObject:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-find.yaml + // Change the value of the checkbox in B3. await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const table = sheet.tables.getItem("ExpensesTable"); - const searchRange = table.getRange(); - const foundRange = searchRange.findOrNullObject($("#searchText").val().toString(), { - completeMatch: isCompleteMatchToggle, - matchCase: isMatchCaseToggle, - searchDirection: searchDirectionToggle - }); - - foundRange.load("address"); - await context.sync(); + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("B3"); - if (foundRange.isNullObject) { - console.log("Text not found"); - } else { - console.log(foundRange.address); - } + range.values = [["TRUE"]]; + await context.sync(); }); -'Excel.Range#getCellProperties:member(1)': +Excel.Range#valuesAsJson:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml - - await Excel.run(async (context) => { - const cell = context.workbook.getActiveCell(); - - // Define the cell properties to get by setting the matching LoadOptions to true. - const propertiesToGet = cell.getCellProperties({ - address: true, - format: { - fill: { - color: true - }, - font: { - color: true - } - }, - style: true - }); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-formatted-number.yaml - // Sync to get the data from the workbook. - await context.sync(); - const cellProperties = propertiesToGet.value[0][0]; - console.log( - `Address: ${cellProperties.address}\nStyle: ${cellProperties.style}\nFill Color: ${cellProperties.format.fill.color}\nFont Color: ${cellProperties.format.font.color}`); - }); -'Excel.Range#getDependents:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-dependents.yaml - // This function highlights all the dependent cells of the active cell. + // This function creates a double data type, - // Dependent cells contain formulas that refer to other cells. + // and sets the format of this data type as a date. await Excel.run(async (context) => { - // Get addresses of the active cell's dependent cells. - const range = context.workbook.getActiveCell(); - const dependents = range.getDependents(); - range.load("address"); - dependents.areas.load("address"); - await context.sync(); - - console.log(`All dependent cells of ${range.address}:`); + // Get the Sample worksheet and a range on that sheet. + const sheet = context.workbook.worksheets.getItemOrNullObject("Sample"); + const dateRange = sheet.getRange("A1"); - // Use the dependents API to loop through dependents of the active cell. - for (let i = 0; i < dependents.areas.items.length; i++) { - // Highlight and print out the address of each dependent cell. - dependents.areas.items[i].format.fill.color = "Orange"; - console.log(` ${dependents.areas.items[i].address}`); - } + // Write a number formatted as a date to cell A1. + dateRange.valuesAsJson = [ + [ + { + type: Excel.CellValueType.double, + basicValue: 32889.0, + numberFormat: "m/d/yyyy" + } + ] + ]; await context.sync(); }); -'Excel.Range#getDirectDependents:member(1)': +Excel.Range#getDirectDependents:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-direct-dependents.yaml + await Excel.run(async (context) => { // Direct dependents are cells that contain formulas that refer to other cells. let range = context.workbook.getActiveCell(); @@ -4763,119 +5851,42 @@ } await context.sync(); }); -'Excel.Range#getDirectPrecedents:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/precedents.yaml - - await Excel.run(async (context) => { - // Precedents are cells referenced by the formula in a cell. - // A "direct precedent" is a cell directly referenced by the selected formula. - let range = context.workbook.getActiveCell(); - let directPrecedents = range.getDirectPrecedents(); - range.load("address"); - directPrecedents.areas.load("address"); - await context.sync(); - - console.log(`Direct precedent cells of ${range.address}:`); - - // Use the direct precedents API to loop through precedents of the active cell. - for (let i = 0; i < directPrecedents.areas.items.length; i++) { - // Highlight and console the address of each precedent cell. - directPrecedents.areas.items[i].format.fill.color = "Yellow"; - console.log(` ${directPrecedents.areas.items[i].address}`); - } - await context.sync(); - }); -'Excel.Range#getExtendedRange:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-get-range-edge.yaml - - await Excel.run(async (context) => { - // Get the selected range. - const range = context.workbook.getSelectedRange(); - - // Specify the direction with the `KeyboardDirection` enum. - const direction = Excel.KeyboardDirection.down; - - // Get the active cell in the workbook. - const activeCell = context.workbook.getActiveCell(); - - // Get all the cells from the currently selected range to the bottom-most edge of the used range. - // This method acts like the Ctrl+Shift+Arrow key keyboard shortcut while a range is selected. - const extendedRange = range.getExtendedRange( - direction, - activeCell // If the selected range contains more than one cell, the active cell must be defined. - ); - extendedRange.select(); - - await context.sync(); - }); -'Excel.Range#getIntersectionOrNullObject:member(1)': +Excel.Range#sort:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-relationships.yaml - - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const salesTable = sheet.tables.getItem("SalesTable"); - const dataRange = salesTable.getDataBodyRange(); - - // We want the most recent quarter that has data, so - // exclude quarters without data and get the last of - // the remaining columns. - const usedDataRange = dataRange.getUsedRange(true /* valuesOnly */); - const currentQuarterRange = usedDataRange.getLastColumn(); - - // Asian and European teams have separate contests. - const asianSalesRange = sheet.getRange("A2:E4"); - const europeanSalesRange = sheet.getRange("A5:E7"); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-column-and-row-sort.yaml - // The data for each chart is the intersection of the - // current quarter column and the rows for the continent. - const asianContestRange = asianSalesRange.getIntersectionOrNullObject(currentQuarterRange); - const europeanContestRange = europeanSalesRange.getIntersectionOrNullObject(currentQuarterRange); - // Must sync before you can test the output of *OrNullObject - // method/property. - await context.sync(); + async function sortTopToBottom(criteria: string) { + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("A1:E5"); - if (asianContestRange.isNullObject) { - // See the declaration of this function for how to - // test this code path. - reportMissingData("Asian"); - } else { - createContinentChart( - sheet, - "Asian", - asianContestRange, - "A9", - "F24" - ); - } + // Find the column header that provides the sort criteria. + const header = range.find(criteria, {}); + header.load("columnIndex"); + await context.sync(); - if (europeanContestRange.isNullObject) { - // See the declaration of this function for how to - // test this code path. - reportMissingData("European"); - } else { - createContinentChart( - sheet, - "European", - europeanContestRange, - "A25", - "F40" + range.sort.apply( + [ + { + key: header.columnIndex, + sortOn: Excel.SortOn.value + } + ], + false /*matchCase*/, + true /*hasHeaders*/, + Excel.SortOrientation.rows ); - } - - await context.sync(); - }); -'Excel.Range#getMergedAreasOrNullObject:member(1)': + await context.sync(); + }); + } +Excel.Range#getMergedAreasOrNullObject:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-merged-ranges.yaml + await Excel.run(async (context) => { // Retrieve the worksheet and the table in that worksheet. const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -4897,334 +5908,205 @@ await context.sync(); }); -'Excel.Range#getPivotTables:member(1)': +Excel.Range#merge:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-get-pivottables.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-merged-ranges.yaml + await Excel.run(async (context) => { - const activeRange = context.workbook.getSelectedRange(); + // Retrieve the worksheet and the table in that worksheet. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const tableRange = sheet.getRange("B2:E6"); - // Get all the PivotTables that intersect with this range. - const partiallyContainedPivotTables = activeRange.getPivotTables(); - // Get all the PivotTables that are completely contained within this range. - const fullyContainedPivotTables = activeRange.getPivotTables(true); + // Create a merged range in the first row of the table. + const chartTitle = tableRange.getRow(0); + chartTitle.merge(true); - partiallyContainedPivotTables.load("name"); - fullyContainedPivotTables.load("name"); - await context.sync(); + // Format the merged range. + chartTitle.format.horizontalAlignment = "Center"; - // Display the names in the console. - console.log("PivotTables in the current range:") - partiallyContainedPivotTables.items.forEach((pivotTable) => { - console.log(`\t${pivotTable.name}`); - }); - console.log("PivotTables completely contained in the current range:") - fullyContainedPivotTables.items.forEach((pivotTable) => { - console.log(`\t${pivotTable.name}`); - }); + await context.sync(); }); -'Excel.Range#getPrecedents:member(1)': +Excel.Range#group:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/precedents.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/outline.yaml - await Excel.run(async (context) => { - // Precedents are cells referenced by the formula in a cell. - let range = context.workbook.getActiveCell(); - let precedents = range.getPrecedents(); - range.load("address"); - precedents.areas.load("address"); - await context.sync(); - console.log(`All precedent cells of ${range.address}:`); + Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Group the larger, main level. Note that the outline controls + // will be on row 10, meaning 4-9 will collapse and expand. + sheet.getRange("4:9").group(Excel.GroupOption.byRows); - // Use the precedents API to loop through precedents of the active cell. - for (let i = 0; i < precedents.areas.items.length; i++) { - // Highlight and console the address of each precedent cell. - precedents.areas.items[i].format.fill.color = "Orange"; - console.log(` ${precedents.areas.items[i].address}`); - } - await context.sync(); + // Group the smaller, sublevels. Note that the outline controls + // will be on rows 6 and 9, meaning 4-5 and 7-8 will collapse and expand. + sheet.getRange("4:5").group(Excel.GroupOption.byRows); + sheet.getRange("7:8").group(Excel.GroupOption.byRows); + await context.sync(); }); -'Excel.Range#getRangeEdge:member(1)': +Excel.Range#ungroup:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-get-range-edge.yaml - - await Excel.run(async (context) => { - // Get the selected range. - const range = context.workbook.getSelectedRange(); - - // Specify the direction with the `KeyboardDirection` enum. - const direction = Excel.KeyboardDirection.up; - - // Get the active cell in the workbook. - const activeCell = context.workbook.getActiveCell(); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/outline.yaml - // Get the top-most cell of the current used range. - // This method acts like the Ctrl+Arrow key keyboard shortcut while a range is selected. - const rangeEdge = range.getRangeEdge( - direction, - activeCell // If the selected range contains more than one cell, the active cell must be defined. - ); - rangeEdge.select(); - await context.sync(); + Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // This removes two levels of groups from the "A1-R10" range. + // Any groups at the same level on the same dimension will be removed by a single call. + sheet.getRange("A1:R10").ungroup(Excel.GroupOption.byRows); + sheet.getRange("A1:R10").ungroup(Excel.GroupOption.byRows); + sheet.getRange("A1:R10").ungroup(Excel.GroupOption.byColumns); + sheet.getRange("A1:R10").ungroup(Excel.GroupOption.byColumns); + await context.sync(); }); -'Excel.Range#getSpecialCells:member(1)': +Excel.Range#getPivotTables:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-areas.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-get-pivottables.yaml + await Excel.run(async (context) => { + const activeRange = context.workbook.getSelectedRange(); - const sheet = context.workbook.worksheets.getActiveWorksheet(); - const usedRange = sheet.getUsedRange(); + // Get all the PivotTables that intersect with this range. + const partiallyContainedPivotTables = activeRange.getPivotTables(); + // Get all the PivotTables that are completely contained within this range. + const fullyContainedPivotTables = activeRange.getPivotTables(true); - // Find the ranges with either text or logical (boolean) values. - const formulaRanges = usedRange.getSpecialCells("Constants", "LogicalText"); - formulaRanges.format.fill.color = "orange"; + partiallyContainedPivotTables.load("name"); + fullyContainedPivotTables.load("name"); + await context.sync(); - return context.sync(); + // Display the names in the console. + console.log("PivotTables in the current range:") + partiallyContainedPivotTables.items.forEach((pivotTable) => { + console.log(`\t${pivotTable.name}`); + }); + console.log("PivotTables completely contained in the current range:") + fullyContainedPivotTables.items.forEach((pivotTable) => { + console.log(`\t${pivotTable.name}`); + }); }); -'Excel.Range#getSpillingToRange:member(1)': +Excel.Range#getDirectPrecedents:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/dynamic-arrays.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/precedents.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - // Set G4 to a formula that returns a dynamic array. - const targetCell = sheet.getRange("G4"); - targetCell.formulas = [["=A4:D4"]]; + await Excel.run(async (context) => { + // Precedents are cells referenced by the formula in a cell. + // A "direct precedent" is a cell directly referenced by the selected formula. + let range = context.workbook.getActiveCell(); + let directPrecedents = range.getDirectPrecedents(); + range.load("address"); + directPrecedents.areas.load("address"); + await context.sync(); - // Get the address of the cells that the dynamic array spilled into. - const spillRange = targetCell.getSpillingToRange(); - spillRange.load("address"); + console.log(`Direct precedent cells of ${range.address}:`); - // Fit the columns for readability. - sheet.getUsedRange().format.autofitColumns(); + // Use the direct precedents API to loop through precedents of the active cell. + for (let i = 0; i < directPrecedents.areas.items.length; i++) { + // Highlight and console the address of each precedent cell. + directPrecedents.areas.items[i].format.fill.color = "Yellow"; + console.log(` ${directPrecedents.areas.items[i].address}`); + } await context.sync(); - - console.log(`Copying the table headers spilled into ${spillRange.address}.`); }); -'Excel.Range#getUsedRange:member(1)': +Excel.Range#getPrecedents:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-relationships.yaml - - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const salesTable = sheet.tables.getItem("SalesTable"); - const dataRange = salesTable.getDataBodyRange(); - - // We want the most recent quarter that has data, so - // exclude quarters without data and get the last of - // the remaining columns. - const usedDataRange = dataRange.getUsedRange(true /* valuesOnly */); - const currentQuarterRange = usedDataRange.getLastColumn(); - - // Asian and European teams have separate contests. - const asianSalesRange = sheet.getRange("A2:E4"); - const europeanSalesRange = sheet.getRange("A5:E7"); - - // The data for each chart is the intersection of the - // current quarter column and the rows for the continent. - const asianContestRange = asianSalesRange.getIntersectionOrNullObject(currentQuarterRange); - const europeanContestRange = europeanSalesRange.getIntersectionOrNullObject(currentQuarterRange); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/precedents.yaml - // Must sync before you can test the output of *OrNullObject - // method/property. - await context.sync(); - if (asianContestRange.isNullObject) { - // See the declaration of this function for how to - // test this code path. - reportMissingData("Asian"); - } else { - createContinentChart( - sheet, - "Asian", - asianContestRange, - "A9", - "F24" - ); - } + await Excel.run(async (context) => { + // Precedents are cells referenced by the formula in a cell. + let range = context.workbook.getActiveCell(); + let precedents = range.getPrecedents(); + range.load("address"); + precedents.areas.load("address"); + await context.sync(); - if (europeanContestRange.isNullObject) { - // See the declaration of this function for how to - // test this code path. - reportMissingData("European"); - } else { - createContinentChart( - sheet, - "European", - europeanContestRange, - "A25", - "F40" - ); - } + console.log(`All precedent cells of ${range.address}:`); - await context.sync(); + // Use the precedents API to loop through precedents of the active cell. + for (let i = 0; i < precedents.areas.items.length; i++) { + // Highlight and console the address of each precedent cell. + precedents.areas.items[i].format.fill.color = "Orange"; + console.log(` ${precedents.areas.items[i].address}`); + } + await context.sync(); }); -'Excel.Range#getUsedRangeOrNullObject:member(1)': +Excel.Range#getSpecialCells:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/used-range.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-areas.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const salesTable = sheet.tables.getItem("SalesTable"); - const dataRange = salesTable.getDataBodyRange(); - // Pass true so only cells with values count as used - const usedDataRange = dataRange.getUsedRangeOrNullObject( - true /* valuesOnly */ - ); + await Excel.run(async (context) => { - //Must sync before reading value returned from *OrNullObject method/property. - await context.sync(); + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const usedRange = sheet.getUsedRange(); - if (usedDataRange.isNullObject) { - console.log("Need Data to Make Chart"); - console.log("To create a meaningful chart, press 'Fill the table' (or add names to the Product column and numbers to some of the other cells). Then press 'Try to create chart' again."); - } else { - const chart = sheet.charts.add( - Excel.ChartType.columnClustered, - dataRange, - "Columns" - ); - chart.setPosition("A15", "F30"); - chart.title.text = "Quarterly sales chart"; - chart.legend.position = "Right"; - chart.legend.format.fill.setSolidColor("white"); - chart.dataLabels.format.font.size = 15; - chart.dataLabels.format.font.color = "black"; - } + // Find the ranges with either text or logical (boolean) values. + const formulaRanges = usedRange.getSpecialCells("Constants", "LogicalText"); + formulaRanges.format.fill.color = "orange"; - await context.sync(); + return context.sync(); }); -'Excel.Range#group:member(1)': +Excel.Range#autoFill:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/outline.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-auto-fill.yaml - Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); - - // Group the larger, main level. Note that the outline controls - // will be on row 10, meaning 4-9 will collapse and expand. - sheet.getRange("4:9").group(Excel.GroupOption.byRows); - // Group the smaller, sublevels. Note that the outline controls - // will be on rows 6 and 9, meaning 4-5 and 7-8 will collapse and expand. - sheet.getRange("4:5").group(Excel.GroupOption.byRows); - sheet.getRange("7:8").group(Excel.GroupOption.byRows); - await context.sync(); + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const sumCell = sheet.getRange("P4"); + + // Copy everything. The formulas will be contextually updated based on their new locations. + sumCell.autoFill("P4:P7", Excel.AutoFillType.fillCopy); + sumCell.format.autofitColumns(); + await context.sync(); }); -'Excel.Range#hyperlink:member': +Excel.Range#getCellProperties:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Orders"); + const cell = context.workbook.getActiveCell(); - let productsRange = sheet.getRange("A3:A5"); - productsRange.load("values"); + // Define the cell properties to get by setting the matching LoadOptions to true. + const propertiesToGet = cell.getCellProperties({ + address: true, + format: { + fill: { + color: true + }, + font: { + color: true + } + }, + style: true + }); + // Sync to get the data from the workbook. await context.sync(); + const cellProperties = propertiesToGet.value[0][0]; + console.log( + `Address: ${cellProperties.address}\nStyle: ${cellProperties.style}\nFill Color: ${cellProperties.format.fill.color}\nFont Color: ${cellProperties.format.font.color}`); + }); +Excel.Range#setCellProperties:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml - // Create a hyperlink to a URL - // for each product name in the first table. - for (let i = 0; i < productsRange.values.length; i++) { - let cellRange = productsRange.getCell(i, 0); - let cellText = productsRange.values[i][0]; - - let hyperlink = { - textToDisplay: cellText, - screenTip: "Search Bing for '" + cellText + "'", - address: "https://www.bing.com?q=" + cellText - } - cellRange.hyperlink = hyperlink; - } - - await context.sync(); - }); -'Excel.Range#merge:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-merged-ranges.yaml - - await Excel.run(async (context) => { - // Retrieve the worksheet and the table in that worksheet. - const sheet = context.workbook.worksheets.getActiveWorksheet(); - const tableRange = sheet.getRange("B2:E6"); - - // Create a merged range in the first row of the table. - const chartTitle = tableRange.getRow(0); - chartTitle.merge(true); - - // Format the merged range. - chartTitle.format.horizontalAlignment = "Center"; - - await context.sync(); - }); -'Excel.Range#moveTo:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-copyfrom.yaml - - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - // Place a label in front of the moved data. - sheet.getRange("F12").values = [["Moved Range:"]]; - - // Move the range from A1:E1 to G12:K12. - sheet.getRange("A1:E1").moveTo("G12"); - await context.sync(); - }); -'Excel.Range#removeDuplicates:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-remove-duplicates.yaml - - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const range = sheet.getRange("B2:D11"); - - const deleteResult = range.removeDuplicates([0],true); - deleteResult.load(); - await context.sync(); - - console.log(deleteResult.removed + " entries with duplicate names removed."); - console.log(deleteResult.uniqueRemaining + " entries with unique names remain in the range."); - }); -'Excel.Range#set:member(2)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/90-scenarios/multiple-property-set.yaml - - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - - const sourceRange = sheet.getRange("B2:E2"); - sourceRange.load("format/fill/color, format/font/name, format/font/color"); - await context.sync(); - - // Set properties based on the loaded and synced - // source range. - const targetRange = sheet.getRange("B7:E7"); - targetRange.set(sourceRange); - targetRange.format.autofitColumns(); - await context.sync(); - }); -'Excel.Range#setCellProperties:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -5297,202 +6179,198 @@ sheet.getUsedRange().format.autofitColumns(); await context.sync(); }); -'Excel.Range#sort:member': +Excel.Range#copyFrom:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-column-and-row-sort.yaml - - async function sortTopToBottom(criteria: string) { - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); - const range = sheet.getRange("A1:E5"); - - // Find the column header that provides the sort criteria. - const header = range.find(criteria, {}); - header.load("columnIndex"); - await context.sync(); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-copyfrom.yaml - range.sort.apply( - [ - { - key: header.columnIndex, - sortOn: Excel.SortOn.value - } - ], - false /*matchCase*/, - true /*hasHeaders*/, - Excel.SortOrientation.rows - ); - await context.sync(); - }); - } -'Excel.Range#style:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml await Excel.run(async (context) => { - let worksheet = context.workbook.worksheets.getItem("Sample"); - let range = worksheet.getRange("A1:E1"); - - // Apply built-in style. - // Styles are in the Home tab ribbon. - range.style = Excel.BuiltInStyle.neutral; - range.format.horizontalAlignment = "Right"; + const sheet = context.workbook.worksheets.getItem("Sample"); + // Place a label in front of the copied data. + sheet.getRange("F2").values = [["Copied Formula"]]; + // Copy a range preserving the formulas. + // Note: non-formula values are copied over as is. + sheet.getRange("G2").copyFrom("A1:E1", Excel.RangeCopyType.formulas); await context.sync(); }); -'Excel.Range#ungroup:member(1)': +Excel.Range#moveTo:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/outline.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-copyfrom.yaml - Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); - - // This removes two levels of groups from the "A1-R10" range. - // Any groups at the same level on the same dimension will be removed by a single call. - sheet.getRange("A1:R10").ungroup(Excel.GroupOption.byRows); - sheet.getRange("A1:R10").ungroup(Excel.GroupOption.byRows); - sheet.getRange("A1:R10").ungroup(Excel.GroupOption.byColumns); - sheet.getRange("A1:R10").ungroup(Excel.GroupOption.byColumns); + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + // Place a label in front of the moved data. + sheet.getRange("F12").values = [["Moved Range:"]]; + + // Move the range from A1:E1 to G12:K12. + sheet.getRange("A1:E1").moveTo("G12"); await context.sync(); }); -'Excel.Range#valuesAsJson:member': +Excel.Range#getDependents:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-formatted-number.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-dependents.yaml - // This function creates a formatted number data type, - // and sets the format of this data type as a date. + // This function highlights all the dependent cells of the active cell. + + // Dependent cells contain formulas that refer to other cells. await Excel.run(async (context) => { - // Get the Sample worksheet and a range on that sheet. - const sheet = context.workbook.worksheets.getItemOrNullObject("Sample"); - const dateRange = sheet.getRange("A1"); + // Get addresses of the active cell's dependent cells. + const range = context.workbook.getActiveCell(); + const dependents = range.getDependents(); + range.load("address"); + dependents.areas.load("address"); + await context.sync(); - // Write a number formatted as a date to cell A1. - dateRange.valuesAsJson = [ - [ - { - type: Excel.CellValueType.formattedNumber, - basicValue: 32889.0, - numberFormat: "m/d/yyyy" - } - ] - ]; + console.log(`All dependent cells of ${range.address}:`); + + // Use the dependents API to loop through dependents of the active cell. + for (let i = 0; i < dependents.areas.items.length; i++) { + // Highlight and print out the address of each dependent cell. + dependents.areas.items[i].format.fill.color = "Orange"; + console.log(` ${dependents.areas.items[i].address}`); + } await context.sync(); }); -'Excel.RangeAreas#format:member': +Excel.Range#getSpillingToRange:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-areas.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/dynamic-arrays.yaml + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); - const sheet = context.workbook.worksheets.getActiveWorksheet(); - const usedRange = sheet.getUsedRange(); + // Set G4 to a formula that returns a dynamic array. + const targetCell = sheet.getRange("G4"); + targetCell.formulas = [["=A4:D4"]]; - // Find the ranges with formulas. - const formulaRanges = usedRange.getSpecialCells("Formulas"); - formulaRanges.format.fill.color = "lightgreen"; + // Get the address of the cells that the dynamic array spilled into. + const spillRange = targetCell.getSpillingToRange(); + spillRange.load("address"); - await context.sync(); + // Fit the columns for readability. + sheet.getUsedRange().format.autofitColumns(); + await context.sync(); + + console.log(`Copying the table headers spilled into ${spillRange.address}.`); }); -'Excel.RangeCopyType:enum': +Excel.Range#find:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-copyfrom.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-find.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); - // Place a label in front of the copied data. - sheet.getRange("F2").values = [["Copied Formula"]]; + const table = sheet.tables.getItem("ExpensesTable"); + const searchRange = table.getRange(); - // Copy a range preserving the formulas. - // Note: non-formula values are copied over as is. - sheet.getRange("G2").copyFrom("A1:E1", Excel.RangeCopyType.formulas); + // NOTE: If no match is found, an ItemNotFound error + // is thrown when Range.find is evaluated. + const searchText = (document.getElementById("searchText") as HTMLTextAreaElement).value; + const foundRange = searchRange.find(searchText, { + completeMatch: isCompleteMatchToggle, + matchCase: isMatchCaseToggle, + searchDirection: searchDirectionToggle + }); + + foundRange.load("address"); await context.sync(); + + + console.log(foundRange.address); }); -'Excel.RangeFormat#textOrientation:member': +Excel.Range#findOrNullObject:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-text-orientation.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-find.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); - const range = sheet.getRange("B2:E2"); - - // Set textOrientation to either an integer between -90 and 90 - // or to 180 for vertically-oriented text. - range.format.textOrientation = 90; - + const table = sheet.tables.getItem("ExpensesTable"); + const searchRange = table.getRange(); + const searchText = (document.getElementById("searchText") as HTMLTextAreaElement).value; + const foundRange = searchRange.findOrNullObject(searchText, { + completeMatch: isCompleteMatchToggle, + matchCase: isMatchCaseToggle, + searchDirection: searchDirectionToggle + }); + + foundRange.load("address"); await context.sync(); + + if (foundRange.isNullObject) { + console.log("Text not found"); + } else { + console.log(foundRange.address); + } }); -'Excel.RangeHyperlink#address:member': +Excel.Range#getExtendedRange:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-get-range-edge.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Orders"); - let productsRange = sheet.getRange("A3:A5"); - productsRange.load("values"); + await Excel.run(async (context) => { + // Get the selected range. + const range = context.workbook.getSelectedRange(); - await context.sync(); + // Specify the direction with the `KeyboardDirection` enum. + const direction = Excel.KeyboardDirection.down; - // Create a hyperlink to a URL - // for each product name in the first table. - for (let i = 0; i < productsRange.values.length; i++) { - let cellRange = productsRange.getCell(i, 0); - let cellText = productsRange.values[i][0]; + // Get the active cell in the workbook. + const activeCell = context.workbook.getActiveCell(); - let hyperlink = { - textToDisplay: cellText, - screenTip: "Search Bing for '" + cellText + "'", - address: "https://www.bing.com?q=" + cellText - } - cellRange.hyperlink = hyperlink; - } + // Get all the cells from the currently selected range to the bottom-most edge of the used range. + // This method acts like the Ctrl+Shift+Arrow key keyboard shortcut while a range is selected. + const extendedRange = range.getExtendedRange( + direction, + activeCell // If the selected range contains more than one cell, the active cell must be defined. + ); + extendedRange.select(); - await context.sync(); + await context.sync(); }); -'Excel.RangeHyperlink#documentReference:member': +Excel.Range#getRangeEdge:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-get-range-edge.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Orders"); - let productsRange = sheet.getRange("A9:A11"); - productsRange.load("values"); + await Excel.run(async (context) => { + // Get the selected range. + const range = context.workbook.getSelectedRange(); - await context.sync(); + // Specify the direction with the `KeyboardDirection` enum. + const direction = Excel.KeyboardDirection.up; - // Create a hyperlink to a location within the workbook - // for each product name in the second table. - for (let i = 0; i < productsRange.values.length; i++) { - let cellRange = productsRange.getCell(i, 0); - let cellText = productsRange.values[i][0]; + // Get the active cell in the workbook. + const activeCell = context.workbook.getActiveCell(); - let hyperlink = { - textToDisplay: cellText, - screenTip: "Navigate to the '" + cellText + "' worksheet", - documentReference: cellText + "!A1" - } - cellRange.hyperlink = hyperlink; - } + // Get the top-most cell of the current used range. + // This method acts like the Ctrl+Arrow key keyboard shortcut while a range is selected. + const rangeEdge = range.getRangeEdge( + direction, + activeCell // If the selected range contains more than one cell, the active cell must be defined. + ); + rangeEdge.select(); - await context.sync(); + await context.sync(); }); -'Excel.RangeHyperlink#screenTip:member': +Excel.Range#hyperlink:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Orders"); @@ -5517,88 +6395,132 @@ await context.sync(); }); -'Excel.RangeHyperlink#textToDisplay:member': +Excel.Range#getIntersectionOrNullObject:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-relationships.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Orders"); + const sheet = context.workbook.worksheets.getItem("Sample"); + const salesTable = sheet.tables.getItem("SalesTable"); + const dataRange = salesTable.getDataBodyRange(); - let productsRange = sheet.getRange("A3:A5"); - productsRange.load("values"); + // We want the most recent quarter that has data, so + // exclude quarters without data and get the last of + // the remaining columns. + const usedDataRange = dataRange.getUsedRange(true /* valuesOnly */); + const currentQuarterRange = usedDataRange.getLastColumn(); + // Asian and European teams have separate contests. + const asianSalesRange = sheet.getRange("A2:E4"); + const europeanSalesRange = sheet.getRange("A5:E7"); + + // The data for each chart is the intersection of the + // current quarter column and the rows for the continent. + const asianContestRange = asianSalesRange.getIntersectionOrNullObject(currentQuarterRange); + const europeanContestRange = europeanSalesRange.getIntersectionOrNullObject(currentQuarterRange); + + // Must sync before you can test the output of *OrNullObject + // method/property. await context.sync(); - // Create a hyperlink to a URL - // for each product name in the first table. - for (let i = 0; i < productsRange.values.length; i++) { - let cellRange = productsRange.getCell(i, 0); - let cellText = productsRange.values[i][0]; + if (asianContestRange.isNullObject) { + // See the declaration of this function for how to + // test this code path. + reportMissingData("Asian"); + } else { + createContinentChart( + sheet, + "Asian", + asianContestRange, + "A9", + "F24" + ); + } - let hyperlink = { - textToDisplay: cellText, - screenTip: "Search Bing for '" + cellText + "'", - address: "https://www.bing.com?q=" + cellText - } - cellRange.hyperlink = hyperlink; + if (europeanContestRange.isNullObject) { + // See the declaration of this function for how to + // test this code path. + reportMissingData("European"); + } else { + createContinentChart( + sheet, + "European", + europeanContestRange, + "A25", + "F40" + ); } await context.sync(); }); -'Excel.RangeUnderlineStyle:enum': +Excel.Range#getUsedRange:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-relationships.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Orders"); + const sheet = context.workbook.worksheets.getItem("Sample"); + const salesTable = sheet.tables.getItem("SalesTable"); + const dataRange = salesTable.getDataBodyRange(); - const productsRange = sheet.getRange("A3:A11"); - productsRange.load("values"); + // We want the most recent quarter that has data, so + // exclude quarters without data and get the last of + // the remaining columns. + const usedDataRange = dataRange.getUsedRange(true /* valuesOnly */); + const currentQuarterRange = usedDataRange.getLastColumn(); - await context.sync(); + // Asian and European teams have separate contests. + const asianSalesRange = sheet.getRange("A2:E4"); + const europeanSalesRange = sheet.getRange("A5:E7"); - // Clear all hyperlinks. - for (let i = 0; i < productsRange.values.length; i++) { - let cellRange = productsRange.getCell(i, 0); + // The data for each chart is the intersection of the + // current quarter column and the rows for the continent. + const asianContestRange = asianSalesRange.getIntersectionOrNullObject(currentQuarterRange); + const europeanContestRange = europeanSalesRange.getIntersectionOrNullObject(currentQuarterRange); - // Clear the hyperlink. - // This eliminates the hyperlink but does not update text format. - cellRange.clear(Excel.ClearApplyTo.hyperlinks); + // Must sync before you can test the output of *OrNullObject + // method/property. + await context.sync(); - // Update text format. - cellRange.format.font.underline = Excel.RangeUnderlineStyle.none; - cellRange.format.font.color = "#000000"; + if (asianContestRange.isNullObject) { + // See the declaration of this function for how to + // test this code path. + reportMissingData("Asian"); + } else { + createContinentChart( + sheet, + "Asian", + asianContestRange, + "A9", + "F24" + ); } - await context.sync(); - }); -'Excel.ReadingOrder:enum': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml - - await Excel.run(async (context) => { - let style = context.workbook.styles.getItem("Diagonal Orientation Style"); - style.load("textOrientation, horizontalAlignment, autoIndent, readingOrder, wrapText, includeProtection, shrinkToFit, locked"); + if (europeanContestRange.isNullObject) { + // See the declaration of this function for how to + // test this code path. + reportMissingData("European"); + } else { + createContinentChart( + sheet, + "European", + europeanContestRange, + "A25", + "F40" + ); + } await context.sync(); - - console.log("Orientation: " + style.textOrientation); - console.log("Horizontal alignment: " + style.horizontalAlignment); - console.log("Add indent: " + style.autoIndent); - console.log("Reading order: " + style.readingOrder); - console.log("Wrap text: " + style.wrapText); - console.log("Include protection: " + style.includeProtection); - console.log("Shrink to fit: " + style.shrinkToFit); - console.log("Style locked: " + style.locked); }); -'Excel.RemoveDuplicatesResult#uniqueRemaining:member': +Excel.Range#removeDuplicates:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-remove-duplicates.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); const range = sheet.getRange("B2:D11"); @@ -5610,400 +6532,735 @@ console.log(deleteResult.removed + " entries with duplicate names removed."); console.log(deleteResult.uniqueRemaining + " entries with unique names remain in the range."); }); -'Excel.Runtime#enableEvents:member': +Excel.Range#style:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-disable-events.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + await Excel.run(async (context) => { - context.runtime.load("enableEvents"); - await context.sync(); + let worksheet = context.workbook.worksheets.getItem("Sample"); + let range = worksheet.getRange("A1:E1"); - // check if events are enabled and toggle accordingly - const eventBoolean = !context.runtime.enableEvents - context.runtime.enableEvents = eventBoolean; - if (eventBoolean) { - console.log("Events are currently on."); - } else { - console.log("Events are currently off."); - } + // Apply built-in style. + // Styles are in the Home tab ribbon. + range.style = Excel.BuiltInStyle.neutral; + range.format.horizontalAlignment = "Right"; await context.sync(); }); -'Excel.SaveBehavior:enum': +Excel.Range#getUsedRangeOrNullObject:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-save-and-close.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/used-range.yaml + await Excel.run(async (context) => { - context.workbook.save(Excel.SaveBehavior.prompt); - }); -'Excel.SearchDirection:enum': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-find.yaml + const sheet = context.workbook.worksheets.getItem("Sample"); + const salesTable = sheet.tables.getItem("SalesTable"); + const dataRange = salesTable.getDataBodyRange(); - searchDirectionToggle = searchDirectionToggle === - Excel.SearchDirection.forward ? Excel.SearchDirection.backwards : - Excel.SearchDirection.forward; + // Pass true so only cells with values count as used + const usedDataRange = dataRange.getUsedRangeOrNullObject( + true /* valuesOnly */ + ); - console.log("Search direction = " + searchDirectionToggle); -'Excel.SettableCellProperties#style:member': + //Must sync before reading value returned from *OrNullObject method/property. + await context.sync(); + + if (usedDataRange.isNullObject) { + console.log("Need Data to Make Chart"); + console.log("To create a meaningful chart, press 'Fill the table' (or add names to the Product column and numbers to some of the other cells). Then press 'Try to create chart' again."); + } else { + const chart = sheet.charts.add( + Excel.ChartType.columnClustered, + dataRange, + "Columns" + ); + chart.setPosition("A15", "F30"); + chart.title.text = "Quarterly sales chart"; + chart.legend.position = "Right"; + chart.legend.format.fill.setSolidColor("white"); + chart.dataLabels.format.font.size = 15; + chart.dataLabels.format.font.color = "black"; + } + + await context.sync(); + }); +Excel.Range#set:member(2): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/90-scenarios/multiple-property-set.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); + const sheet = context.workbook.worksheets.getItem("Sample"); - // Creating the SettableCellProperties objects to use for the range. - // In your add-in, these should be created once, outside the function. - const topHeaderProps: Excel.SettableCellProperties = { - // The style property takes a string matching the name of an Excel style. - // Built-in style names are listed in the `BuiltInStyle` enum. - // Note that a style will overwrite any formatting, - // so do not use the format property with the style property. - style: "Heading1" - }; + const sourceRange = sheet.getRange("B2:E2"); + sourceRange.load("format/fill/color, format/font/name, format/font/color"); + await context.sync(); - const headerProps: Excel.SettableCellProperties = { - // Any subproperties of format that are not set will not be changed when these cell properties are set. - format: { - fill: { - color: "Blue" - }, - font: { - color: "White", - bold: true - } - } - }; + // Set properties based on the loaded and synced + // source range. + const targetRange = sheet.getRange("B7:E7"); + targetRange.set(sourceRange); + targetRange.format.autofitColumns(); + await context.sync(); + }); +Excel.RangeAreas#format:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-areas.yaml - const nonApplicableProps: Excel.SettableCellProperties = { - format: { - fill: { - pattern: Excel.FillPattern.gray25 - }, - font: { - color: "Gray", - italic: true - } - } - }; - const matchupScoreProps: Excel.SettableCellProperties = { - format: { - borders: { - bottom: { - style: Excel.BorderLineStyle.continuous - }, - left: { - style: Excel.BorderLineStyle.continuous - }, - right: { - style: Excel.BorderLineStyle.continuous - }, - top: { - style: Excel.BorderLineStyle.continuous - } - } - } - }; + await Excel.run(async (context) => { - const range = sheet.getRange("A1:E5"); + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const usedRange = sheet.getUsedRange(); - // You can use empty JSON objects to avoid changing a cell's properties. - range.setCellProperties([ - [topHeaderProps, {}, {}, {}, {}], - [{}, {}, headerProps, headerProps, headerProps], - [{}, headerProps, nonApplicableProps, matchupScoreProps, matchupScoreProps], - [{}, headerProps, matchupScoreProps, nonApplicableProps, matchupScoreProps], - [{}, headerProps, matchupScoreProps, matchupScoreProps, nonApplicableProps] - ]); + // Find the ranges with formulas. + const formulaRanges = usedRange.getSpecialCells("Formulas"); + formulaRanges.format.fill.color = "lightgreen"; - sheet.getUsedRange().format.autofitColumns(); await context.sync(); }); -'Excel.Setting#delete:member(1)': +Excel.RangeCopyType:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/create-get-change-delete-settings.yaml - - await Excel.run(async (context) => { - const settings = context.workbook.settings; - let needsReview = settings.getItem("NeedsReview"); - needsReview.delete(); - needsReview = settings.getItemOrNullObject("NeedsReview"); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-copyfrom.yaml - await context.sync(); - if (needsReview.isNullObject) { - console.log("The setting has been deleted"); - } else { - console.log("The setting was not deleted"); - } + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + // Place a label in front of the copied data. + sheet.getRange("F2").values = [["Copied Formula"]]; + // Copy a range preserving the formulas. + // Note: non-formula values are copied over as is. + sheet.getRange("G2").copyFrom("A1:E1", Excel.RangeCopyType.formulas); await context.sync(); }); -'Excel.SettingCollection#add:member(1)': +Excel.RangeFormat#textOrientation:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-text-orientation.yaml + await Excel.run(async (context) => { - const settings = context.workbook.settings; - settings.onSettingsChanged.add(onChangedSetting); + const sheet = context.workbook.worksheets.getItem("Sample"); + const range = sheet.getRange("B2:E2"); + + // Set textOrientation to either an integer between -90 and 90 + // or to 180 for vertically-oriented text. + range.format.textOrientation = 90; await context.sync(); - console.log("Settings changed handler registered."); }); -'Excel.SettingCollection#getItemOrNullObject:member(1)': +Excel.RangeHyperlink#address:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/create-get-change-delete-settings.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + await Excel.run(async (context) => { - const settings = context.workbook.settings; - let needsReview = settings.getItem("NeedsReview"); - needsReview.delete(); - needsReview = settings.getItemOrNullObject("NeedsReview"); + const sheet = context.workbook.worksheets.getItem("Orders"); + + let productsRange = sheet.getRange("A3:A5"); + productsRange.load("values"); await context.sync(); - if (needsReview.isNullObject) { - console.log("The setting has been deleted"); - } else { - console.log("The setting was not deleted"); + // Create a hyperlink to a URL + // for each product name in the first table. + for (let i = 0; i < productsRange.values.length; i++) { + let cellRange = productsRange.getCell(i, 0); + let cellText = productsRange.values[i][0]; + + let hyperlink = { + textToDisplay: cellText, + screenTip: "Search Bing for '" + cellText + "'", + address: "https://www.bing.com?q=" + cellText + } + cellRange.hyperlink = hyperlink; } await context.sync(); }); -'Excel.SettingCollection#onSettingsChanged:member': +Excel.RangeHyperlink#documentReference:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + await Excel.run(async (context) => { - const settings = context.workbook.settings; - settings.onSettingsChanged.add(onChangedSetting); + const sheet = context.workbook.worksheets.getItem("Orders"); + + let productsRange = sheet.getRange("A9:A11"); + productsRange.load("values"); + + await context.sync(); + + // Create a hyperlink to a location within the workbook + // for each product name in the second table. + for (let i = 0; i < productsRange.values.length; i++) { + let cellRange = productsRange.getCell(i, 0); + let cellText = productsRange.values[i][0]; + + let hyperlink = { + textToDisplay: cellText, + screenTip: "Navigate to the '" + cellText + "' worksheet", + documentReference: cellText + "!A1" + } + cellRange.hyperlink = hyperlink; + } await context.sync(); - console.log("Settings changed handler registered."); }); -'Excel.Shape#delete:member(1)': +Excel.RangeHyperlink#screenTip:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-create-and-delete.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + await Excel.run(async (context) => { - context.workbook.worksheets.getItemOrNullObject("Shapes").delete(); - const sheet = context.workbook.worksheets.add("Shapes"); + const sheet = context.workbook.worksheets.getItem("Orders"); - const shapes = sheet.shapes; + let productsRange = sheet.getRange("A3:A5"); + productsRange.load("values"); - // load all the shapes in the collection without loading their properties - shapes.load("items/$none"); await context.sync(); - shapes.items.forEach((shape) => shape.delete()); + // Create a hyperlink to a URL + // for each product name in the first table. + for (let i = 0; i < productsRange.values.length; i++) { + let cellRange = productsRange.getCell(i, 0); + let cellText = productsRange.values[i][0]; + + let hyperlink = { + textToDisplay: cellText, + screenTip: "Search Bing for '" + cellText + "'", + address: "https://www.bing.com?q=" + cellText + } + cellRange.hyperlink = hyperlink; + } + await context.sync(); }); -'Excel.Shape#fill:member': +Excel.RangeHyperlink#textToDisplay:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-create-and-delete.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Shapes"); - const shape = sheet.shapes.addGeometricShape(Excel.GeometricShapeType.smileyFace); - shape.left = 300; - shape.top = 100; - shape.height = 100; - shape.width = 100; - shape.fill.foregroundColor = "yellow" + const sheet = context.workbook.worksheets.getItem("Orders"); + + let productsRange = sheet.getRange("A3:A5"); + productsRange.load("values"); + + await context.sync(); + + // Create a hyperlink to a URL + // for each product name in the first table. + for (let i = 0; i < productsRange.values.length; i++) { + let cellRange = productsRange.getCell(i, 0); + let cellText = productsRange.values[i][0]; + + let hyperlink = { + textToDisplay: cellText, + screenTip: "Search Bing for '" + cellText + "'", + address: "https://www.bing.com?q=" + cellText + } + cellRange.hyperlink = hyperlink; + } + await context.sync(); }); -'Excel.Shape#getAsImage:member(1)': +Excel.RangeUnderlineStyle:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-images.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Shapes"); - const shape = sheet.shapes.getItem("Image"); - const result = shape.getAsImage(Excel.PictureFormat.png); + const sheet = context.workbook.worksheets.getItem("Orders"); + + const productsRange = sheet.getRange("A3:A11"); + productsRange.load("values"); + await context.sync(); - const imageString = result.value; - // Your add-in would save this string as a .png file. - console.log("The image's Base64-encoded string: " + imageString); - }); -'Excel.Shape#group:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-groups.yaml + // Clear all hyperlinks. + for (let i = 0; i < productsRange.values.length; i++) { + let cellRange = productsRange.getCell(i, 0); - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Shapes"); + // Clear the hyperlink. + // This removes the hyperlink but does not update text format. + cellRange.clear(Excel.ClearApplyTo.hyperlinks); - const shapeGroup = sheet.shapes.getItem("Group").group; - shapeGroup.ungroup(); - console.log("Shapes ungrouped"); + // Update text format. + cellRange.format.font.underline = Excel.RangeUnderlineStyle.none; + cellRange.format.font.color = "#000000"; + } await context.sync(); }); -'Excel.Shape#incrementLeft:member(1)': +Excel.ReadingOrder:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Shapes"); - const shape = sheet.shapes.getItem("Square") - shape.incrementLeft(-25); + let style = context.workbook.styles.getItem("Diagonal Orientation Style"); + style.load("textOrientation, horizontalAlignment, autoIndent, readingOrder, wrapText, includeProtection, shrinkToFit, locked"); + await context.sync(); + + console.log("Orientation: " + style.textOrientation); + console.log("Horizontal alignment: " + style.horizontalAlignment); + console.log("Add indent: " + style.autoIndent); + console.log("Reading order: " + style.readingOrder); + console.log("Wrap text: " + style.wrapText); + console.log("Include protection: " + style.includeProtection); + console.log("Shrink to fit: " + style.shrinkToFit); + console.log("Style locked: " + style.locked); }); -'Excel.Shape#incrementRotation:member(1)': +Excel.RemoveDuplicatesResult#uniqueRemaining:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-images.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-remove-duplicates.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Shapes"); - const shape = sheet.shapes.getItem("Image"); - shape.incrementRotation(180); + const sheet = context.workbook.worksheets.getItem("Sample"); + const range = sheet.getRange("B2:D11"); + + const deleteResult = range.removeDuplicates([0],true); + deleteResult.load(); await context.sync(); + + console.log(deleteResult.removed + " entries with duplicate names removed."); + console.log(deleteResult.uniqueRemaining + " entries with unique names remain in the range."); }); -'Excel.Shape#incrementTop:member(1)': +Excel.Runtime#enableEvents:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-disable-events.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Shapes"); - const shape = sheet.shapes.getItem("Pentagon") - shape.incrementTop(25); + context.runtime.load("enableEvents"); + await context.sync(); + + // check if events are enabled and toggle accordingly + const eventBoolean = !context.runtime.enableEvents + context.runtime.enableEvents = eventBoolean; + if (eventBoolean) { + console.log("Events are currently on."); + } else { + console.log("Events are currently off."); + } + await context.sync(); }); -'Excel.Shape#line:member': +Excel.SaveBehavior:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-save-and-close.yaml + await Excel.run(async (context) => { - const shapes = context.workbook.worksheets.getItem("Shapes").shapes; - const line = shapes.getItem("StraightLine").line; - line.beginArrowheadLength = Excel.ArrowheadLength.long; - line.beginArrowheadWidth = Excel.ArrowheadWidth.wide; - line.beginArrowheadStyle = Excel.ArrowheadStyle.oval; + context.workbook.save(Excel.SaveBehavior.prompt); + }); +Excel.SearchDirection:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-find.yaml - line.endArrowheadLength = Excel.ArrowheadLength.long; - line.endArrowheadWidth = Excel.ArrowheadWidth.wide; - line.endArrowheadStyle = Excel.ArrowheadStyle.triangle; + searchDirectionToggle = searchDirectionToggle === + Excel.SearchDirection.forward ? Excel.SearchDirection.backwards : + Excel.SearchDirection.forward; + + console.log("Search direction = " + searchDirectionToggle); +Excel.SettableCellProperties#style:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Creating the SettableCellProperties objects to use for the range. + // In your add-in, these should be created once, outside the function. + const topHeaderProps: Excel.SettableCellProperties = { + // The style property takes a string matching the name of an Excel style. + // Built-in style names are listed in the `BuiltInStyle` enum. + // Note that a style will overwrite any formatting, + // so do not use the format property with the style property. + style: "Heading1" + }; + + const headerProps: Excel.SettableCellProperties = { + // Any subproperties of format that are not set will not be changed when these cell properties are set. + format: { + fill: { + color: "Blue" + }, + font: { + color: "White", + bold: true + } + } + }; + + const nonApplicableProps: Excel.SettableCellProperties = { + format: { + fill: { + pattern: Excel.FillPattern.gray25 + }, + font: { + color: "Gray", + italic: true + } + } + }; + + const matchupScoreProps: Excel.SettableCellProperties = { + format: { + borders: { + bottom: { + style: Excel.BorderLineStyle.continuous + }, + left: { + style: Excel.BorderLineStyle.continuous + }, + right: { + style: Excel.BorderLineStyle.continuous + }, + top: { + style: Excel.BorderLineStyle.continuous + } + } + } + }; + + const range = sheet.getRange("A1:E5"); + + // You can use empty JSON objects to avoid changing a cell's properties. + range.setCellProperties([ + [topHeaderProps, {}, {}, {}, {}], + [{}, {}, headerProps, headerProps, headerProps], + [{}, headerProps, nonApplicableProps, matchupScoreProps, matchupScoreProps], + [{}, headerProps, matchupScoreProps, nonApplicableProps, matchupScoreProps], + [{}, headerProps, matchupScoreProps, matchupScoreProps, nonApplicableProps] + ]); + + sheet.getUsedRange().format.autofitColumns(); await context.sync(); }); -'Excel.Shape#lockAspectRatio:member': +Excel.Setting#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/create-get-change-delete-settings.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Shapes"); - const shape = sheet.shapes.getItem("Octagon") - shape.lockAspectRatio = true; - shape.scaleHeight(1.25, Excel.ShapeScaleType.currentSize); + const settings = context.workbook.settings; + let needsReview = settings.getItem("NeedsReview"); + needsReview.delete(); + needsReview = settings.getItemOrNullObject("NeedsReview"); + + await context.sync(); + + if (needsReview.isNullObject) { + console.log("The setting has been deleted"); + } else { + console.log("The setting was not deleted"); + } + await context.sync(); }); -'Excel.Shape#rotation:member': +Excel.SettingCollection#add:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-create-and-delete.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Shapes"); - const shape = sheet.shapes.addGeometricShape(Excel.GeometricShapeType.triangle); - shape.left = 100; - shape.top = 300; - shape.height = 150; - shape.width = 200; - shape.rotation = 45; - shape.fill.clear(); + const settings = context.workbook.settings; + settings.onSettingsChanged.add(onChangedSetting); + await context.sync(); + console.log("Settings changed handler registered."); }); -'Excel.Shape#scaleHeight:member(1)': +Excel.SettingCollection#onSettingsChanged:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Shapes"); - const shape = sheet.shapes.getItem("Octagon") - shape.lockAspectRatio = true; - shape.scaleHeight(1.25, Excel.ShapeScaleType.currentSize); + const settings = context.workbook.settings; + settings.onSettingsChanged.add(onChangedSetting); + await context.sync(); + console.log("Settings changed handler registered."); }); -'Excel.Shape#setZOrder:member(1)': +Excel.SettingCollection#getItemOrNullObject:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/create-get-change-delete-settings.yaml + await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Shapes"); - const shape = sheet.shapes.getItem("Octagon") - shape.setZOrder(Excel.ShapeZOrder.sendBackward); + const settings = context.workbook.settings; + let needsReview = settings.getItem("NeedsReview"); + needsReview.delete(); + needsReview = settings.getItemOrNullObject("NeedsReview"); + + await context.sync(); + + if (needsReview.isNullObject) { + console.log("The setting has been deleted"); + } else { + console.log("The setting was not deleted"); + } + await context.sync(); }); -'Excel.ShapeAutoSize:enum': +Excel.Shape#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-textboxes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-create-and-delete.yaml + await Excel.run(async (context) => { - const shapes = context.workbook.worksheets.getItem("Shapes").shapes; - const textbox = shapes.getItem("Textbox"); - textbox.textFrame.autoSizeSetting = Excel.ShapeAutoSize.autoSizeShapeToFitText; + context.workbook.worksheets.getItemOrNullObject("Shapes").delete(); + const sheet = context.workbook.worksheets.add("Shapes"); + + const shapes = sheet.shapes; + + // load all the shapes in the collection without loading their properties + shapes.load("items/$none"); + await context.sync(); + + shapes.items.forEach((shape) => shape.delete()); await context.sync(); }); -'Excel.ShapeCollection#addGeometricShape:member(1)': +Excel.Shape#fill:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-create-and-delete.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Shapes"); - const shape = sheet.shapes.addGeometricShape(Excel.GeometricShapeType.hexagon); - shape.left = 5; - shape.top = 5; - shape.height = 175; - shape.width = 200; + const shape = sheet.shapes.addGeometricShape(Excel.GeometricShapeType.smileyFace); + shape.left = 300; + shape.top = 100; + shape.height = 100; + shape.width = 100; + shape.fill.foregroundColor = "yellow" await context.sync(); }); -'Excel.ShapeCollection#addGroup:member(1)': +Excel.Shape#rotation:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-groups.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-create-and-delete.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Shapes"); - const square = sheet.shapes.getItem("Square"); - const pentagon = sheet.shapes.getItem("Pentagon"); - const octagon = sheet.shapes.getItem("Octagon"); - - const shapeGroup = sheet.shapes.addGroup([square, pentagon, octagon]); - shapeGroup.name = "Group"; - console.log("Shapes grouped"); - + const shape = sheet.shapes.addGeometricShape(Excel.GeometricShapeType.triangle); + shape.left = 100; + shape.top = 300; + shape.height = 150; + shape.width = 200; + shape.rotation = 45; + shape.fill.clear(); await context.sync(); }); -'Excel.ShapeCollection#addImage:member(1)': +Excel.Shape#group:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-images.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-groups.yaml - const myFile = document.getElementById("selectedFile"); - const reader = new FileReader(); + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Shapes"); + + const shapeGroup = sheet.shapes.getItem("Group").group; + shapeGroup.ungroup(); + console.log("Shapes ungrouped"); + + await context.sync(); + }); +Excel.Shape#getAsImage:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-images.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Shapes"); + const shape = sheet.shapes.getItem("Image"); + const result = shape.getAsImage(Excel.PictureFormat.png); + await context.sync(); + + const imageString = result.value; + // Your add-in would save this string as a .png file. + console.log("The image's Base64-encoded string: " + imageString); + }); +Excel.Shape#incrementRotation:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-images.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Shapes"); + const shape = sheet.shapes.getItem("Image"); + shape.incrementRotation(180); + await context.sync(); + }); +Excel.Shape#line:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml + + + await Excel.run(async (context) => { + const shapes = context.workbook.worksheets.getItem("Shapes").shapes; + const line = shapes.getItem("StraightLine").line; + line.beginArrowheadLength = Excel.ArrowheadLength.long; + line.beginArrowheadWidth = Excel.ArrowheadWidth.wide; + line.beginArrowheadStyle = Excel.ArrowheadStyle.oval; + + line.endArrowheadLength = Excel.ArrowheadLength.long; + line.endArrowheadWidth = Excel.ArrowheadWidth.wide; + line.endArrowheadStyle = Excel.ArrowheadStyle.triangle; + + await context.sync(); + }); +Excel.Shape#incrementLeft:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Shapes"); + const shape = sheet.shapes.getItem("Square") + shape.incrementLeft(-25); + await context.sync(); + }); +Excel.Shape#incrementTop:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Shapes"); + const shape = sheet.shapes.getItem("Pentagon") + shape.incrementTop(25); + await context.sync(); + }); +Excel.Shape#lockAspectRatio:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Shapes"); + const shape = sheet.shapes.getItem("Octagon") + shape.lockAspectRatio = true; + shape.scaleHeight(1.25, Excel.ShapeScaleType.currentSize); + await context.sync(); + }); +Excel.Shape#scaleHeight:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Shapes"); + const shape = sheet.shapes.getItem("Octagon") + shape.lockAspectRatio = true; + shape.scaleHeight(1.25, Excel.ShapeScaleType.currentSize); + await context.sync(); + }); +Excel.Shape#setZOrder:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Shapes"); + const shape = sheet.shapes.getItem("Octagon") + shape.setZOrder(Excel.ShapeZOrder.sendBackward); + await context.sync(); + }); +Excel.ShapeAutoSize:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-textboxes.yaml + + + await Excel.run(async (context) => { + const shapes = context.workbook.worksheets.getItem("Shapes").shapes; + const textbox = shapes.getItem("Textbox"); + textbox.textFrame.autoSizeSetting = Excel.ShapeAutoSize.autoSizeShapeToFitText; + await context.sync(); + }); +Excel.ShapeCollection#addGeometricShape:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-create-and-delete.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Shapes"); + const shape = sheet.shapes.addGeometricShape(Excel.GeometricShapeType.hexagon); + shape.left = 5; + shape.top = 5; + shape.height = 175; + shape.width = 200; + await context.sync(); + }); +Excel.ShapeCollection#addGroup:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-groups.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Shapes"); + const square = sheet.shapes.getItem("Square"); + const pentagon = sheet.shapes.getItem("Pentagon"); + const octagon = sheet.shapes.getItem("Octagon"); + + const shapeGroup = sheet.shapes.addGroup([square, pentagon, octagon]); + shapeGroup.name = "Group"; + console.log("Shapes grouped"); + + await context.sync(); + }); +Excel.ShapeCollection#addImage:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-images.yaml + + + const myFile = document.getElementById("selectedFile") as HTMLInputElement; + + const reader = new FileReader(); reader.onload = (event) => { @@ -6021,22 +7278,24 @@ // Read in the image file as a data URL. reader.readAsDataURL(myFile.files[0]); -'Excel.ShapeCollection#addLine:member(1)': +Excel.ShapeCollection#addLine:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml + await Excel.run(async (context) => { const shapes = context.workbook.worksheets.getItem("Shapes").shapes; const line = shapes.addLine(200, 50, 300, 150, Excel.ConnectorType.straight); line.name = "StraightLine"; await context.sync(); }); -'Excel.ShapeCollection#addTextBox:member(1)': +Excel.ShapeCollection#addTextBox:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-textboxes.yaml + await Excel.run(async (context) => { const shapes = context.workbook.worksheets.getItem("Shapes").shapes; const textbox = shapes.addTextBox("A box with text"); @@ -6047,11 +7306,12 @@ textbox.name = "Textbox"; await context.sync(); }); -'Excel.ShapeGroup#ungroup:member(1)': +Excel.ShapeGroup#ungroup:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-groups.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Shapes"); @@ -6061,11 +7321,12 @@ await context.sync(); }); -'Excel.ShapeScaleType:enum': +Excel.ShapeScaleType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Shapes"); const shape = sheet.shapes.getItem("Octagon") @@ -6073,33 +7334,36 @@ shape.scaleHeight(1.25, Excel.ShapeScaleType.currentSize); await context.sync(); }); -'Excel.ShapeTextHorizontalAlignment:enum': +Excel.ShapeTextHorizontalAlignment:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-textboxes.yaml + await Excel.run(async (context) => { const shapes = context.workbook.worksheets.getItem("Shapes").shapes; const textbox = shapes.getItem("Textbox"); textbox.textFrame.horizontalAlignment = Excel.ShapeTextHorizontalAlignment.center; await context.sync(); }); -'Excel.ShapeZOrder:enum': +Excel.ShapeZOrder:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Shapes"); const shape = sheet.shapes.getItem("Octagon") shape.setZOrder(Excel.ShapeZOrder.sendBackward); await context.sync(); }); -'Excel.SheetVisibility:enum': +Excel.SheetVisibility:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-visibility.yaml + await Excel.run(async (context) => { const visibleSheets = await filterWorksheetsByVisibility(context, Excel.SheetVisibility.visible); @@ -6115,11 +7379,12 @@ console.log("Cannot hide the only visible worksheet"); } }); -'Excel.ShowAsCalculation:enum': +Excel.ShowAsCalculation:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-calculations.yaml + await Excel.run(async (context) => { const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); const farmDataHierarchy: Excel.DataPivotHierarchy = pivotTable.dataHierarchies.getItem("Sum of Crates Sold at Farm"); @@ -6141,11 +7406,12 @@ wholesaleDataHierarchy.showAs = wholesaleShowAs; await context.sync(); }); -'Excel.ShowAsRule#baseItem:member': +Excel.ShowAsRule#baseItem:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-calculations.yaml + await Excel.run(async (context) => { const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); const farmDataHierarchy: Excel.DataPivotHierarchy = pivotTable.dataHierarchies.getItem("Sum of Crates Sold at Farm"); @@ -6170,51 +7436,56 @@ wholesaleDataHierarchy.showAs = wholesaleShowAs; await context.sync(); }); -'Excel.Slicer#clearFilters:member(1)': +Excel.Slicer#clearFilters:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-slicer.yaml + await Excel.run(async (context) => { const slicer = context.workbook.slicers.getItem("Fruit Slicer"); slicer.clearFilters(); await context.sync(); }); -'Excel.Slicer#delete:member(1)': +Excel.Slicer#delete:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-slicer.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); sheet.slicers.getItemAt(0).delete(); await context.sync(); }); -'Excel.Slicer#selectItems:member(1)': +Excel.Slicer#selectItems:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-slicer.yaml + await Excel.run(async (context) => { const slicer = context.workbook.slicers.getItem("Fruit Slicer"); slicer.selectItems(["Lemon", "Lime", "Orange"]); await context.sync(); }); -'Excel.Slicer#style:member': +Excel.Slicer#style:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-slicer.yaml + await Excel.run(async (context) => { const slicer = context.workbook.slicers.getItem("Fruit Slicer"); slicer.style = "SlicerStyleLight6"; await context.sync(); }); -'Excel.SlicerCollection#add:member(1)': +Excel.SlicerCollection#add:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-slicer.yaml + await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Pivot"); const slicer = sheet.slicers.add( @@ -6224,11 +7495,12 @@ slicer.name = "Fruit Slicer"; await context.sync(); }); -'Excel.SlicerCollection#getItem:member(1)': +Excel.SlicerCollection#getItem:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-slicer.yaml + await Excel.run(async (context) => { const slicer = context.workbook.slicers.getItem("Fruit Slicer"); slicer.caption = "Fruit Types"; @@ -6238,11 +7510,12 @@ slicer.width = 150; await context.sync(); }); -'Excel.SortOn:enum': +Excel.SortOn:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-column-and-row-sort.yaml + async function sortTopToBottom(criteria: string) { await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -6267,11 +7540,12 @@ await context.sync(); }); } -'Excel.SortOrientation:enum': +Excel.SortOrientation:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-column-and-row-sort.yaml + async function sortLeftToRight(criteria: string) { await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); @@ -6296,11 +7570,12 @@ await context.sync(); }); } -'CustomFunctions.StreamingInvocation#setResult:member': +CustomFunctions.StreamingInvocation#setResult:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/16-custom-functions/streaming-function.yaml + /** @CustomFunction * @description Increments the cell with a given amount at a specified interval in milliseconds. * @param {number} amount - The amount to add to the cell value on each increment. @@ -6321,11 +7596,12 @@ clearInterval(timer); } } -'Excel.Style#delete:member(1)': +Excel.Style#delete:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + await Excel.run(async (context) => { let style = context.workbook.styles.getItem("Diagonal Orientation Style"); @@ -6337,7632 +7613,17341 @@ console.log("Successfully deleted the diagonal orientation style from the Home tab ribbon."); }); -'Excel.Style#font:member': +Excel.Style#font:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + + + await Excel.run(async (context) => { + let style = context.workbook.styles.getItem("Normal"); + style.font.load("bold, color, italic, name, size"); + style.fill.load("color"); + + await context.sync(); + + console.log("Bold: " + style.font.bold); + console.log("Font color: " + style.font.color); + console.log("Italic: " + style.font.italic); + console.log("Name: " + style.font.name); + console.log("Size: " + style.font.size); + console.log("Fill color: " + style.fill.color); + }); +Excel.Style#horizontalAlignment:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + + + await Excel.run(async (context) => { + let worksheet = context.workbook.worksheets.getItem("Sample"); + let range = worksheet.getRange("A1:E1"); + + // Apply built-in style. + // Styles are in the Home tab ribbon. + range.style = Excel.BuiltInStyle.neutral; + range.format.horizontalAlignment = "Right"; + + await context.sync(); + }); +Excel.Style#load:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + + + await Excel.run(async (context) => { + let style = context.workbook.styles.getItem("Diagonal Orientation Style"); + style.load("textOrientation, horizontalAlignment, autoIndent, readingOrder, wrapText, includeProtection, shrinkToFit, locked"); + + await context.sync(); + + console.log("Orientation: " + style.textOrientation); + console.log("Horizontal alignment: " + style.horizontalAlignment); + console.log("Add indent: " + style.autoIndent); + console.log("Reading order: " + style.readingOrder); + console.log("Wrap text: " + style.wrapText); + console.log("Include protection: " + style.includeProtection); + console.log("Shrink to fit: " + style.shrinkToFit); + console.log("Style locked: " + style.locked); + }); +Excel.StyleCollection#add:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + + + await Excel.run(async (context) => { + let styles = context.workbook.styles; + + // Add a new style to the style collection. + // Styles is in the Home tab ribbon. + styles.add("Diagonal Orientation Style"); + + let newStyle = styles.getItem("Diagonal Orientation Style"); + + // The "Diagonal Orientation Style" properties. + newStyle.textOrientation = 38; + newStyle.autoIndent = true; + newStyle.includeProtection = true; + newStyle.shrinkToFit = true; + newStyle.locked = false; + + await context.sync(); + + console.log("Successfully added a new style with diagonal orientation to the Home tab ribbon."); + }); +Excel.StyleCollection#getItem:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + + + await Excel.run(async (context) => { + let styles = context.workbook.styles; + + // Add a new style to the style collection. + // Styles is in the Home tab ribbon. + styles.add("Diagonal Orientation Style"); + + let newStyle = styles.getItem("Diagonal Orientation Style"); + + // The "Diagonal Orientation Style" properties. + newStyle.textOrientation = 38; + newStyle.autoIndent = true; + newStyle.includeProtection = true; + newStyle.shrinkToFit = true; + newStyle.locked = false; + + await context.sync(); + + console.log("Successfully added a new style with diagonal orientation to the Home tab ribbon."); + }); +Excel.Table#onChanged:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-table-changed.yaml + + + await Excel.run(async (context) => { + let table = context.workbook.tables.getItemAt(0); + table.onChanged.add(onChange); + + await context.sync(); + console.log("A handler has been registered for the onChanged event"); + }); +Excel.Table#onSelectionChanged:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-table-changed.yaml + + + await Excel.run(async (context) => { + let table = context.workbook.tables.getItemAt(0); + table.onSelectionChanged.add(onSelectionChange); + + await context.sync(); + console.log("A handler has been registered for table onSelectionChanged event"); + }); +Excel.Table#resize:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/46-table/resize-table.yaml + + + await Excel.run(async (context) => { + // Retrieve the worksheet and a table on that worksheet. + const sheet = context.workbook.worksheets.getItem("Sample"); + const expensesTable = sheet.tables.getItem("ExpensesTable"); + + // Resize the table. + expensesTable.resize("A1:D20"); + + await context.sync(); + }); +Excel.TableChangedEventArgs#details:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/data-change-event-details.yaml + + + async function onTableChanged(eventArgs: Excel.TableChangedEventArgs) { + await Excel.run(async (context) => { + const details = eventArgs.details; + const address = eventArgs.address; + + console.log(`Change at ${address}: was ${details.valueBefore}(${details.valueTypeBefore}),` + + ` now is ${details.valueAfter}(${details.valueTypeAfter})`); + }); + } +Excel.TableChangedEventArgs#tableId:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-tablecollection-changed.yaml + + + async function onChange(event) { + await Excel.run(async (context) => { + let table = context.workbook.tables.getItem(event.tableId); + let worksheet = context.workbook.worksheets.getItem(event.worksheetId); + worksheet.load("name"); + + await context.sync(); + + console.log("Handler for table collection onChanged event has been triggered. Data changed address: " + event.address); + console.log("Table Id : " + event.tableId); + console.log("Worksheet Id : " + worksheet.name); + }); + } +Excel.TableChangedEventArgs#worksheetId:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-tablecollection-changed.yaml + + + async function onChange(event) { + await Excel.run(async (context) => { + let table = context.workbook.tables.getItem(event.tableId); + let worksheet = context.workbook.worksheets.getItem(event.worksheetId); + worksheet.load("name"); + + await context.sync(); + + console.log("Handler for table collection onChanged event has been triggered. Data changed address: " + event.address); + console.log("Table Id : " + event.tableId); + console.log("Worksheet Id : " + worksheet.name); + }); + } +Excel.TableCollection:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml + + + // Add checkboxes to the table. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Get the second column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Change the boolean values to checkboxes. + range.control = { + type: Excel.CellControlType.checkbox + }; + await context.sync(); + }); +Excel.TableCollection#getItem:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml + + + // Remove checkboxes from the table. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Get the second column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Change the checkboxes back to boolean values. + range.control = { + type: Excel.CellControlType.empty + }; + await context.sync(); + }); +Excel.TableCollection#onChanged:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-tablecollection-changed.yaml + + + await Excel.run(async (context) => { + let tables = context.workbook.tables; + tables.onChanged.add(onChange); + + await context.sync(); + console.log("A handler has been registered for the table collection onChanged event"); + }); +Excel.TableColumn#getDataBodyRange:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml + + + // Add checkboxes to the table. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Get the second column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Change the boolean values to checkboxes. + range.control = { + type: Excel.CellControlType.checkbox + }; + await context.sync(); + }); +Excel.TableColumnCollection:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml + + + // Add checkboxes to the table. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Get the second column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Change the boolean values to checkboxes. + range.control = { + type: Excel.CellControlType.checkbox + }; + await context.sync(); + }); +Excel.TableColumnCollection#getItem:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml + + + // Remove all content from the Analysis column. + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Get the second column in the table, without the header. + const range = sheet.tables.getItem("FruitTable").columns.getItem("Analysis").getDataBodyRange(); + + // Clear all the data from the second column. + range.clearOrResetContents(); + await context.sync(); + }); +Excel.TableSelectionChangedEventArgs#address:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-table-changed.yaml + + + async function onSelectionChange(args) { + await Excel.run(async (context) => { + console.log("Handler for table onSelectionChanged event has been triggered. The new selection is: " + args.address); + }); + } +Excel.TextConditionalFormat#format:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + const range = sheet.getRange("B16:D18"); + const conditionalFormat = range.conditionalFormats + .add(Excel.ConditionalFormatType.containsText); + conditionalFormat.textComparison.format.font.color = "red"; + conditionalFormat.textComparison.rule = { operator: Excel.ConditionalTextOperator.contains, text: "Delayed" }; + + await context.sync(); + }); +Excel.TextConditionalFormat#rule:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + const range = sheet.getRange("B16:D18"); + const conditionalFormat = range.conditionalFormats + .add(Excel.ConditionalFormatType.containsText); + conditionalFormat.textComparison.format.font.color = "red"; + conditionalFormat.textComparison.rule = { operator: Excel.ConditionalTextOperator.contains, text: "Delayed" }; + + await context.sync(); + }); +Excel.TextFrame#deleteText:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-textboxes.yaml + + + await Excel.run(async (context) => { + const shapes = context.workbook.worksheets.getItem("Shapes").shapes; + const textbox = shapes.getItem("Textbox"); + textbox.textFrame.deleteText(); + await context.sync(); + }); +Excel.ValueFilterCondition:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotfilters.yaml + + + await Excel.run(async (context) => { + // Add a PivotFilter to filter on the values correlated with a row. + + // Get the PivotTable. + const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); + + // Get the "Farm" field. + const field = pivotTable.hierarchies.getItem("Farm").fields.getItem("Farm"); + + // Filter to only include rows with more than 500 wholesale crates sold. + const filter: Excel.PivotValueFilter = { + condition: Excel.ValueFilterCondition.greaterThan, + comparator: 500, + value: "Sum of Crates Sold Wholesale" + }; + + // Apply the value filter to the field. + field.applyFilter({ valueFilter: filter }); + + await context.sync(); + }); +Excel.VerticalAlignment:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + + + await Excel.run(async (context) => { + let worksheet = context.workbook.worksheets.getItem("Sample"); + let range = worksheet.getRange("A1:E1"); + // Apply new style. + range.style = ("Diagonal Orientation Style"); + range.format.verticalAlignment = "Justify"; + + await context.sync(); + }); +Excel.WebImageCellValue#address:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-web-image.yaml + + + // This function retrieves the image URL from the selected cell and opens + that image in a new browser tab. + + await Excel.run(async (context) => { + // Load the active cell information. + const activeCell = context.workbook.getActiveCell(); + activeCell.load("valuesAsJson"); + await context.sync(); + + // Get image URL from the active cell. + const values = activeCell.valuesAsJson; + const webImageData = values[0][0] as Excel.WebImageCellValue; + const webImageUrl = webImageData.address; + + if (!webImageUrl) { + console.log("The selected cell is missing an image URL. Select a cell that contains an image."); + return; + } + + // Open the image URL in a new browser tab. + const tab = window.open(webImageData.address, "_blank"); + }); +Excel.WebImageCellValue#type:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-web-image.yaml + + + // This function inserts a web image into the currently selected cell. + + await Excel.run(async (context) => { + // Retrieve image data from the task pane and then clear the input fields. + const imageUrl = (document.getElementById("url") as HTMLInputElement).value; + const imageAltText = (document.getElementById("alt-text") as HTMLInputElement).value; + clearForm(); + + // Load the active cell. + const activeCell = context.workbook.getActiveCell(); + activeCell.load(); + await context.sync(); + + if (!imageUrl) { + console.log("Please enter an image URL."); + return; + } + + // Create a web image object and assign the image details. + const webImage: Excel.WebImageCellValue = { + type: "WebImage", /* The string equivalent of `Excel.CellValueType.webImage`. */ + address: imageUrl, + altText: imageAltText + }; + + // Insert web image into the active cell. + activeCell.valuesAsJson = [[webImage]]; + + await context.sync(); + }); +Excel.Workbook#properties:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/26-document/properties.yaml + + + await Excel.run(async (context) => { + let titleValue = "Excel document properties API"; + let subjectValue = "Set and get document properties"; + let keywordsValue = "Set and get operations"; + let commentsValue = "This is an Excel document properties API code sample"; + let categoryValue = "Office Add-ins"; + let managerValue = "John"; + let companyValue = "Microsoft"; + + let docProperties = context.workbook.properties; + + // Set the writeable document properties. + docProperties.title = titleValue; + docProperties.subject = subjectValue; + docProperties.keywords = keywordsValue; + docProperties.comments = commentsValue; + docProperties.category = categoryValue; + docProperties.manager = managerValue; + docProperties.company = companyValue; + + await context.sync(); + + console.log("Set the following document properties: title, subject, keywords, comments, category, manager, company."); + }); +Excel.Workbook#onActivated:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-activated.yaml + + + async function workbookActivated(event: Excel.WorkbookActivatedEventArgs) { + await Excel.run(async (context) => { + // Callback function for when the workbook is activated. + console.log("The workbook was activated."); + }); + } + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-activated.yaml + + + await Excel.run(async (context) => { + const workbook = context.workbook; + + // Register the workbook activated event handler. + workbook.onActivated.add(workbookActivated); + + await context.sync(); + console.log("Added event handler for workbook activated."); + }); +Excel.Workbook#pivotTables:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-get-pivottables.yaml + + + await Excel.run(async (context) => { + // Get the names of all the PivotTables in the workbook. + const pivotTables = context.workbook.pivotTables; + pivotTables.load("name"); + await context.sync(); + + // Display the names in the console. + console.log("PivotTables in the workbook:") + pivotTables.items.forEach((pivotTable) => { + console.log(`\t${pivotTable.name}`); + }); + }); +Excel.Workbook#getSelectedRanges:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-areas.yaml + + + await Excel.run(async (context) => { + + const selectedRanges = context.workbook.getSelectedRanges(); + selectedRanges.format.fill.color = "lightblue"; + + await context.sync(); + }) +Excel.Workbook#styles:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + + + await Excel.run(async (context) => { + let styles = context.workbook.styles; + + // Add a new style to the style collection. + // Styles is in the Home tab ribbon. + styles.add("Diagonal Orientation Style"); + + let newStyle = styles.getItem("Diagonal Orientation Style"); + + // The "Diagonal Orientation Style" properties. + newStyle.textOrientation = 38; + newStyle.autoIndent = true; + newStyle.includeProtection = true; + newStyle.shrinkToFit = true; + newStyle.locked = false; + + await context.sync(); + + console.log("Successfully added a new style with diagonal orientation to the Home tab ribbon."); + }); +Excel.Workbook#getActiveShapeOrNullObject:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-get-active.yaml + + + // This method gets the active shape and displays it as an image in the task + pane. + + await Excel.run(async (context) => { + // Get the currently active shape, if any. + const activeShape = context.workbook.getActiveShapeOrNullObject(); + + if (activeShape) { + // Convert the active shape to an image. + const shapeImage = activeShape.getAsImage(Excel.PictureFormat.png); + await context.sync(); + + // Display the image in the task pane. + const imageContainer = document.getElementById("image"); + imageContainer.innerHTML = ''; // Clear the container before adding a new image. + const imageElement = document.createElement("img"); + imageElement.src = "data:image/png;base64," + shapeImage.value; + imageContainer.appendChild(imageElement); + } else { + console.log("No active shape"); + } + }); +Excel.Workbook#getActiveCell:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-get-active-cell.yaml + + + await Excel.run(async (context) => { + + let myWorkbook = context.workbook; + let activeCell = myWorkbook.getActiveCell(); + activeCell.load("address"); + + await context.sync(); + + console.log("The active cell is " + activeCell.address); + }); +Excel.Workbook#insertWorksheetsFromBase64:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-insert-external-worksheets.yaml + + + // Retrieve the file and set up an HTML FileReader element. + + const myFile = document.getElementById("file") as HTMLInputElement; + + const reader = new FileReader(); + + + reader.onload = (event) => { + // Remove the metadata before the Base64-encoded string. + const startIndex = reader.result.toString().indexOf("base64,"); + externalWorkbook = reader.result.toString().substr(startIndex + 7); + }; + + + // Read the file as a data URL so that we can parse the Base64-encoded + string. + + reader.readAsDataURL(myFile.files[0]); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-insert-external-worksheets.yaml + + + await Excel.run(async (context) => { + // Retrieve the source workbook. + const workbook = context.workbook; + + // Set up the insert options. + const options = { + sheetNamesToInsert: [], // Insert all the worksheets from the source workbook. + positionType: Excel.WorksheetPositionType.after, // Insert after the `relativeTo` sheet. + relativeTo: "Sheet1" // The sheet relative to which the other worksheets will be inserted. Used with `positionType`. + }; + + // Insert the new worksheets. + workbook.insertWorksheetsFromBase64(externalWorkbook, options); + await context.sync(); + }); +Excel.Workbook#close:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-save-and-close.yaml + + + await Excel.run(async (context) => { + context.workbook.close(Excel.CloseBehavior.save); + }); +Excel.Workbook#save:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-save-and-close.yaml + + + await Excel.run(async (context) => { + context.workbook.save(Excel.SaveBehavior.save); + }); +Excel.WorkbookProtection#protect:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/data-protection.yaml + + + let password = await passwordHandler(); + + passwordHelper(password); + + await Excel.run(async (context) => { + let workbook = context.workbook; + workbook.load("protection/protected"); + + await context.sync(); + + if (!workbook.protection.protected) { + workbook.protection.protect(password); + } + }); +Excel.WorkbookProtection#unprotect:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/data-protection.yaml + + + let password = await passwordHandler(); + + passwordHelper(password); + + await Excel.run(async (context) => { + let workbook = context.workbook; + workbook.protection.unprotect(password); + }); +Excel.WorkbookRangeAreas#areas:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/precedents.yaml + + + await Excel.run(async (context) => { + // Precedents are cells referenced by the formula in a cell. + // A "direct precedent" is a cell directly referenced by the selected formula. + let range = context.workbook.getActiveCell(); + let directPrecedents = range.getDirectPrecedents(); + range.load("address"); + directPrecedents.areas.load("address"); + await context.sync(); + + console.log(`Direct precedent cells of ${range.address}:`); + + // Use the direct precedents API to loop through precedents of the active cell. + for (let i = 0; i < directPrecedents.areas.items.length; i++) { + // Highlight and console the address of each precedent cell. + directPrecedents.areas.items[i].format.fill.color = "Yellow"; + console.log(` ${directPrecedents.areas.items[i].address}`); + } + await context.sync(); + }); +Excel.Worksheet#customProperties:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/26-document/custom-properties.yaml + + + await Excel.run(async (context) => { + // Load the keys and values of all custom properties in the current worksheet. + const customWorksheetProperties = context.workbook.worksheets.getActiveWorksheet().customProperties; + customWorksheetProperties.load(["key", "value"]); + await context.sync(); + + // Log each custom property to the console. + // Note that your document may have more properties than those you have set using this snippet. + customWorksheetProperties.items.forEach((property) => { + console.log(`${property.key}:${property.value}`); + }); + }); +Excel.Worksheet#onColumnSorted:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-column-and-row-sort.yaml + + + await Excel.run(async (context) => { + console.log("Adding column handler"); + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // This will fire whenever a column has been moved as the result of a sort action. + sheet.onColumnSorted.add((event) => { + return Excel.run((context) => { + console.log("Column sorted: " + event.address); + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Clear formatting for section, then highlight the sorted area. + sheet.getRange("A1:E5").format.fill.clear(); + if (event.address !== "") { + sheet.getRanges(event.address).format.fill.color = "yellow"; + } + + return context.sync(); + }); + }); + }); +Excel.Worksheet#onRowSorted:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-column-and-row-sort.yaml + + + await Excel.run(async (context) => { + console.log("Adding row handler"); + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // This will fire whenever a row has been moved as the result of a sort action. + sheet.onRowSorted.add((event) => { + return Excel.run((context) => { + console.log("Row sorted: " + event.address); + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // Clear formatting for section, then highlight the sorted area. + sheet.getRange("A1:E5").format.fill.clear(); + if (event.address !== "") { + sheet.getRanges(event.address).format.fill.color = "yellow"; + } + + return context.sync(); + }); + }); + }); +Excel.Worksheet#onSingleClicked:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-worksheet-single-click.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + sheet.onSingleClicked.add((event) => { + return Excel.run((context) => { + console.log(`Click detected at ${event.address} (pixel offset from upper-left cell corner: ${event.offsetX}, ${event.offsetY})`); + return context.sync(); + }); + }); + + console.log("The worksheet click handler is registered."); + + await context.sync(); + }); +Excel.Worksheet#onFormulaChanged:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-formula-changed.yaml + + + await Excel.run(async (context) => { + // Retrieve the worksheet named "Sample". + let sheet = context.workbook.worksheets.getItem("Sample"); + + // Register the formula changed event handler for this worksheet. + sheet.onFormulaChanged.add(formulaChangeHandler); + await context.sync(); + + console.log("Registered a formula changed event handler for this worksheet."); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-formula-changed.yaml + + + async function formulaChangeHandler(event: + Excel.WorksheetFormulaChangedEventArgs) { + await Excel.run(async (context) => { + // Retrieve details about the formula change event. + const cellAddress = event.formulaDetails[0].cellAddress; + const previousFormula = event.formulaDetails[0].previousFormula; + const source = event.source; + + // Print out the change event details. + console.log( + `The formula in cell ${cellAddress} changed. + The previous formula was: ${previousFormula}. + The source of the change was: ${source}.` + ); + }); + } +Excel.Worksheet#onChanged:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet.yaml + + + await Excel.run(async (context) => { + let sheet = context.workbook.worksheets.getItem("Sample"); + sheet.onChanged.add(onChange); + await context.sync(); + + console.log("Added a worksheet-level data-changed event handler."); + }); +Excel.Worksheet#onProtectionChanged:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet-protection.yaml + + + // This function registers an event handler for the onProtectionChanged + event of a worksheet. + + await Excel.run(async (context) => { + // Set "Sample" as the active worksheet. + context.workbook.worksheets.getItemOrNullObject("Sample").delete(); + const sheet = context.workbook.worksheets.add("Sample"); + sheet.activate(); + + // Register the onProtectionChanged event handler. + sheet.onProtectionChanged.add(checkProtection); + await context.sync(); + console.log("Added a worksheet protection change event handler."); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet-protection.yaml + + + async function checkProtection(event: + Excel.WorksheetProtectionChangedEventArgs) { + // This function is an event handler that returns the protection status of a worksheet + // and information about the changed worksheet. + await Excel.run(async (context) => { + const protectionStatus = event.isProtected; + const worksheetId = event.worksheetId; + const source = event.source; + console.log("Protection status changed. Protection status is now: " + protectionStatus + "."); + console.log(" ID of changed worksheet: " + worksheetId + "."); + console.log(" Source of change event: " + source + "."); + }); + } +Excel.Worksheet#showOutlineLevels:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/outline.yaml + + + Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + + // This shows the top 3 outline levels; collapsing any additional sublevels. + sheet.showOutlineLevels(3, 3); + await context.sync(); + }); +Excel.Worksheet#slicers:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-slicer.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Pivot"); + const slicer = sheet.slicers.add( + "Farm Sales", /* The slicer data source. For PivotTables, this can be the PivotTable object reference or name. */ + "Type" /* The field in the data source to filter by. For PivotTables, this can be a PivotField object reference or ID. */ + ); + slicer.name = "Fruit Slicer"; + await context.sync(); + }); +Excel.Worksheet#pivotTables:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-get-pivottables.yaml + + + await Excel.run(async (context) => { + // Get the names of all the PivotTables in the current worksheet. + const pivotTables = context.workbook.worksheets.getActiveWorksheet().pivotTables; + pivotTables.load("name"); + await context.sync(); + + // Display the names in the console. + console.log("PivotTables in the current worksheet:") + pivotTables.items.forEach((pivotTable) => { + console.log(`\t${pivotTable.name}`); + }); + }); +Excel.Worksheet#getRanges:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-areas.yaml + + + await Excel.run(async (context) => { + + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const specifiedRanges = sheet.getRanges("D3:D5, G3:G5"); + specifiedRanges.format.fill.color = "pink"; + + await context.sync(); + }) +Excel.Worksheet#autoFilter:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-auto-filter.yaml + + + // This function adds a percentage AutoFilter to the active worksheet + + // and applies the filter to a column of the used range. + + await Excel.run(async (context) => { + // Retrieve the active worksheet and the used range on that worksheet. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const farmData = sheet.getUsedRange(); + + // Add a filter that will only show the rows with the top 50% of values in column 3. + sheet.autoFilter.apply(farmData, 3, { + criterion1: "50", + filterOn: Excel.FilterOn.topPercent + }); + + await context.sync(); + }); +Excel.Worksheet#copy:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-copy.yaml + + + await Excel.run(async (context) => { + + let myWorkbook = context.workbook; + let sampleSheet = myWorkbook.worksheets.getActiveWorksheet(); + let copiedSheet = sampleSheet.copy("End") + + sampleSheet.load("name"); + copiedSheet.load("name"); + + await context.sync(); + + console.log("'" + sampleSheet.name + "' was copied to '" + copiedSheet.name + "'") + }); +Excel.Worksheet#findAllOrNullObject:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-find-all.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + const foundRanges = sheet.findAllOrNullObject("Complete", { + completeMatch: true, + matchCase: false + }); + + await context.sync(); + + if (foundRanges.isNullObject) { + console.log("No complete projects"); + } else { + foundRanges.format.fill.color = "green" + } + }); +Excel.Worksheet#showGridlines:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/gridlines.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + sheet.showGridlines = true; + + await context.sync(); + }); +Excel.Worksheet#getNext:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml + + + await Excel.run(async (context) => { + const sheets = context.workbook.worksheets; + + // We don't want to include the default worksheet that was created + // when the workbook was created, so our "firstSheet" will be the one + // after the literal first. Note chaining of navigation methods. + const firstSheet = sheets.getFirst().getNext(); + const lastSheet = sheets.getLast(); + const firstTaxRateRange = firstSheet.getRange("B2"); + const lastTaxRateRange = lastSheet.getRange("B2"); + + firstSheet.load("name"); + lastSheet.load("name"); + firstTaxRateRange.load("text"); + lastTaxRateRange.load("text"); + + await context.sync(); + + let firstYear = firstSheet.name.substr(5, 4); + let lastYear = lastSheet.name.substr(5, 4); + console.log(`Tax Rate change from ${firstYear} to ${lastYear}`, `Tax rate for ${firstYear}: ${firstTaxRateRange.text[0][0]}\nTax rate for ${lastYear}: ${lastTaxRateRange.text[0][0]}`) + + await context.sync(); + }); +Excel.Worksheet#getPrevious:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml + + + await Excel.run(async (context) => { + const sheets = context.workbook.worksheets; + const currentSheet = sheets.getActiveWorksheet(); + const previousYearSheet = currentSheet.getPrevious(); + const currentTaxDueRange = currentSheet.getRange("C2"); + const previousTaxDueRange = previousYearSheet.getRange("C2"); + + currentSheet.load("name"); + previousYearSheet.load("name"); + currentTaxDueRange.load("text"); + previousTaxDueRange.load("text"); + + await context.sync(); + + let currentYear = currentSheet.name.substr(5, 4); + let previousYear = previousYearSheet.name.substr(5, 4); + console.log("Two Year Tax Due Comparison", `Tax due for ${currentYear} was ${currentTaxDueRange.text[0][0]}\nTax due for ${previousYear} was ${previousTaxDueRange.text[0][0]}`) + + await context.sync(); + }); +Excel.Worksheet#tabColor:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/tab-color.yaml + + + await Excel.run(async (context) => { + const activeSheet = context.workbook.worksheets.getActiveWorksheet(); + activeSheet.tabColor = "#FF0000"; + + await context.sync(); + }); +Excel.WorksheetAddedEventArgs#worksheetId:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + + + async function onWorksheetAdd(event) { + await Excel.run(async (context) => { + console.log( + "Handler for worksheet onAdded event has been triggered. Newly added worksheet Id : " + + event.worksheetId + ); + }); + } +Excel.WorksheetChangedEventArgs#changeDirectionState:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet.yaml + + + async function onChange(event: Excel.WorksheetChangedEventArgs) { + // This function is an event handler that returns the address, trigger source, + // and insert or delete shift directions of the change. + await Excel.run(async (context) => { + // Return the address where change occurred. + console.log(`Handler for worksheet onChanged event has been triggered.`); + console.log(` Data changed address: ` + event.address); + + // Return the source of the event that triggered the change. + console.log(` Data change trigger source: ` + event.triggerSource); + + // Note:insertShiftDirection and deleteShiftDirection are exclusive and both enums can't have a value at the same time. + // If one has a value, then the other will return undefined. + + // If the insert shift direction is defined, return it. + if (event.changeDirectionState.insertShiftDirection) { + console.log(` Cells inserted shift direction: ` + event.changeDirectionState.insertShiftDirection); + } + + // If the delete shift direction is defined, return it. + if (event.changeDirectionState.deleteShiftDirection) { + console.log(` Cells deleted shift direction: ` + event.changeDirectionState.deleteShiftDirection); + } + }); + } + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet.yaml + + + // This function deletes data from a range and sets the delete shift + direction to "up". + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + const range = sheet.getRange("A5:F5"); + range.delete(Excel.DeleteShiftDirection.up); + }); +Excel.WorksheetChangedEventArgs#triggerSource:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet.yaml + + + async function onChange(event: Excel.WorksheetChangedEventArgs) { + // This function is an event handler that returns the address, trigger source, + // and insert or delete shift directions of the change. + await Excel.run(async (context) => { + // Return the address where change occurred. + console.log(`Handler for worksheet onChanged event has been triggered.`); + console.log(` Data changed address: ` + event.address); + + // Return the source of the event that triggered the change. + console.log(` Data change trigger source: ` + event.triggerSource); + + // Note:insertShiftDirection and deleteShiftDirection are exclusive and both enums can't have a value at the same time. + // If one has a value, then the other will return undefined. + + // If the insert shift direction is defined, return it. + if (event.changeDirectionState.insertShiftDirection) { + console.log(` Cells inserted shift direction: ` + event.changeDirectionState.insertShiftDirection); + } + + // If the delete shift direction is defined, return it. + if (event.changeDirectionState.deleteShiftDirection) { + console.log(` Cells deleted shift direction: ` + event.changeDirectionState.deleteShiftDirection); + } + }); + } +Excel.WorksheetCollection#onActivated:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + + + await Excel.run(async (context) => { + let sheets = context.workbook.worksheets; + sheets.onActivated.add(onActivate); + + await context.sync(); + console.log("A handler has been registered for the OnActivate event."); + }); +Excel.WorksheetCollection#onAdded:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + + + await Excel.run(async (context) => { + let sheet = context.workbook.worksheets; + sheet.onAdded.add(onWorksheetAdd); + + await context.sync(); + console.log("A handler has been registered for the OnAdded event."); + }); +Excel.WorksheetCollection#onDeactivated:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + + + await Excel.run(async (context) => { + let sheets = context.workbook.worksheets; + sheets.onDeactivated.add(onDeactivate); + + await context.sync(); + console.log("A handler has been registered for the OnDeactivate event."); + }); +Excel.WorksheetCollection#getFirst:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml + + + await Excel.run(async (context) => { + const sheets = context.workbook.worksheets; + + // We don't want to include the default worksheet that was created + // when the workbook was created, so our "firstSheet" will be the one + // after the literal first. Note chaining of navigation methods. + const firstSheet = sheets.getFirst().getNext(); + const lastSheet = sheets.getLast(); + const firstTaxRateRange = firstSheet.getRange("B2"); + const lastTaxRateRange = lastSheet.getRange("B2"); + + firstSheet.load("name"); + lastSheet.load("name"); + firstTaxRateRange.load("text"); + lastTaxRateRange.load("text"); + + await context.sync(); + + let firstYear = firstSheet.name.substr(5, 4); + let lastYear = lastSheet.name.substr(5, 4); + console.log(`Tax Rate change from ${firstYear} to ${lastYear}`, `Tax rate for ${firstYear}: ${firstTaxRateRange.text[0][0]}\nTax rate for ${lastYear}: ${lastTaxRateRange.text[0][0]}`) + + await context.sync(); + }); +Excel.WorksheetCollection#getLast:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml + + + await Excel.run(async (context) => { + const sheets = context.workbook.worksheets; + + // We don't want to include the default worksheet that was created + // when the workbook was created, so our "firstSheet" will be the one + // after the literal first. Note chaining of navigation methods. + const firstSheet = sheets.getFirst().getNext(); + const lastSheet = sheets.getLast(); + const firstTaxRateRange = firstSheet.getRange("B2"); + const lastTaxRateRange = lastSheet.getRange("B2"); + + firstSheet.load("name"); + lastSheet.load("name"); + firstTaxRateRange.load("text"); + lastTaxRateRange.load("text"); + + await context.sync(); + + let firstYear = firstSheet.name.substr(5, 4); + let lastYear = lastSheet.name.substr(5, 4); + console.log(`Tax Rate change from ${firstYear} to ${lastYear}`, `Tax rate for ${firstYear}: ${firstTaxRateRange.text[0][0]}\nTax rate for ${lastYear}: ${lastTaxRateRange.text[0][0]}`) + + await context.sync(); + }); +Excel.WorksheetCustomPropertyCollection#add:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/26-document/custom-properties.yaml + + + await Excel.run(async (context) => { + // Get the key/value pair from the task pane. + const userKey = document.getElementById("key").textContent; + const userValue = document.getElementById("value").textContent; + + // Add the custom property. + const customWorksheetProperties = context.workbook.worksheets.getActiveWorksheet().customProperties; + customWorksheetProperties.add(userKey, userValue); + + await context.sync(); + + console.log(`Successfully set custom worksheet property ${userKey}:${userValue}.`); + }); +Excel.WorksheetFreezePanes#freezeAt:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-freeze-panes.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + + // Freeze the specified range in top-and-left-most pane of the worksheet. + sheet.freezePanes.freezeAt(sheet.getRange("H2:K5")); + + await context.sync(); + }); +Excel.WorksheetFreezePanes#freezeColumns:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-freeze-panes.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + + // Freeze the first two columns in the worksheet. + sheet.freezePanes.freezeColumns(2); + + await context.sync(); + }); +Excel.WorksheetFreezePanes#freezeRows:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-freeze-panes.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + + // Freeze the top two rows in the worksheet. + sheet.freezePanes.freezeRows(2); + + await context.sync(); + }); +Excel.WorksheetFreezePanes#getLocationOrNullObject:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-freeze-panes.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + const frozenRange = sheet.freezePanes.getLocationOrNullObject(); + frozenRange.load("address"); + + await context.sync(); + + if (frozenRange.isNullObject) { + console.log(`The worksheet does not contain a frozen pane.`); + } else { + console.log(`The address of the frozen range (cells that are frozen in the top-and-left-most pane) is "${frozenRange.address}"`); + } + }); +Excel.WorksheetFreezePanes#unfreeze:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-freeze-panes.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + sheet.freezePanes.unfreeze(); + + await context.sync(); + }); +Excel.WorksheetPositionType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-insert-external-worksheets.yaml + + + await Excel.run(async (context) => { + // Retrieve the source workbook. + const workbook = context.workbook; + + // Set up the insert options. + const options = { + sheetNamesToInsert: [], // Insert all the worksheets from the source workbook. + positionType: Excel.WorksheetPositionType.after, // Insert after the `relativeTo` sheet. + relativeTo: "Sheet1" // The sheet relative to which the other worksheets will be inserted. Used with `positionType`. + }; + + // Insert the new worksheets. + workbook.insertWorksheetsFromBase64(externalWorkbook, options); + await context.sync(); + }); +Excel.WorksheetProtection#protect:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/data-protection.yaml + + + let password = await passwordHandler(); + + passwordHelper(password); + + await Excel.run(async (context) => { + let activeSheet = context.workbook.worksheets.getActiveWorksheet(); + activeSheet.load("protection/protected"); + + await context.sync(); + + if (!activeSheet.protection.protected) { + activeSheet.protection.protect(null, password); + } + }); +Excel.WorksheetProtection#unprotect:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/data-protection.yaml + + + let password = await passwordHandler(); + + passwordHelper(password); + + await Excel.run(async (context) => { + let activeSheet = context.workbook.worksheets.getActiveWorksheet(); + activeSheet.protection.unprotect(password); + }); +Excel.WorksheetProtectionChangedEventArgs#isProtected:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet-protection.yaml + + + async function checkProtection(event: + Excel.WorksheetProtectionChangedEventArgs) { + // This function is an event handler that returns the protection status of a worksheet + // and information about the changed worksheet. + await Excel.run(async (context) => { + const protectionStatus = event.isProtected; + const worksheetId = event.worksheetId; + const source = event.source; + console.log("Protection status changed. Protection status is now: " + protectionStatus + "."); + console.log(" ID of changed worksheet: " + worksheetId + "."); + console.log(" Source of change event: " + source + "."); + }); + } +Excel.WorksheetProtectionChangedEventArgs#source:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet-protection.yaml + + + async function checkProtection(event: + Excel.WorksheetProtectionChangedEventArgs) { + // This function is an event handler that returns the protection status of a worksheet + // and information about the changed worksheet. + await Excel.run(async (context) => { + const protectionStatus = event.isProtected; + const worksheetId = event.worksheetId; + const source = event.source; + console.log("Protection status changed. Protection status is now: " + protectionStatus + "."); + console.log(" ID of changed worksheet: " + worksheetId + "."); + console.log(" Source of change event: " + source + "."); + }); + } +Excel.WorksheetProtectionChangedEventArgs#worksheetId:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet-protection.yaml + + + async function checkProtection(event: + Excel.WorksheetProtectionChangedEventArgs) { + // This function is an event handler that returns the protection status of a worksheet + // and information about the changed worksheet. + await Excel.run(async (context) => { + const protectionStatus = event.isProtected; + const worksheetId = event.worksheetId; + const source = event.source; + console.log("Protection status changed. Protection status is now: " + protectionStatus + "."); + console.log(" ID of changed worksheet: " + worksheetId + "."); + console.log(" Source of change event: " + source + "."); + }); + } +Excel.WorksheetSingleClickedEventArgs#address:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-worksheet-single-click.yaml + + + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + sheet.onSingleClicked.add((event) => { + return Excel.run((context) => { + console.log(`Click detected at ${event.address} (pixel offset from upper-left cell corner: ${event.offsetX}, ${event.offsetY})`); + return context.sync(); + }); + }); + + console.log("The worksheet click handler is registered."); + + await context.sync(); + }); +Office.AppointmentCompose#addFileAttachmentAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + + + const attachmentUrl = (document.getElementById("attachmentUrl") as + HTMLInputElement).value; + + Office.context.mailbox.item.addFileAttachmentAsync( + attachmentUrl, + getFileName(attachmentUrl), + { isInline: false }, + (result) => { + console.log(result); + } + ); +Office.AppointmentCompose#addFileAttachmentFromBase64Async:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + + + const base64String = + "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAACRUlEQVRYw82XzXHbMBCFP2F8tzsQc8Ixyh0zoiuIXIGdCsxUYKqC0B04FdiuwMoM7mGOOIXqQGoAymXhgSX+itJM9kIRFLAP+3YXD5Pdbscx5oxaAIW8Ztr6l2PWmQwF4IyaieP53qdfAqQ8CwBn1JU4vpWhrbxXQA5MZfynANmcDIAzKgcy4FKGXsVJFf3nLgKyBQptfT4KQMRz2N0fcbxqmRMDWXflx0VPnrdArq0vekQ1Dv0UeHZGNebHhwjU8AzwKM43RyZnbAf58Q6ghudeWd0Aus0+5EcMIIRi3beua0D3Nm39BEAx3i7HTK4DEBJn5YxKOnaRA5+ErpMBWMpzDvx1RuXCcxOISlufAjfC7zgAsqsvUvMAD0ApPaEtGi9AIlUzKgJo60tt/SyKRkzLrAXERluf7W1gOICWaMyB386oooOWsIHvXbSoHuUSFovtHqicUVnH3EJoeT0aQEf5/XBGlc6otIOWBXAtPeZkAIJ9Bt6cUU9tZautX2nrk3MACHYr1ZKProKRtDw4o8pzAPjWo+NtpXTTvoteDDg8noDAcwbcRedAkGdFXyk2GEDcegVAFp2gyVDHjRQ4o6q2smoqtR5Hd+qMqtoALCWUUymr1m43QMZfOaMK4C0SrMsDANJ2E5FNcbdbjHC+ENl+H0myJFbLtaq4Rt8dyPBYRQV1E40nMv9rl7xrOw3DGb+Whcqu3i/OM6CUOWvgRlufNmnLYy4m77uJI7AXtdNcTDrU71LEyv7v01/N/ovL6bmu5/8A1tNWZldH0W4AAAAASUVORK5CYII="; + Office.context.mailbox.item.addFileAttachmentFromBase64Async( + base64String, + "logo.png", + { isInline: false }, + (result) => { + console.log(result); + } + ); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + + + // Set the signature for the current item with inline image. + + const modIcon1Base64 = + "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpDRDMxMDg1MjBCNDZFMTExODE2MkM1RUI2M0M4MDYxRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFMTUxQjgyRjQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFMTUxQjgyRTQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkQxMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkNEMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+uC/WfAAAAehJREFUeNpilCzfwEAEkAbiECA2A2J1IOaHin8E4ptAfBaIVwLxU0IGMRKw0B6IW4DYhoE4cASIK6E0VsCEQ1wUiNcB8QESLGOAqj0MxBuhZhBloS4QnwHiQAbygR/UDF1CFupCXSjHQDmQg5qli8tCUBBsQUoQ1AD8UDNFsVk4n0o+w+bT+egWglKjNymmeGhLkqLcG2oHAwtUoIuQDj5OVgZPLUmwRe5aEmAxqYqNpFgKssOcCeplM0KqdST5GfpDDRm0JfkYrj3/SE7QguyQY4ImYYLgCtAS10kHGMw6dzNsv/qC7OwCClJXYlR++v6b4er3j5QmIFcmaNlIL6AOslCIjhYKMTHQGTBBqxh6gXcgC6/R0cKbIAv30dHCfaAKGJTxHxJSqS3Fz9DkowNmywpyMcgA8fF7b8D8VWcfM6w8+4gYC+VB+RCk8hSh0gaUD4/dewvlvUWRe/z+GzGWgex4BGtiOAHxXhoHpzMoSGHZAhSPW2lo2VZYWkHOh4nEtLrIAE+hZmNUwK+B2BOIv1PRsu9QM1/jatNcBtVZ0IREKXgENesyoVYbzNIdFFi2A5tl+NqlL6BB4QBNzsSCU1A9nlAzMAALAQMOQl0qB23qWwKxIlIrDBQ394H4OBCvISYqAAIMACVibHDqsO7zAAAAAElFTkSuQmCC"; + + Office.context.mailbox.item.addFileAttachmentFromBase64Async( + modIcon1Base64, + "myImage.png", + { isInline: true }, + function(result) { + if (result.status == Office.AsyncResultStatus.Succeeded) { + const signature = (document.getElementById("signature") as HTMLInputElement).value + ""; + console.log(`Setting signature to "${signature}".`); + Office.context.mailbox.item.body.setSignatureAsync( + signature, + { coercionType: "html" }, + function(asyncResult) { + console.log(`setSignatureAsync: ${asyncResult.status}`); + } + ); + } else { + console.error(`addFileAttachmentFromBase64Async: ${result.error}`); + } + } + ); +Office.AppointmentCompose#categories:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + Office.context.mailbox.item.categories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + console.log("Categories assigned to this item:"); + console.log(JSON.stringify(categories)); + } else { + console.log("There are no categories assigned to this item."); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + // Note: In order for you to successfully add a category, + + // it must be in the mailbox categories master list. + + + Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const masterCategories = asyncResult.value; + if (masterCategories && masterCategories.length > 0) { + // Grab the first category from the master list. + const categoryToAdd = [masterCategories[0].displayName]; + Office.context.mailbox.item.categories.addAsync(categoryToAdd, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully assigned category '${categoryToAdd}' to item.`); + } else { + console.log("categories.addAsync call failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("There are no categories in the master list on this mailbox. You can add categories using Office.context.mailbox.masterCategories.addAsync."); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + Office.context.mailbox.item.categories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + // Grab the first category assigned to this item. + const categoryToRemove = [categories[0].displayName]; + Office.context.mailbox.item.categories.removeAsync(categoryToRemove, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully unassigned category '${categoryToRemove}' from this item.`); + } else { + console.log("categories.removeAsync call failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("There are no categories assigned to this item."); + } + } else { + console.error(asyncResult.error); + } + }); +Office.AppointmentCompose#close:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/25-item-save-and-close/close.yaml + + + Office.context.mailbox.item.close(); +Office.AppointmentCompose#disableClientSignatureAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + + + // Disable the client signature. + + Office.context.mailbox.item.disableClientSignatureAsync(function(asyncResult) + { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("disableClientSignatureAsync succeeded"); + } else { + console.error(asyncResult.error); + } + }); +Office.AppointmentCompose#end:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-end-appointment-organizer.yaml + + + Office.context.mailbox.item.end.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Appointment ends: ${result.value}`); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-end-appointment-organizer.yaml + + + Office.context.mailbox.item.start.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Get start date failed with message ${result.error.message}`); + return; + } + + const end = result.value; // Set end to current start date and time. + end.setDate(end.getDate() + 1); // Set end as 1 day later than start date. + Office.context.mailbox.item.end.setAsync(end, (result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Set end date failed with message ${result.error.message}`); + return; + } + console.log(`Successfully set end date and time to ${end}`); + }); + }); +Office.AppointmentCompose#enhancedLocation:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + + + Office.context.mailbox.item.enhancedLocation.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Failed to get locations. Error message: ${result.error.message}`); + return; + } + const places = result.value; + if (places && places.length > 0) { + result.value.forEach(function(place) { + console.log(`Location: ${place.displayName} (type: ${place.locationIdentifier.type})`); + if (place.locationIdentifier.type === Office.MailboxEnums.LocationType.Room) { + console.log("Email address: " + place.emailAddress); + } + }); + } else { + console.log("There are no locations."); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + + + const locations = [ + { + id: "Contoso", + type: Office.MailboxEnums.LocationType.Custom + }, + { + id: "room500@test.com", + type: Office.MailboxEnums.LocationType.Room + } + ]; + + Office.context.mailbox.item.enhancedLocation.addAsync(locations, (result) => + { + if (result.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully added locations ${JSON.stringify(locations)}`); + } else { + console.error(`Failed to add locations. Error message: ${result.error.message}`); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + + + const locations = [ + { + id: "Contoso", + type: Office.MailboxEnums.LocationType.Custom + }, + { + id: "room500@test.com", + type: Office.MailboxEnums.LocationType.Room + } + ]; + + Office.context.mailbox.item.enhancedLocation.removeAsync(locations, (result) + => { + if (result.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully removed locations ${JSON.stringify(locations)}`); + } else { + console.error(`Failed to remove locations. Error message: ${result.error.message}`); + } + }); +Office.AppointmentCompose#getAttachmentContentAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachment-content.yaml + + + // Gets the attachments of the current message or appointment in compose + mode. The getAttachmentsAsync call can only be used in compose mode. + + Office.context.mailbox.item.getAttachmentsAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.log(result.error.message); + return; + } + + if (result.value.length <= 0) { + console.log("Mail item has no attachments."); + return; + } + + for (let i = 0; i < result.value.length; i++) { + // Log the attachment type and its contents to the console. + Office.context.mailbox.item.getAttachmentContentAsync(result.value[i].id, handleAttachmentsCallback); + } + }); +Office.AppointmentCompose#getAttachmentsAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + + + Office.context.mailbox.item.getAttachmentsAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(result.error.message); + return; + } + + if (result.value.length > 0) { + for (let i = 0; i < result.value.length; i++) { + const attachment = result.value[i]; + let attachmentType; + switch (attachment.attachmentType) { + case Office.MailboxEnums.AttachmentType.Cloud: + attachmentType = "Attachment is stored in a cloud location"; + break; + case Office.MailboxEnums.AttachmentType.File: + attachmentType = "Attachment is a file"; + break; + case Office.MailboxEnums.AttachmentType.Item: + attachmentType = "Attachment is an Exchange item"; + break; + } + console.log( + "ID: " + + attachment.id + + "\n" + + "Type: " + + attachmentType + + "\n" + + "Name: " + + attachment.name + + "\n" + + "Size: " + + attachment.size + + "\n" + + "isInline: " + + attachment.isInline + ); + } + } else { + console.log("No attachments on this message."); + } + }); +Office.AppointmentCompose#getItemIdAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/item-id-compose.yaml + + + Office.context.mailbox.item.getItemIdAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`getItemIdAsync failed with message: ${result.error.message}`); + return; + } + + console.log(result.value); + }); +Office.AppointmentCompose#getSelectedDataAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/get-selected-data.yaml + + + Office.context.mailbox.item.getSelectedDataAsync(Office.CoercionType.Text, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const text = asyncResult.value.data; + const prop = asyncResult.value.sourceProperty; + console.log("Selected text in " + prop + ": " + text); + } else { + console.error(asyncResult.error); + } + }); +Office.AppointmentCompose#getSharedPropertiesAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + + + Office.context.mailbox.item.getSharedPropertiesAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error("The current folder or mailbox isn't shared."); + return; + } + const sharedProperties = result.value; + console.log(`Owner: ${sharedProperties.owner}`); + console.log(`Permissions: ${sharedProperties.delegatePermissions}`); + console.log(`Target mailbox: ${sharedProperties.targetMailbox}`); + }); +Office.AppointmentCompose#isAllDayEvent:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/get-set-isalldayevent.yaml + + + Office.context.mailbox.item.isAllDayEvent.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Is this an all-day event? " + asyncResult.value); + } else { + console.log("Failed to get if this is an all-day event. Error: " + JSON.stringify(asyncResult.error)); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/get-set-isalldayevent.yaml + + + Office.context.mailbox.item.isAllDayEvent.setAsync(true, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Failed to set all-day event: " + JSON.stringify(asyncResult.error)); + } else { + console.log("Appointment set to all-day event."); + } + }); +Office.AppointmentCompose#isClientSignatureEnabledAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + + + // Check if the client signature is currently enabled. + + Office.context.mailbox.item.isClientSignatureEnabledAsync(function(asyncResult) + { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("isClientSignatureEnabledAsync succeeded with result: " + asyncResult.value); + } else { + console.error(asyncResult.error); + } + }); +Office.AppointmentCompose#itemType:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-type.yaml + + + const itemType = Office.context.mailbox.item.itemType; + + switch (itemType) { + case Office.MailboxEnums.ItemType.Appointment: + console.log(`Current item is an ${itemType}.`); + break; + case Office.MailboxEnums.ItemType.Message: + console.log(`Current item is a ${itemType}. A message could be an email, meeting request, meeting response, or meeting cancellation.`); + break; + } +Office.AppointmentCompose#loadCustomPropertiesAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + + + Office.context.mailbox.item.loadCustomPropertiesAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`loadCustomPropertiesAsync failed with message ${result.error.message}`); + return; + } + + customProps = result.value; + console.log("Loaded the CustomProperties object."); + }); +Office.AppointmentCompose#location:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-location-appointment-organizer.yaml + + + Office.context.mailbox.item.location.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Appointment location: ${result.value}`); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-location-appointment-organizer.yaml + + + const location = "my office"; + + Office.context.mailbox.item.location.setAsync(location, (result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Successfully set location to ${location}`); + }); +Office.AppointmentCompose#notificationMessages:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds a progress indicator to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.ProgressIndicator, + message: "Progress indicator with id = " + id + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds an informational notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Non-persistent informational notification message with id = " + id, + icon: "PG.Icon.16", + persistent: false + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds a persistent information notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Persistent informational notification message with id = " + id, + icon: "PG.Icon.16", + persistent: true + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Gets all the notification messages and their keys for the current mail + item. + + Office.context.mailbox.item.notificationMessages.getAllAsync((asyncResult) + => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + console.log(asyncResult.value); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Replaces a notification message of a given key with another message. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + Office.context.mailbox.item.notificationMessages.replaceAsync( + id, + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Notification message with id = " + id + " has been replaced with an informational message.", + icon: "icon2", + persistent: false + }, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Removes a notification message from the current mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + Office.context.mailbox.item.notificationMessages.removeAsync(id, + handleResult); +Office.AppointmentCompose#optionalAttendees:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-optional-attendees-appointment-organizer.yaml + + + Office.context.mailbox.item.optionalAttendees.getAsync(function(asyncResult) + { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const apptOptionalAttendees = asyncResult.value; + for (let i = 0; i < apptOptionalAttendees.length; i++) { + console.log( + "Optional attendees: " + + apptOptionalAttendees[i].displayName + + " (" + + apptOptionalAttendees[i].emailAddress + + ") - response: " + + apptOptionalAttendees[i].appointmentResponse + ); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-optional-attendees-appointment-organizer.yaml + + + const email = (document.getElementById("emailOptional") as + HTMLInputElement).value; + + const emailArray = [email]; + + Office.context.mailbox.item.optionalAttendees.setAsync(emailArray, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Succeeded in setting optional attendees field."); + } else { + console.error(asyncResult.error); + } + }); +Office.AppointmentCompose#organizer:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-organizer-appointment-organizer.yaml + + + Office.context.mailbox.item.organizer.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const apptOrganizer = asyncResult.value; + console.log("Organizer: " + apptOrganizer.displayName + " (" + apptOrganizer.emailAddress + ")"); + } else { + console.error(asyncResult.error); + } + }); +Office.AppointmentCompose#recurrence:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + + + Office.context.mailbox.item.recurrence.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const recurrence = asyncResult.value; + if (recurrence === null) { + console.log("This is a single appointment."); + } else { + console.log(`Recurrence pattern: ${JSON.stringify(recurrence)}`); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + + + // Important: Can only set the recurrence pattern of an appointment series. + + + const currentDate = new Date(); + + let seriesTimeObject: Office.SeriesTime; + + // Set series start date to tomorrow. + + seriesTimeObject.setStartDate(currentDate.getFullYear(), + currentDate.getMonth(), currentDate.getDay() + 1); + + // Set series end date to one year from now. + + seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, + currentDate.getMonth() + 1, currentDate.getDay()); + + // Set start time to 1:30 PM. + + seriesTimeObject.setStartTime(13, 30); + + // Set duration to 30 minutes. + + seriesTimeObject.setDuration(30); + + + const pattern: Office.Recurrence = { + seriesTime: seriesTimeObject, + recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, + recurrenceProperties: { + interval: 1, + dayOfWeek: Office.MailboxEnums.Days.Tue, + weekNumber: Office.MailboxEnums.WeekNumber.Second, + month: Office.MailboxEnums.Month.Sep + }, + recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } + }; + + + Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { + if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); + return; + } + console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); + }); +Office.AppointmentCompose#removeAttachmentAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + + + Office.context.mailbox.item.removeAttachmentAsync( + (document.getElementById("attachmentId") as HTMLInputElement).value, + (result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(result.error.message); + return; + } + + console.log(`Attachment removed successfully.`); + } + ); +Office.AppointmentCompose#requiredAttendees:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-required-attendees-appointment-organizer.yaml + + + Office.context.mailbox.item.requiredAttendees.getAsync(function(asyncResult) + { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const apptRequiredAttendees = asyncResult.value; + for (let i = 0; i < apptRequiredAttendees.length; i++) { + console.log( + "Required attendees: " + + apptRequiredAttendees[i].displayName + + " (" + + apptRequiredAttendees[i].emailAddress + + ") - response: " + + apptRequiredAttendees[i].appointmentResponse + ); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-required-attendees-appointment-organizer.yaml + + + const email = (document.getElementById("emailRequired") as + HTMLInputElement).value; + + const emailArray = [email]; + + Office.context.mailbox.item.requiredAttendees.setAsync(emailArray, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Succeeded in setting required attendees field."); + } else { + console.error(asyncResult.error); + } + }); +Office.AppointmentCompose#saveAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/25-item-save-and-close/save.yaml + + + Office.context.mailbox.item.saveAsync(function (result) { + if (result.status === Office.AsyncResultStatus.Succeeded) { + console.log(`saveAsync succeeded, itemId is ${result.value}`); + } + else { + console.error(`saveAsync failed with message ${result.error.message}`); + } + }); +Office.AppointmentCompose#sendAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/send-async.yaml + + + // This snippet sends the current message or appointment being composed. + + Office.context.mailbox.item.sendAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + }); +Office.AppointmentCompose#sensitivity:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-sensitivity-level.yaml + + + Office.context.mailbox.item.sensitivity.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Sensitivity: " + asyncResult.value); + } else { + console.log("Failed to get sensitivity: " + JSON.stringify(asyncResult.error)); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-sensitivity-level.yaml + + + Office.context.mailbox.item.sensitivity.setAsync( + Office.MailboxEnums.AppointmentSensitivityType.Private, + function callback(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Failed to set appointment sensitivity: " + JSON.stringify(asyncResult.error)); + } else { + console.log("Successfully set appointment sensitivity."); + } + } + ); +Office.AppointmentCompose#sensitivityLabel:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/60-sensitivity-label/sensitivity-label.yaml + + + // This snippet gets the current mail item's sensitivity label. + + Office.context.sensitivityLabelsCatalog.getIsEnabledAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded && asyncResult.value == true) { + Office.context.mailbox.item.sensitivityLabel.getAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(asyncResult.value); + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); +Office.AppointmentCompose#seriesId:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-series-id.yaml + + + const seriesId = Office.context.mailbox.item.seriesId; + + + if (seriesId === undefined) { + console.log("This is a message that's not a meeting request."); + } else if (seriesId === null) { + console.log("This is a single appointment, a parent series, or a meeting request for a series or single meeting."); + } else { + console.log("This is an instance belonging to series with ID " + seriesId); + } +Office.AppointmentCompose#sessionData:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + + + Office.context.mailbox.item.sessionData.getAllAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("The sessionData is " + JSON.stringify(asyncResult.value)); + } else { + console.log("Failed to get all sessionData. Error: " + JSON.stringify(asyncResult.error)); + } + }); +Office.AppointmentCompose#setSelectedDataAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/set-selected-data.yaml + + + Office.context.mailbox.item.setSelectedDataAsync("Replaced", + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Selected text has been updated successfully."); + } else { + console.error(asyncResult.error); + } + }); +Office.AppointmentCompose#start:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml + + + Office.context.mailbox.item.start.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Appointment starts: ${result.value}`); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml + + + const start = new Date(); // Represents current date and time. + + start.setDate(start.getDate() + 2); // Add 2 days to current date. + + Office.context.mailbox.item.start.setAsync(start, (result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Successfully set start date and time to ${start}`); + }); +Office.AppointmentCompose#subject:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-subject-compose.yaml + + + Office.context.mailbox.item.subject.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Subject: ${result.value}`); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-subject-compose.yaml + + + let subject = "Hello World!"; + + Office.context.mailbox.item.subject.setAsync(subject, (result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Successfully set subject to ${subject}`); + }); +Office.AppointmentRead#attachments:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachments-read.yaml + + + const item = Office.context.mailbox.item; + + + if (item.attachments.length > 0) { + for (let i = 0; i < item.attachments.length; i++) { + const attachment = item.attachments[i]; + console.log(`${i+1}. Name: ${attachment.name}`); + console.log(`ID: ${attachment.id}`); + console.log(`Type: ${attachment.attachmentType}`); + console.log(`Inline content: ${attachment.isInline}`); + console.log(`Size: ${attachment.size}`); + } + } else { + console.log("This mail item doesn't contain any attachments."); + } +Office.AppointmentRead#categories:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + Office.context.mailbox.item.categories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + console.log("Categories assigned to this item:"); + console.log(JSON.stringify(categories)); + } else { + console.log("There are no categories assigned to this item."); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + // Note: In order for you to successfully add a category, + + // it must be in the mailbox categories master list. + + + Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const masterCategories = asyncResult.value; + if (masterCategories && masterCategories.length > 0) { + // Grab the first category from the master list. + const categoryToAdd = [masterCategories[0].displayName]; + Office.context.mailbox.item.categories.addAsync(categoryToAdd, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully assigned category '${categoryToAdd}' to item.`); + } else { + console.log("categories.addAsync call failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("There are no categories in the master list on this mailbox. You can add categories using Office.context.mailbox.masterCategories.addAsync."); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + Office.context.mailbox.item.categories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + // Grab the first category assigned to this item. + const categoryToRemove = [categories[0].displayName]; + Office.context.mailbox.item.categories.removeAsync(categoryToRemove, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully unassigned category '${categoryToRemove}' from this item.`); + } else { + console.log("categories.removeAsync call failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("There are no categories assigned to this item."); + } + } else { + console.error(asyncResult.error); + } + }); +Office.AppointmentRead#dateTimeCreated:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-date-time-created-read.yaml + + + console.log(`Creation date and time: + ${Office.context.mailbox.item.dateTimeCreated}`); +Office.AppointmentRead#dateTimeModified:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-date-time-modified-read.yaml + + + console.log(`Date and time item last modified: + ${Office.context.mailbox.item.dateTimeModified}`); +Office.AppointmentRead#displayReplyAllForm:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + + + Office.context.mailbox.item.displayReplyAllForm("This is a reply ALL with + some bold text."); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + + + // Define attachments. + + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + + // Create the reply with attachments. + + Office.context.mailbox.item.displayReplyAllForm({ + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment], + callback: (result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + + console.log("Created a reply-all form with attachments."); + } + }); +Office.AppointmentRead#displayReplyAllFormAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + + + Office.context.mailbox.item.displayReplyAllFormAsync("This is a reply ALL + with some bold text.", function( + asyncResult + ) { + console.log(JSON.stringify(asyncResult)); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + + + // Define attachments. + + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + + // The async version was introduced in requirement set 1.9. + + // It provides a callback when the new appointment form has been created. + + Office.context.mailbox.item.displayReplyAllFormAsync( + { + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment] + }, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${asyncResult.error.message}`); + return; + } + + console.log("Created a reply-all form with attachments."); + } + ); +Office.AppointmentRead#displayReplyForm:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + + + Office.context.mailbox.item.displayReplyForm("This is a reply with some + text in italics."); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + + + // Define attachments. + + const base64Attachment = { + base64file: + "iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAIAAABt+uBvAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTM0A1t6AAAF3klEQVR4Xt2aMcolRRSFdQUuwSW4AAMzU8ENzAIMDA1NzHUBgqmZkbG4ADGVQRgGZBBElAERRPg9eC+PQ73qc6u66lZ3v48bzH+7uqr6VN/T1f3mjafT8Pr7b37+8G3En99+5akTcAqB/n7+48uP3vvp3TdvgT//+uE7P3woBwv07+s/Xn32jKXhwKF/Xr3wpgdxpEC/ffnp8/ffKkQpAg3QDDr6Ocs5RiCzm0ILEQca02qB7u2mPQ4xpnUCabtBWDWFdbfYmBYJ1HLZN6PBP3794uOiAcdKY0oXKLQbFE71jkBS33FrjClRoNBuXjx7J/QUNNCdZBtTikAtdtO1+JBA34Z5xjRfIG03I/YBTYVMScY0U6DQbsbXGdevF2C6Mc0RKLQbHEUbbz0MZNKPuYnGNCpQaDdY0iQTDR9zU4xpSCB9t+PQ719/7k3T0P49bkw7BQrtZnBajTS+uIwYU7dA4ZzynrhMWF/3sc+YOgQK7WaiNQpCh9bRu36tAmm7wT2MovOmaUAaPY3G6DKmWCBtNzaYN80EJjIuDUejMSmBUC/abnCrL3Di8IEwErhAvUGrCxRa4C+ffLDAicMVmhW42K2VLgUK67zlFXwcqL9GmltseUXlDirOvMXIbqKdHc/vieGTIJoE6rL93djNWwy9OHwqRCyQqM+J6LpeFj4bIhZoTWVdWCCLBbvkY93HwqdCdJg0AheQ/XRf9mivhk+C6BMIscawUdR5m0MRPjzRLZAFZMo2pnBHlhE+NhELJGa5YNO42Jh8VCIWCBnMEu8WRf4WC147sAxYjGLcjPDxiCaBDMxS+MKCF1cUdXbF+UhEh0CGqDjksz9CZ++2fRiiWyCgKw532QJjEhMYCR+A2COQoStuwcYyw5i8a2K/QIZ+Ei/YWM41Ju+UGBUI6Bses4eIqf6Nzkc+43N4j8QEgQxdcZApe2OJdRp/R/G+iGkCGbriFmws9TqF4b0QkwUC4SNmwcYSu419xuTnE/MFMrCSRT9FZG8s9xmTn0xkCQSKfu4Di5y9sew1Jj+NOFIgC1hG9q+y7b+s+QnE8QJZYJ0n/g+rKvoBYuFNibMIZJG9sYQx6Y8n3o44l0AILDKWOtW/xf/g8RbE6QSygGVkbyyrxuTHiJMKZLHgjbcY0bPEqQWySN1YFmN5lriAQBZJxlSM4lniMgIhMjaWxRCeJa4kkAWcdaIxFZ17lrieQBazNpZFt54lriqQBXZ9g8ZUdOhZ4toCIWxj6UP2U/TmWSJRoDU/9V1YIIDdcONr9L64dond2P19T8QjmDSDdUYhTJHpcR7z90Am/bVBx6NtFLcIv+pXAzfgo71qaFAmWx9linjYl9UWIJN4zD3454527ncD+DP7g5nBgyI8S5xCIIMHzbCbKjwowrPESQXyVD48aHXcWCDc7dm/Wxk8qKcymfZN2gJ+mfqDDODhPJUDLmTrAeotiFaBLJI2IwYP5KnZ2IaeByrC2xEVgdCFeCfIqzgexVNT0T9Ab30VqAgEwneCjIrj/j01CVFTFuKrQF0gQ/wCaQHJJ1Yc9+ypYcKawgXqrwJKIEPfmRMrjrv11BhTZh4LZGAdhDFNqTju0FN70TW1ZTdVWgUCoTFh1JGK46481U9YU70fITsEMrQxjVQc9+OpTnRNhXZTpVsgI5zKjorjHjzVjK6pkWXbKZCBm1kYU2/F8bmeakDXVJfdVBkSCGB+wpi6lo5P9FSEvpF77abKqECGNqbGiuNTPLWNrikc2mE3VeYIZOj1DCuOG3uqhq6pEbupMlMgA7PfMiY9e27pqTvEGozbTZX5AgFtTFsVx208ReiammI3VVIEMrQxYbWLS+KjnvofXVMT7aZKokCGKIqi4viQp3pOTyJdIAO3wJYx3SqOk/hT1FSS3VRZJBDQxlQUkaipPLupsk4gQxuTjmy7qbJaIEM4SzXW2E2VYwQyhDHdYqXdVDlSIKCNabHdVDlYIOPemA6xmyqnEMgwYzrQbio8Pf0HxndUxitiwgUAAAAASUVORK5CYII=", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + + // Create the reply with attachments. + + Office.context.mailbox.item.displayReplyForm({ + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment], + callback: (result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + + console.log("Created a reply with attachments."); + } + }); +Office.AppointmentRead#displayReplyFormAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + + + Office.context.mailbox.item.displayReplyFormAsync("This is a reply with + some text in italics.", function( + asyncResult + ) { + console.log(JSON.stringify(asyncResult)); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + + + // Define attachments. + + const base64Attachment = { + base64file: + "iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAIAAABt+uBvAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTM0A1t6AAAF3klEQVR4Xt2aMcolRRSFdQUuwSW4AAMzU8ENzAIMDA1NzHUBgqmZkbG4ADGVQRgGZBBElAERRPg9eC+PQ73qc6u66lZ3v48bzH+7uqr6VN/T1f3mjafT8Pr7b37+8G3En99+5akTcAqB/n7+48uP3vvp3TdvgT//+uE7P3woBwv07+s/Xn32jKXhwKF/Xr3wpgdxpEC/ffnp8/ffKkQpAg3QDDr6Ocs5RiCzm0ILEQca02qB7u2mPQ4xpnUCabtBWDWFdbfYmBYJ1HLZN6PBP3794uOiAcdKY0oXKLQbFE71jkBS33FrjClRoNBuXjx7J/QUNNCdZBtTikAtdtO1+JBA34Z5xjRfIG03I/YBTYVMScY0U6DQbsbXGdevF2C6Mc0RKLQbHEUbbz0MZNKPuYnGNCpQaDdY0iQTDR9zU4xpSCB9t+PQ719/7k3T0P49bkw7BQrtZnBajTS+uIwYU7dA4ZzynrhMWF/3sc+YOgQK7WaiNQpCh9bRu36tAmm7wT2MovOmaUAaPY3G6DKmWCBtNzaYN80EJjIuDUejMSmBUC/abnCrL3Di8IEwErhAvUGrCxRa4C+ffLDAicMVmhW42K2VLgUK67zlFXwcqL9GmltseUXlDirOvMXIbqKdHc/vieGTIJoE6rL93djNWwy9OHwqRCyQqM+J6LpeFj4bIhZoTWVdWCCLBbvkY93HwqdCdJg0AheQ/XRf9mivhk+C6BMIscawUdR5m0MRPjzRLZAFZMo2pnBHlhE+NhELJGa5YNO42Jh8VCIWCBnMEu8WRf4WC147sAxYjGLcjPDxiCaBDMxS+MKCF1cUdXbF+UhEh0CGqDjksz9CZ++2fRiiWyCgKw532QJjEhMYCR+A2COQoStuwcYyw5i8a2K/QIZ+Ei/YWM41Ju+UGBUI6Bses4eIqf6Nzkc+43N4j8QEgQxdcZApe2OJdRp/R/G+iGkCGbriFmws9TqF4b0QkwUC4SNmwcYSu419xuTnE/MFMrCSRT9FZG8s9xmTn0xkCQSKfu4Di5y9sew1Jj+NOFIgC1hG9q+y7b+s+QnE8QJZYJ0n/g+rKvoBYuFNibMIZJG9sYQx6Y8n3o44l0AILDKWOtW/xf/g8RbE6QSygGVkbyyrxuTHiJMKZLHgjbcY0bPEqQWySN1YFmN5lriAQBZJxlSM4lniMgIhMjaWxRCeJa4kkAWcdaIxFZ17lrieQBazNpZFt54lriqQBXZ9g8ZUdOhZ4toCIWxj6UP2U/TmWSJRoDU/9V1YIIDdcONr9L64dond2P19T8QjmDSDdUYhTJHpcR7z90Am/bVBx6NtFLcIv+pXAzfgo71qaFAmWx9linjYl9UWIJN4zD3454527ncD+DP7g5nBgyI8S5xCIIMHzbCbKjwowrPESQXyVD48aHXcWCDc7dm/Wxk8qKcymfZN2gJ+mfqDDODhPJUDLmTrAeotiFaBLJI2IwYP5KnZ2IaeByrC2xEVgdCFeCfIqzgexVNT0T9Ab30VqAgEwneCjIrj/j01CVFTFuKrQF0gQ/wCaQHJJ1Yc9+ypYcKawgXqrwJKIEPfmRMrjrv11BhTZh4LZGAdhDFNqTju0FN70TW1ZTdVWgUCoTFh1JGK46481U9YU70fITsEMrQxjVQc9+OpTnRNhXZTpVsgI5zKjorjHjzVjK6pkWXbKZCBm1kYU2/F8bmeakDXVJfdVBkSCGB+wpi6lo5P9FSEvpF77abKqECGNqbGiuNTPLWNrikc2mE3VeYIZOj1DCuOG3uqhq6pEbupMlMgA7PfMiY9e27pqTvEGozbTZX5AgFtTFsVx208ReiammI3VVIEMrQxYbWLS+KjnvofXVMT7aZKokCGKIqi4viQp3pOTyJdIAO3wJYx3SqOk/hT1FSS3VRZJBDQxlQUkaipPLupsk4gQxuTjmy7qbJaIEM4SzXW2E2VYwQyhDHdYqXdVDlSIKCNabHdVDlYIOPemA6xmyqnEMgwYzrQbio8Pf0HxndUxitiwgUAAAAASUVORK5CYII=", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + + // The async version was introduced in requirement set 1.9. + + // It provides a callback when the new appointment form has been created. + + Office.context.mailbox.item.displayReplyFormAsync( + { + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment] + }, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${asyncResult.error.message}`); + return; + } + + console.log("Created reply with attachments."); + } + ); +Office.AppointmentRead#end:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-end-read.yaml + + + console.log(`Appointment ends: ${Office.context.mailbox.item.end}`); +Office.AppointmentRead#enhancedLocation:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + + + Office.context.mailbox.item.enhancedLocation.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Failed to get locations. Error message: ${result.error.message}`); + return; + } + const places = result.value; + if (places && places.length > 0) { + result.value.forEach(function(place) { + console.log(`Location: ${place.displayName} (type: ${place.locationIdentifier.type})`); + if (place.locationIdentifier.type === Office.MailboxEnums.LocationType.Room) { + console.log("Email address: " + place.emailAddress); + } + }); + } else { + console.log("There are no locations."); + } + }); +Office.AppointmentRead#getAttachmentContentAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachment-content.yaml + + + // Gets the attachments of the current message or appointment in read mode. + The item.attachments call can only be used in read mode. + + const item = Office.context.mailbox.item; + + const attachments = item.attachments; + + if (attachments.length <= 0) { + console.log("Mail item has no attachments."); + return; + } + + + for (let i = 0; i < attachments.length; i++) { + // Log the attachment type and its contents to the console. + item.getAttachmentContentAsync(attachments[i].id, handleAttachmentsCallback); + } +Office.AppointmentRead#getRegExMatches:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-regex-matches/contextual.yaml + + + // This API only works when you click on the highlighted word "ScriptLab". + + console.log(Office.context.mailbox.item.getRegExMatches()); +Office.AppointmentRead#getRegExMatchesByName:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-regex-matches/contextual.yaml + + + // This API only works when you click on the highlighted word "ScriptLab". + + console.log(Office.context.mailbox.item.getRegExMatchesByName("sampleRegexName")); +Office.AppointmentRead#getSelectedRegExMatches:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-regex-matches/contextual.yaml + + + const matches = Office.context.mailbox.item.getSelectedRegExMatches(); + + if (matches) { + console.log(matches); + } else { + console.error("Open add-in by clicking on a highlighted regex match, for this API to return something useful."); + } +Office.AppointmentRead#getSharedPropertiesAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + + + Office.context.mailbox.item.getSharedPropertiesAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error("The current folder or mailbox isn't shared."); + return; + } + const sharedProperties = result.value; + console.log(`Owner: ${sharedProperties.owner}`); + console.log(`Permissions: ${sharedProperties.delegatePermissions}`); + console.log(`Target mailbox: ${sharedProperties.targetMailbox}`); + }); +Office.AppointmentRead#itemClass:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-class-read.yaml + + + console.log(`Item class: ${Office.context.mailbox.item.itemClass}`); +Office.AppointmentRead#itemType:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-type.yaml + + + const itemType = Office.context.mailbox.item.itemType; + + switch (itemType) { + case Office.MailboxEnums.ItemType.Appointment: + console.log(`Current item is an ${itemType}.`); + break; + case Office.MailboxEnums.ItemType.Message: + console.log(`Current item is a ${itemType}. A message could be an email, meeting request, meeting response, or meeting cancellation.`); + break; + } +Office.AppointmentRead#loadCustomPropertiesAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + + + Office.context.mailbox.item.loadCustomPropertiesAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`loadCustomPropertiesAsync failed with message ${result.error.message}`); + return; + } + + customProps = result.value; + console.log("Loaded the CustomProperties object."); + }); +Office.AppointmentRead#location:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-location-read.yaml + + + console.log(`Appointment location: + ${Office.context.mailbox.item.location}`); +Office.AppointmentRead#normalizedSubject:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-normalized-subject-read.yaml + + + console.log(`Normalized subject: + ${Office.context.mailbox.item.normalizedSubject}`); +Office.AppointmentRead#notificationMessages:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds a progress indicator to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.ProgressIndicator, + message: "Progress indicator with id = " + id + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds an informational notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Non-persistent informational notification message with id = " + id, + icon: "PG.Icon.16", + persistent: false + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds a persistent information notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Persistent informational notification message with id = " + id, + icon: "PG.Icon.16", + persistent: true + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Gets all the notification messages and their keys for the current mail + item. + + Office.context.mailbox.item.notificationMessages.getAllAsync((asyncResult) + => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + console.log(asyncResult.value); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Replaces a notification message of a given key with another message. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + Office.context.mailbox.item.notificationMessages.replaceAsync( + id, + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Notification message with id = " + id + " has been replaced with an informational message.", + icon: "icon2", + persistent: false + }, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Removes a notification message from the current mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + Office.context.mailbox.item.notificationMessages.removeAsync(id, + handleResult); +Office.AppointmentRead#optionalAttendees:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-optional-attendees-appointment-attendee.yaml + + + const apptOptionalAttendees = Office.context.mailbox.item.optionalAttendees; + + console.log("Optional attendees:"); + + for (let i = 0; i < apptOptionalAttendees.length; i++) { + console.log( + apptOptionalAttendees[i].displayName + + " (" + + apptOptionalAttendees[i].emailAddress + + ") - response: " + + apptOptionalAttendees[i].appointmentResponse + ); + } +Office.AppointmentRead#organizer:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-organizer-appointment-attendee.yaml + + + const apptOrganizer = Office.context.mailbox.item.organizer; + + console.log("Organizer: " + apptOrganizer.displayName + " (" + + apptOrganizer.emailAddress + ")"); +Office.AppointmentRead#recurrence:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-recurrence-read.yaml + + + const recurrence = Office.context.mailbox.item.recurrence; + + + if (recurrence === undefined) { + console.log("This item is a message but not a meeting request."); + } else if (recurrence === null) { + console.log("This is a single appointment."); + } else { + console.log(JSON.stringify(recurrence)); + } +Office.AppointmentRead#requiredAttendees:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-required-attendees-appointment-attendee.yaml + + + const apptRequiredAttendees = Office.context.mailbox.item.requiredAttendees; + + console.log("Required attendees:"); + + for (let i = 0; i < apptRequiredAttendees.length; i++) { + console.log( + apptRequiredAttendees[i].displayName + + " (" + + apptRequiredAttendees[i].emailAddress + + ") - response: " + + apptRequiredAttendees[i].appointmentResponse + ); + } +Office.AppointmentRead#seriesId:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-series-id.yaml + + + const seriesId = Office.context.mailbox.item.seriesId; + + + if (seriesId === undefined) { + console.log("This is a message that's not a meeting request."); + } else if (seriesId === null) { + console.log("This is a single appointment, a parent series, or a meeting request for a series or single meeting."); + } else { + console.log("This is an instance belonging to series with ID " + seriesId); + } +Office.AppointmentRead#start:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-start-read.yaml + + + console.log(`Appointment starts: ${Office.context.mailbox.item.start}`); +Office.AppointmentRead#subject:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-subject-read.yaml + + + console.log(`Subject: ${Office.context.mailbox.item.subject}`); +Office.AttachmentDetails:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachments-read.yaml + + + const item = Office.context.mailbox.item; + + + if (item.attachments.length > 0) { + for (let i = 0; i < item.attachments.length; i++) { + const attachment = item.attachments[i]; + console.log(`${i+1}. Name: ${attachment.name}`); + console.log(`ID: ${attachment.id}`); + console.log(`Type: ${attachment.attachmentType}`); + console.log(`Inline content: ${attachment.isInline}`); + console.log(`Size: ${attachment.size}`); + } + } else { + console.log("This mail item doesn't contain any attachments."); + } +Office.AttachmentDetailsCompose:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + + + Office.context.mailbox.item.getAttachmentsAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(result.error.message); + return; + } + + if (result.value.length > 0) { + for (let i = 0; i < result.value.length; i++) { + const attachment = result.value[i]; + let attachmentType; + switch (attachment.attachmentType) { + case Office.MailboxEnums.AttachmentType.Cloud: + attachmentType = "Attachment is stored in a cloud location"; + break; + case Office.MailboxEnums.AttachmentType.File: + attachmentType = "Attachment is a file"; + break; + case Office.MailboxEnums.AttachmentType.Item: + attachmentType = "Attachment is an Exchange item"; + break; + } + console.log( + "ID: " + + attachment.id + + "\n" + + "Type: " + + attachmentType + + "\n" + + "Name: " + + attachment.name + + "\n" + + "Size: " + + attachment.size + + "\n" + + "isInline: " + + attachment.isInline + ); + } + } else { + console.log("No attachments on this message."); + } + }); +Office.Body:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/add-inline-base64-image.yaml + + + // Get the current body of the message or appointment. + + Office.context.mailbox.item.body.getAsync(Office.CoercionType.Html, + (bodyResult) => { + if (bodyResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to get body: ${bodyResult.error.message}`); + return; + } + + // Add the Base64-encoded image to the end of the body. + const options = { isInline: true, asyncContext: bodyResult.value }; + Office.context.mailbox.item.addFileAttachmentFromBase64Async(base64String, "sample.png", options, (attachResult) => { + if (attachResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to attach file: ${attachResult.error.message}`); + return; + } + + let body = attachResult.asyncContext; + body += ''; + + Office.context.mailbox.item.body.setAsync(body, { coercionType: Office.CoercionType.Html }, (setResult) => { + if (setResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to set body: ${setResult.error.message}`); + return; + } + + console.log("Inline Base64-encoded image added to the end of the body."); + }); + }); + }); +Office.Body#appendOnSendAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/append-text-on-send.yaml + + + // This snippet appends text to the end of the message or appointment's body + once it's sent. + + const text = (document.getElementById("text-field") as + HTMLInputElement).value; + + + // It's recommended to call getTypeAsync and pass its returned value to the + options.coercionType parameter of the appendOnSendAsync call. + + Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + const bodyFormat = asyncResult.value; + Office.context.mailbox.item.body.appendOnSendAsync(text, { coercionType: bodyFormat }, (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + console.log(`"${text}" will be appended to the body once the message or appointment is sent. Send the mail item to test this feature.`); + }); + }); +Office.Body#getAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/add-inline-base64-image.yaml + + + // Get the current body of the message or appointment. + + Office.context.mailbox.item.body.getAsync(Office.CoercionType.Html, + (bodyResult) => { + if (bodyResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to get body: ${bodyResult.error.message}`); + return; + } + + // Add the Base64-encoded image to the end of the body. + const options = { isInline: true, asyncContext: bodyResult.value }; + Office.context.mailbox.item.addFileAttachmentFromBase64Async(base64String, "sample.png", options, (attachResult) => { + if (attachResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to attach file: ${attachResult.error.message}`); + return; + } + + let body = attachResult.asyncContext; + body += ''; + + Office.context.mailbox.item.body.setAsync(body, { coercionType: Office.CoercionType.Html }, (setResult) => { + if (setResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to set body: ${setResult.error.message}`); + return; + } + + console.log("Inline Base64-encoded image added to the end of the body."); + }); + }); + }); +Office.Body#getTypeAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/get-body-format.yaml + + + // Get the mail item's body format (plain text or HTML) and log it to the + console. + + Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + console.log("Body format: " + asyncResult.value); + }); +Office.Body#prependAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/prepend-text-to-item-body.yaml + + + /* This snippet adds text to the beginning of the message or appointment's + body. + + When prepending a link in HTML markup to the body, you can disable the online link preview by setting the anchor tag's id attribute to "LPNoLP". For example, 'Click here!'. + */ + + const text = (document.getElementById("text-field") as + HTMLInputElement).value; + + + // It's recommended to call getTypeAsync and pass its returned value to the + options.coercionType parameter of the prependAsync call. + + Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + const bodyFormat = asyncResult.value; + Office.context.mailbox.item.body.prependAsync(text, { coercionType: bodyFormat }, (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + console.log(`"${text}" prepended to the body.`); + }); + }); +Office.Body#prependOnSendAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/prepend-text-on-send.yaml + + + // This snippet prepends text to the beginning of the message or + appointment's body once it's sent. + + const text = (document.getElementById("text-field") as + HTMLInputElement).value; + + + // It's recommended to call getTypeAsync and pass its returned value to the + options.coercionType parameter of the prependOnSendAsync call. + + Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + const bodyFormat = asyncResult.value; + Office.context.mailbox.item.body.prependOnSendAsync(text, { coercionType: bodyFormat }, (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + console.log(`"${text}" will be prepended to the body once the message or appointment is sent. Send the mail item to test this feature.`); + }); + }); +Office.Body#setAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/add-inline-base64-image.yaml + + + // Get the current body of the message or appointment. + + Office.context.mailbox.item.body.getAsync(Office.CoercionType.Html, + (bodyResult) => { + if (bodyResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to get body: ${bodyResult.error.message}`); + return; + } + + // Add the Base64-encoded image to the end of the body. + const options = { isInline: true, asyncContext: bodyResult.value }; + Office.context.mailbox.item.addFileAttachmentFromBase64Async(base64String, "sample.png", options, (attachResult) => { + if (attachResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to attach file: ${attachResult.error.message}`); + return; + } + + let body = attachResult.asyncContext; + body += ''; + + Office.context.mailbox.item.body.setAsync(body, { coercionType: Office.CoercionType.Html }, (setResult) => { + if (setResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Failed to set body: ${setResult.error.message}`); + return; + } + + console.log("Inline Base64-encoded image added to the end of the body."); + }); + }); + }); +Office.Body#setSelectedDataAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/replace-selected-text.yaml + + + /* This snippet replaces selected text in a message or appointment's body + with specified text. + + If you want to use a link in HTML markup as a value of the setSelectedDataAsync call's data parameter, you can disable online link preview by setting the anchor tag's id attribute to "LPNoLP". For example, 'Click here!'. + */ + + const text = (document.getElementById("text-field") as + HTMLInputElement).value; + + + // It's recommended to call getTypeAsync and pass its returned value to the + options.coercionType parameter of the prependAsync call. + + Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + const bodyFormat = asyncResult.value; + Office.context.mailbox.item.body.setSelectedDataAsync(text, { coercionType: bodyFormat }, (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + console.log(`Replaced selected text with "${text}".`); + }); + }); +Office.Body#setSignatureAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + + + // Set the signature for the current item with inline image. + + const modIcon1Base64 = + "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpDRDMxMDg1MjBCNDZFMTExODE2MkM1RUI2M0M4MDYxRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFMTUxQjgyRjQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFMTUxQjgyRTQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkQxMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkNEMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+uC/WfAAAAehJREFUeNpilCzfwEAEkAbiECA2A2J1IOaHin8E4ptAfBaIVwLxU0IGMRKw0B6IW4DYhoE4cASIK6E0VsCEQ1wUiNcB8QESLGOAqj0MxBuhZhBloS4QnwHiQAbygR/UDF1CFupCXSjHQDmQg5qli8tCUBBsQUoQ1AD8UDNFsVk4n0o+w+bT+egWglKjNymmeGhLkqLcG2oHAwtUoIuQDj5OVgZPLUmwRe5aEmAxqYqNpFgKssOcCeplM0KqdST5GfpDDRm0JfkYrj3/SE7QguyQY4ImYYLgCtAS10kHGMw6dzNsv/qC7OwCClJXYlR++v6b4er3j5QmIFcmaNlIL6AOslCIjhYKMTHQGTBBqxh6gXcgC6/R0cKbIAv30dHCfaAKGJTxHxJSqS3Fz9DkowNmywpyMcgA8fF7b8D8VWcfM6w8+4gYC+VB+RCk8hSh0gaUD4/dewvlvUWRe/z+GzGWgex4BGtiOAHxXhoHpzMoSGHZAhSPW2lo2VZYWkHOh4nEtLrIAE+hZmNUwK+B2BOIv1PRsu9QM1/jatNcBtVZ0IREKXgENesyoVYbzNIdFFi2A5tl+NqlL6BB4QBNzsSCU1A9nlAzMAALAQMOQl0qB23qWwKxIlIrDBQ394H4OBCvISYqAAIMACVibHDqsO7zAAAAAElFTkSuQmCC"; + + Office.context.mailbox.item.addFileAttachmentFromBase64Async( + modIcon1Base64, + "myImage.png", + { isInline: true }, + function(result) { + if (result.status == Office.AsyncResultStatus.Succeeded) { + const signature = (document.getElementById("signature") as HTMLInputElement).value + ""; + console.log(`Setting signature to "${signature}".`); + Office.context.mailbox.item.body.setSignatureAsync( + signature, + { coercionType: "html" }, + function(asyncResult) { + console.log(`setSignatureAsync: ${asyncResult.status}`); + } + ); + } else { + console.error(`addFileAttachmentFromBase64Async: ${result.error}`); + } + } + ); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + + + // Set the signature for the current item. + + const signature = (document.getElementById("signature") as + HTMLInputElement).value; + + console.log(`Setting signature to "${signature}".`); + + Office.context.mailbox.item.body.setSignatureAsync(signature, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("setSignatureAsync succeeded"); + } else { + console.error(asyncResult.error); + } + }); +Office.Categories#addAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + // Note: In order for you to successfully add a category, + + // it must be in the mailbox categories master list. + + + Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const masterCategories = asyncResult.value; + if (masterCategories && masterCategories.length > 0) { + // Grab the first category from the master list. + const categoryToAdd = [masterCategories[0].displayName]; + Office.context.mailbox.item.categories.addAsync(categoryToAdd, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully assigned category '${categoryToAdd}' to item.`); + } else { + console.log("categories.addAsync call failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("There are no categories in the master list on this mailbox. You can add categories using Office.context.mailbox.masterCategories.addAsync."); + } + } else { + console.error(asyncResult.error); + } + }); +Office.Categories#getAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + Office.context.mailbox.item.categories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + console.log("Categories assigned to this item:"); + console.log(JSON.stringify(categories)); + } else { + console.log("There are no categories assigned to this item."); + } + } else { + console.error(asyncResult.error); + } + }); +Office.Categories#removeAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + Office.context.mailbox.item.categories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + // Grab the first category assigned to this item. + const categoryToRemove = [categories[0].displayName]; + Office.context.mailbox.item.categories.removeAsync(categoryToRemove, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully unassigned category '${categoryToRemove}' from this item.`); + } else { + console.log("categories.removeAsync call failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("There are no categories assigned to this item."); + } + } else { + console.error(asyncResult.error); + } + }); +Office.CoercionTypeOptions:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/append-text-on-send.yaml + + + // This snippet appends text to the end of the message or appointment's body + once it's sent. + + const text = (document.getElementById("text-field") as + HTMLInputElement).value; + + + // It's recommended to call getTypeAsync and pass its returned value to the + options.coercionType parameter of the appendOnSendAsync call. + + Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + const bodyFormat = asyncResult.value; + Office.context.mailbox.item.body.appendOnSendAsync(text, { coercionType: bodyFormat }, (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + console.log(`"${text}" will be appended to the body once the message or appointment is sent. Send the mail item to test this feature.`); + }); + }); +Office.CustomProperties#get:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + + + const propertyName = (document.getElementById("get-property-name") as + HTMLInputElement).value; + + const propertyValue = customProps.get(propertyName); + + console.log(`The value of custom property "${propertyName}" is + "${propertyValue}".`); +Office.CustomProperties#getAll:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + + + let allCustomProps; + + if (Office.context.requirements.isSetSupported("Mailbox", "1.9")) { + allCustomProps = customProps.getAll(); + } else { + allCustomProps = customProps["rawData"]; + } + + + console.log(allCustomProps); +Office.CustomProperties#remove:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + + + const propertyName = (document.getElementById("remove-property-name") as + HTMLInputElement).value; + + customProps.remove(propertyName); + + console.log(`Custom property "${propertyName}" removed.`); +Office.CustomProperties#saveAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + + + customProps.saveAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`saveAsync failed with message ${result.error.message}`); + return; + } + + console.log(`Custom properties saved with status: ${result.status}`); + }); +Office.CustomProperties#set:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + + + const propertyName = (document.getElementById("set-property-name") as + HTMLInputElement).value; + + const propertyValue = (document.getElementById("property-value") as + HTMLInputElement).value; + + customProps.set(propertyName, propertyValue); + + console.log(`Custom property "${propertyName}" set to value + "${propertyValue}".`); +Office.DelayDeliveryTime#getAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/delay-message-delivery.yaml + + + // This snippet gets the delivery date and time of a message. + + Office.context.mailbox.item.delayDeliveryTime.getAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + const deliveryDate = asyncResult.value; + if (deliveryDate === 0) { + console.log("Your message will be delivered immediately when you select Send."); + } else { + const date = new Date(deliveryDate); + console.log(`Message delivery date and time: ${date.toString()}`); + } + }); +Office.DelayDeliveryTime#setAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/delay-message-delivery.yaml + + + function setDeliveryDate(minutes) { + // This snippet sets the delivery date and time of a message. + const currentTime = new Date().getTime(); + const milliseconds = totalDelay * 60000; + const timeDelay = new Date(currentTime + milliseconds); + Office.context.mailbox.item.delayDeliveryTime.setAsync(timeDelay, (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + if (minutes === 1440) { + console.log(`Delayed delivery by an additional one day.`); + } else { + console.log(`Delayed delivery by an additional ${minutes} minutes.`); + } + }); + } +Office.Diagnostics:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-diagnostic-information.yaml + + + // This function gets a mailbox's diagnostic information, such as Outlook + client and version, and logs it to the console. + + const diagnostics = Office.context.mailbox.diagnostics; + + console.log(`Client application: ${diagnostics.hostName}`); + + console.log(`Client version: ${diagnostics.hostVersion}`); + + + switch (diagnostics.OWAView) { + case undefined: + console.log("Current view (Outlook on the web only): Not applicable. An Outlook desktop client is in use."); + break; + case Office.MailboxEnums.OWAView.OneColumnNarrow: + console.log("Current view (Outlook on the web only): Viewed from an older generation mobile phone"); + break; + case Office.MailboxEnums.OWAView.OneColumn: + console.log("Current view (Outlook on the web only): Viewed from a newer generation mobile phone"); + break; + case Office.MailboxEnums.OWAView.TwoColumns: + console.log("Current view (Outlook on the web only): Viewed from a tablet"); + break; + case Office.MailboxEnums.OWAView.ThreeColumns: + console.log("Current view (Outlook on the web only): Viewed from a desktop computer"); + break; + } +Office.Display#body:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml + + + // This snippet temporarily sets the content displayed in the body of a + message in read mode. + + // The set content will remain visible until the user switches to a + different message in the Reading Pane or closes the window of the current + message. + + const bodyText = (document.getElementById("body-text-field") as + HTMLInputElement).value; + + Office.context.mailbox.item.display.body.setAsync(bodyText, (asyncResult) => + { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Action failed with error: ${asyncResult.error.message}`); + return; + } + + console.log("Temporarily set the content displayed in the body."); + }); +Office.Display#subject:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml + + + // This snippet temporarily sets the content displayed in the subject field + of a message in read mode. + + // The set content will remain visible until the user switches to a + different message in the Reading Pane or closes the window of the current + message. + + const subjectText = (document.getElementById("subject-text-field") as + HTMLInputElement).value; + + Office.context.mailbox.item.display.subject.setAsync(subjectText, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Action failed with error: ${asyncResult.error.message}`); + return; + } + + console.log("Temporarily set the content displayed in the subject field."); + }); +Office.DisplayedBody#setAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml + + + // This snippet temporarily sets the content displayed in the body of a + message in read mode. + + // The set content will remain visible until the user switches to a + different message in the Reading Pane or closes the window of the current + message. + + const bodyText = (document.getElementById("body-text-field") as + HTMLInputElement).value; + + Office.context.mailbox.item.display.body.setAsync(bodyText, (asyncResult) => + { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Action failed with error: ${asyncResult.error.message}`); + return; + } + + console.log("Temporarily set the content displayed in the body."); + }); +Office.DisplayedSubject#setAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml + + + // This snippet temporarily sets the content displayed in the subject field + of a message in read mode. + + // The set content will remain visible until the user switches to a + different message in the Reading Pane or closes the window of the current + message. + + const subjectText = (document.getElementById("subject-text-field") as + HTMLInputElement).value; + + Office.context.mailbox.item.display.subject.setAsync(subjectText, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Action failed with error: ${asyncResult.error.message}`); + return; + } + + console.log("Temporarily set the content displayed in the subject field."); + }); +Office.DragAndDropEventArgs:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/80-events/drag-drop-item.yaml + + + function dragAndDropEventHandler(event) { + Office.context.mailbox.addHandlerAsync(Office.EventType.DragAndDropEvent, (event) => { + console.log(`Event type: ${event.type}`); + + const eventData = event.dragAndDropEventData; + console.log(`x-coordinate: ${eventData.pageX}, y-coordinate: ${eventData.pageY}`); + + if (eventData.type == "drop") { + console.log("Items dropped into task pane."); + const files = eventData.dataTransfer.files; + files.forEach((file) => { + const content = file.fileContent; + const name = file.name; + const fileType = file.type; + console.log(`File name: ${name}`); + console.log(`File type: ${fileType}`); + console.log(`Contents: ${content.text().then((text) => { console.log(text); })}`); + }); + } + }); + } +Office.DragoverEventData:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/80-events/drag-drop-item.yaml + + + function dragAndDropEventHandler(event) { + Office.context.mailbox.addHandlerAsync(Office.EventType.DragAndDropEvent, (event) => { + console.log(`Event type: ${event.type}`); + + const eventData = event.dragAndDropEventData; + console.log(`x-coordinate: ${eventData.pageX}, y-coordinate: ${eventData.pageY}`); + + if (eventData.type == "drop") { + console.log("Items dropped into task pane."); + const files = eventData.dataTransfer.files; + files.forEach((file) => { + const content = file.fileContent; + const name = file.name; + const fileType = file.type; + console.log(`File name: ${name}`); + console.log(`File type: ${fileType}`); + console.log(`Contents: ${content.text().then((text) => { console.log(text); })}`); + }); + } + }); + } +Office.DropEventData:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/80-events/drag-drop-item.yaml + + + function dragAndDropEventHandler(event) { + Office.context.mailbox.addHandlerAsync(Office.EventType.DragAndDropEvent, (event) => { + console.log(`Event type: ${event.type}`); + + const eventData = event.dragAndDropEventData; + console.log(`x-coordinate: ${eventData.pageX}, y-coordinate: ${eventData.pageY}`); + + if (eventData.type == "drop") { + console.log("Items dropped into task pane."); + const files = eventData.dataTransfer.files; + files.forEach((file) => { + const content = file.fileContent; + const name = file.name; + const fileType = file.type; + console.log(`File name: ${name}`); + console.log(`File type: ${fileType}`); + console.log(`Contents: ${content.text().then((text) => { console.log(text); })}`); + }); + } + }); + } +Office.DroppedItems:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/80-events/drag-drop-item.yaml + + + function dragAndDropEventHandler(event) { + Office.context.mailbox.addHandlerAsync(Office.EventType.DragAndDropEvent, (event) => { + console.log(`Event type: ${event.type}`); + + const eventData = event.dragAndDropEventData; + console.log(`x-coordinate: ${eventData.pageX}, y-coordinate: ${eventData.pageY}`); + + if (eventData.type == "drop") { + console.log("Items dropped into task pane."); + const files = eventData.dataTransfer.files; + files.forEach((file) => { + const content = file.fileContent; + const name = file.name; + const fileType = file.type; + console.log(`File name: ${name}`); + console.log(`File type: ${fileType}`); + console.log(`Contents: ${content.text().then((text) => { console.log(text); })}`); + }); + } + }); + } +Office.DroppedItemDetails:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/80-events/drag-drop-item.yaml + + + function dragAndDropEventHandler(event) { + Office.context.mailbox.addHandlerAsync(Office.EventType.DragAndDropEvent, (event) => { + console.log(`Event type: ${event.type}`); + + const eventData = event.dragAndDropEventData; + console.log(`x-coordinate: ${eventData.pageX}, y-coordinate: ${eventData.pageY}`); + + if (eventData.type == "drop") { + console.log("Items dropped into task pane."); + const files = eventData.dataTransfer.files; + files.forEach((file) => { + const content = file.fileContent; + const name = file.name; + const fileType = file.type; + console.log(`File name: ${name}`); + console.log(`File type: ${fileType}`); + console.log(`Contents: ${content.text().then((text) => { console.log(text); })}`); + }); + } + }); + } +Office.EnhancedLocation#addAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + + + const locations = [ + { + id: "Contoso", + type: Office.MailboxEnums.LocationType.Custom + }, + { + id: "room500@test.com", + type: Office.MailboxEnums.LocationType.Room + } + ]; + + Office.context.mailbox.item.enhancedLocation.addAsync(locations, (result) => + { + if (result.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully added locations ${JSON.stringify(locations)}`); + } else { + console.error(`Failed to add locations. Error message: ${result.error.message}`); + } + }); +Office.EnhancedLocation#getAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + + + Office.context.mailbox.item.enhancedLocation.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Failed to get locations. Error message: ${result.error.message}`); + return; + } + const places = result.value; + if (places && places.length > 0) { + result.value.forEach(function(place) { + console.log(`Location: ${place.displayName} (type: ${place.locationIdentifier.type})`); + if (place.locationIdentifier.type === Office.MailboxEnums.LocationType.Room) { + console.log("Email address: " + place.emailAddress); + } + }); + } else { + console.log("There are no locations."); + } + }); +Office.EnhancedLocation#removeAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + + + const locations = [ + { + id: "Contoso", + type: Office.MailboxEnums.LocationType.Custom + }, + { + id: "room500@test.com", + type: Office.MailboxEnums.LocationType.Room + } + ]; + + Office.context.mailbox.item.enhancedLocation.removeAsync(locations, (result) + => { + if (result.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully removed locations ${JSON.stringify(locations)}`); + } else { + console.error(`Failed to remove locations. Error message: ${result.error.message}`); + } + }); +Office.From#getAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-from-message-compose.yaml + + + Office.context.mailbox.item.from.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const msgFrom = asyncResult.value; + console.log("Message from: " + msgFrom.displayName + " (" + msgFrom.emailAddress + ")"); + } else { + console.error(asyncResult.error); + } + }); +Office.InternetHeaders#getAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml + + + Office.context.mailbox.item.internetHeaders.getAsync( + ["preferred-fruit", "preferred-vegetable", "best-vegetable", "nonexistent-header"], + function (asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Selected headers: " + JSON.stringify(asyncResult.value)); + } else { + console.log("Error getting selected headers: " + JSON.stringify(asyncResult.error)); + } + } + ); +Office.InternetHeaders#removeAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml + + + Office.context.mailbox.item.internetHeaders.removeAsync( + ["best-vegetable", "nonexistent-header"], + function (asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Successfully removed selected headers"); + } else { + console.log("Error removing selected headers: " + JSON.stringify(asyncResult.error)); + } + } + ); +Office.InternetHeaders#setAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml + + + Office.context.mailbox.item.internetHeaders.setAsync( + { "preferred-fruit": "orange", "preferred-vegetable": "broccoli", "best-vegetable": "spinach" }, + function (asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Successfully set headers"); + } else { + console.log("Error setting headers: " + JSON.stringify(asyncResult.error)); + } + } + + ); +Office.IsAllDayEvent#getAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/get-set-isalldayevent.yaml + + + Office.context.mailbox.item.isAllDayEvent.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Is this an all-day event? " + asyncResult.value); + } else { + console.log("Failed to get if this is an all-day event. Error: " + JSON.stringify(asyncResult.error)); + } + }); +Office.IsAllDayEvent#setAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/get-set-isalldayevent.yaml + + + Office.context.mailbox.item.isAllDayEvent.setAsync(true, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Failed to set all-day event: " + JSON.stringify(asyncResult.error)); + } else { + console.log("Appointment set to all-day event."); + } + }); +Office.Item:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-type.yaml + + + const itemType = Office.context.mailbox.item.itemType; + + switch (itemType) { + case Office.MailboxEnums.ItemType.Appointment: + console.log(`Current item is an ${itemType}.`); + break; + case Office.MailboxEnums.ItemType.Message: + console.log(`Current item is a ${itemType}. A message could be an email, meeting request, meeting response, or meeting cancellation.`); + break; + } +Office.Location#getAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-location-appointment-organizer.yaml + + + Office.context.mailbox.item.location.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Appointment location: ${result.value}`); + }); +Office.Location#setAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-location-appointment-organizer.yaml + + + const location = "my office"; + + Office.context.mailbox.item.location.setAsync(location, (result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Successfully set location to ${location}`); + }); +Office.Mailbox#convertToEwsId:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/ids-and-urls.yaml + + + // Get the EWS URL and EWS item ID. + + console.log("EWS URL: " + Office.context.mailbox.ewsUrl); + + const ewsId = Office.context.mailbox.item.itemId; + + console.log("EWS item ID: " + Office.context.mailbox.item.itemId); + + + // Convert the EWS item ID to a REST-formatted ID. + + const restId = Office.context.mailbox.convertToRestId(ewsId, + Office.MailboxEnums.RestVersion.v2_0); + + console.log("REST item ID: " + restId); + + + // Convert the REST-formatted ID back to an EWS-formatted ID. + + const ewsId2 = Office.context.mailbox.convertToEwsId(restId, + Office.MailboxEnums.RestVersion.v2_0); + + console.log("EWS ID (from REST ID): " + ewsId2); +Office.Mailbox#convertToRestId:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/ids-and-urls.yaml + + + // Get the EWS URL and EWS item ID. + + console.log("EWS URL: " + Office.context.mailbox.ewsUrl); + + const ewsId = Office.context.mailbox.item.itemId; + + console.log("EWS item ID: " + Office.context.mailbox.item.itemId); + + + // Convert the EWS item ID to a REST-formatted ID. + + const restId = Office.context.mailbox.convertToRestId(ewsId, + Office.MailboxEnums.RestVersion.v2_0); + + console.log("REST item ID: " + restId); + + + // Convert the REST-formatted ID back to an EWS-formatted ID. + + const ewsId2 = Office.context.mailbox.convertToEwsId(restId, + Office.MailboxEnums.RestVersion.v2_0); + + console.log("EWS ID (from REST ID): " + ewsId2); +Office.Mailbox#diagnostics:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-diagnostic-information.yaml + + + // This function gets a mailbox's diagnostic information, such as Outlook + client and version, and logs it to the console. + + const diagnostics = Office.context.mailbox.diagnostics; + + console.log(`Client application: ${diagnostics.hostName}`); + + console.log(`Client version: ${diagnostics.hostVersion}`); + + + switch (diagnostics.OWAView) { + case undefined: + console.log("Current view (Outlook on the web only): Not applicable. An Outlook desktop client is in use."); + break; + case Office.MailboxEnums.OWAView.OneColumnNarrow: + console.log("Current view (Outlook on the web only): Viewed from an older generation mobile phone"); + break; + case Office.MailboxEnums.OWAView.OneColumn: + console.log("Current view (Outlook on the web only): Viewed from a newer generation mobile phone"); + break; + case Office.MailboxEnums.OWAView.TwoColumns: + console.log("Current view (Outlook on the web only): Viewed from a tablet"); + break; + case Office.MailboxEnums.OWAView.ThreeColumns: + console.log("Current view (Outlook on the web only): Viewed from a desktop computer"); + break; + } +Office.Mailbox#displayAppointmentForm:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-existing-appointment.yaml + + + const itemId = (document.getElementById("itemId") as + HTMLInputElement).value; + + Office.context.mailbox.displayAppointmentForm(itemId); +Office.Mailbox#displayAppointmentFormAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-existing-appointment.yaml + + + const itemId = (document.getElementById("itemId") as + HTMLInputElement).value; + + + // The async version will return error 9049 if the item is not found. + + // The async version is only available starting with requirement set 1.9. + + Office.context.mailbox.displayAppointmentFormAsync(itemId, + function(asyncResult) { + console.log("Result: " + JSON.stringify(asyncResult)); + }); +Office.Mailbox#displayMessageForm:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-existing-message.yaml + + + const itemId = (document.getElementById("itemId") as + HTMLInputElement).value; + + Office.context.mailbox.displayMessageForm(itemId); +Office.Mailbox#displayMessageFormAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-existing-message.yaml + + + const itemId = (document.getElementById("itemId") as + HTMLInputElement).value; + + + // The async version will return error 9049 if the item is not found. + + // The async version is only available starting with requirement set 1.9. + + Office.context.mailbox.displayMessageFormAsync(itemId, function + (asyncResult) { + console.log("Result: " + JSON.stringify(asyncResult)); + }); +Office.Mailbox#displayNewAppointmentForm:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-new-appointment.yaml + + + const start = new Date(); + + const end = new Date(); + + end.setHours(start.getHours() + 1); + + + Office.context.mailbox.displayNewAppointmentForm({ + requiredAttendees: ["bob@contoso.com"], + optionalAttendees: ["sam@contoso.com"], + start: start, + end: end, + location: "Home", + subject: "meeting", + resources: ["projector@contoso.com"], + body: "Hello World!" + }); +Office.Mailbox#displayNewAppointmentFormAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-new-appointment.yaml + + + const start = new Date(); + + const end = new Date(); + + end.setHours(start.getHours() + 1); + + + // The async version is only available starting with requirement set 1.9, + + // and provides a callback when the new appointment form has been created. + + Office.context.mailbox.displayNewAppointmentFormAsync( + { + requiredAttendees: ["bob@contoso.com"], + optionalAttendees: ["sam@contoso.com"], + start: start, + end: end, + location: "Home", + subject: "meeting", + resources: ["projector@contoso.com"], + body: "Hello World!" + }, + function(asyncResult) { + console.log(JSON.stringify(asyncResult)); + } + ); +Office.Mailbox#displayNewMessageForm:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-new-message.yaml + + + Office.context.mailbox.displayNewMessageForm({ + toRecipients: Office.context.mailbox.item.to, // Copies the To line from current item + ccRecipients: ["sam@contoso.com"], + subject: "Outlook add-ins are cool!", + htmlBody: 'Hello World!
', + attachments: [ + { + type: "file", + name: "image.png", + url: "https://i.imgur.com/9S36xvA.jpg", + isInline: true + } + ] + }); +Office.Mailbox#displayNewMessageFormAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-new-message.yaml + + + // The async version is only available starting with requirement set 1.9, + + // and provides a callback when the new message form has been created. + + Office.context.mailbox.displayNewMessageFormAsync( + { + toRecipients: Office.context.mailbox.item.to, // Copies the To line from current item + ccRecipients: ["sam@contoso.com"], + subject: "Outlook add-ins are cool!", + htmlBody: 'Hello World!
', + attachments: [ + { + type: "file", + name: "image.png", + url: "https://i.imgur.com/9S36xvA.jpg", + isInline: true + } + ] + }, + (asyncResult) => { + console.log(JSON.stringify(asyncResult)); + } + ); +Office.Mailbox#ewsUrl:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/ids-and-urls.yaml + + + // Get the EWS URL and EWS item ID. + + console.log("EWS URL: " + Office.context.mailbox.ewsUrl); + + const ewsId = Office.context.mailbox.item.itemId; + + console.log("EWS item ID: " + Office.context.mailbox.item.itemId); + + + // Convert the EWS item ID to a REST-formatted ID. + + const restId = Office.context.mailbox.convertToRestId(ewsId, + Office.MailboxEnums.RestVersion.v2_0); + + console.log("REST item ID: " + restId); + + + // Convert the REST-formatted ID back to an EWS-formatted ID. + + const ewsId2 = Office.context.mailbox.convertToEwsId(restId, + Office.MailboxEnums.RestVersion.v2_0); + + console.log("EWS ID (from REST ID): " + ewsId2); +Office.Mailbox#getCallbackTokenAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/user-callback-token.yaml + + + Office.context.mailbox.getCallbackTokenAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`Token retrieval failed with message: ${result.error.message}`); + return; + } + + console.log(result.value); + }); +Office.Mailbox#getSelectedItemsAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-message-properties.yaml + + + // Retrieves the selected messages' properties and logs them to the console. + + Office.context.mailbox.getSelectedItemsAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + asyncResult.value.forEach((message) => { + console.log(`Item ID: ${message.itemId}`); + console.log(`Conversation ID: ${message.conversationId}`); + console.log(`Internet message ID: ${message.internetMessageId}`); + console.log(`Subject: ${message.subject}`); + console.log(`Item type: ${message.itemType}`); + console.log(`Item mode: ${message.itemMode}`); + console.log(`Has attachment: ${message.hasAttachment}`); + }); + }); +Office.Mailbox#getUserIdentityTokenAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/user-identity-token.yaml + + + Office.context.mailbox.getUserIdentityTokenAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`Token retrieval failed with message: ${result.error.message}`) + return; + } + + console.log(result.value); + }); +Office.Mailbox#loadItemByIdAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-loaded-message-properties.yaml + + + async function getSenderEmailAddress(item) { + const itemId = item.itemId; + await new Promise((resolve) => { + Office.context.mailbox.loadItemByIdAsync(itemId, (result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.log(result.error.message); + return; + } + + const loadedItem = result.value; + const sender = loadedItem.from.emailAddress; + appendToListItem(sender); + + // Unload the current message before processing another selected message. + loadedItem.unloadAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + resolve(); + }); + }); + }); + } +Office.Mailbox#makeEwsRequestAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-attendee.yaml + + + const ewsId = Office.context.mailbox.item.itemId; + + const request = ` + + + + + AllProperties + + + + + + + `; + + Office.context.mailbox.makeEwsRequestAsync(request, (result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(result.error.message); + return; + } + + console.log(getUID(result.value)); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/send-message-using-make-ews-request-async.yaml + + + const request = ''+ + ' '+ + ' '+ + ' '+ + ' '+ + ' '+ + ' '+ + ' Hello, Outlook!'+ + ' This message was sent from a ScriptLab code sample, used from ' + Office.context.mailbox.diagnostics.hostName + ', version ' + Office.context.mailbox.diagnostics.hostVersion + '!'+ + ' '+ + ' ' + Office.context.mailbox.userProfile.emailAddress + ''+ + ' '+ + ' '+ + ' '+ + ' '+ + ' '+ + ''; + + Office.context.mailbox.makeEwsRequestAsync(request, (result) => { + console.log(result); + }); +Office.Mailbox#masterCategories:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + + + Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + console.log("Master categories:"); + console.log(JSON.stringify(categories)); + } else { + console.log("There are no categories in the master list."); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + + + const masterCategoriesToAdd = [ + { + displayName: "TestCategory", + color: Office.MailboxEnums.CategoryColor.Preset0 + } + ]; + + + Office.context.mailbox.masterCategories.addAsync(masterCategoriesToAdd, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Successfully added categories to master list"); + } else { + console.log("masterCategories.addAsync call failed with error: " + asyncResult.error.message); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + + + const masterCategoriesToRemove = ["TestCategory"]; + + + Office.context.mailbox.masterCategories.removeAsync(masterCategoriesToRemove, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Successfully removed categories from master list"); + } else { + console.log("masterCategories.removeAsync call failed with error: " + asyncResult.error.message); + } + }); +Office.MailboxEnums.ActionType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds an informational message with actions to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + + const itemId = Office.context.mailbox.item.itemId; + + const details = { + type: Office.MailboxEnums.ItemNotificationMessageType.InsightMessage, + message: "This is an insight notification with id = " + id, + icon: "PG.Icon.16", + actions: [ + { + actionText: "Open insight", + actionType: Office.MailboxEnums.ActionType.ShowTaskPane, + // Identify whether the current mail item is in read or compose mode to set the appropriate commandId value. + commandId: (itemId == undefined ? "PG.HelpCommand.Compose" : "PG.HelpCommand.Read"), + contextData: { a: "aValue", b: "bValue" } + } + ] + }; + + + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); +Office.MailboxEnums.AppointmentSensitivityType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-sensitivity-level.yaml + + + Office.context.mailbox.item.sensitivity.setAsync( + Office.MailboxEnums.AppointmentSensitivityType.Private, + function callback(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Failed to set appointment sensitivity: " + JSON.stringify(asyncResult.error)); + } else { + console.log("Successfully set appointment sensitivity."); + } + } + ); +Office.MailboxEnums.AttachmentContentFormat:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachment-content.yaml + + + function handleAttachmentsCallback(result) { + // Identifies whether the attachment is a Base64-encoded string, .eml file, .icalendar file, or a URL. + switch (result.value.format) { + case Office.MailboxEnums.AttachmentContentFormat.Base64: + // Handle file attachment. + console.log("Attachment is a Base64-encoded string."); + break; + case Office.MailboxEnums.AttachmentContentFormat.Eml: + // Handle email item attachment. + console.log("Attachment is a message."); + break; + case Office.MailboxEnums.AttachmentContentFormat.ICalendar: + // Handle .icalender attachment. + console.log("Attachment is a calendar item."); + break; + case Office.MailboxEnums.AttachmentContentFormat.Url: + // Handle cloud attachment. + console.log("Attachment is a cloud attachment."); + break; + default: + // Handle attachment formats that aren't supported. + } + + console.log(result.value.content); + } +Office.MailboxEnums.AttachmentType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + + + Office.context.mailbox.item.getAttachmentsAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(result.error.message); + return; + } + + if (result.value.length > 0) { + for (let i = 0; i < result.value.length; i++) { + const attachment = result.value[i]; + let attachmentType; + switch (attachment.attachmentType) { + case Office.MailboxEnums.AttachmentType.Cloud: + attachmentType = "Attachment is stored in a cloud location"; + break; + case Office.MailboxEnums.AttachmentType.File: + attachmentType = "Attachment is a file"; + break; + case Office.MailboxEnums.AttachmentType.Item: + attachmentType = "Attachment is an Exchange item"; + break; + } + console.log( + "ID: " + + attachment.id + + "\n" + + "Type: " + + attachmentType + + "\n" + + "Name: " + + attachment.name + + "\n" + + "Size: " + + attachment.size + + "\n" + + "isInline: " + + attachment.isInline + ); + } + } else { + console.log("No attachments on this message."); + } + }); +Office.MailboxEnums.CategoryColor:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + + + const masterCategoriesToAdd = [ + { + displayName: "TestCategory", + color: Office.MailboxEnums.CategoryColor.Preset0 + } + ]; + + + Office.context.mailbox.masterCategories.addAsync(masterCategoriesToAdd, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Successfully added categories to master list"); + } else { + console.log("masterCategories.addAsync call failed with error: " + asyncResult.error.message); + } + }); +Office.MailboxEnums.ComposeType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + + + // Get the compose type of the current message. + + Office.context.mailbox.item.getComposeTypeAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log( + "getComposeTypeAsync succeeded with composeType: " + + asyncResult.value.composeType + + " and coercionType: " + + asyncResult.value.coercionType + ); + } else { + console.error(asyncResult.error); + } + }); +Office.MailboxEnums.Days:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + + + // Important: Can only set the recurrence pattern of an appointment series. + + + const currentDate = new Date(); + + let seriesTimeObject: Office.SeriesTime; + + // Set series start date to tomorrow. + + seriesTimeObject.setStartDate(currentDate.getFullYear(), + currentDate.getMonth(), currentDate.getDay() + 1); + + // Set series end date to one year from now. + + seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, + currentDate.getMonth() + 1, currentDate.getDay()); + + // Set start time to 1:30 PM. + + seriesTimeObject.setStartTime(13, 30); + + // Set duration to 30 minutes. + + seriesTimeObject.setDuration(30); + + + const pattern: Office.Recurrence = { + seriesTime: seriesTimeObject, + recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, + recurrenceProperties: { + interval: 1, + dayOfWeek: Office.MailboxEnums.Days.Tue, + weekNumber: Office.MailboxEnums.WeekNumber.Second, + month: Office.MailboxEnums.Month.Sep + }, + recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } + }; + + + Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { + if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); + return; + } + console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); + }); +Office.MailboxEnums.ItemNotificationMessageType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds an error notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.ErrorMessage, + message: "Error notification message with id = " + id + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); +Office.MailboxEnums.ItemType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-type.yaml + + + const itemType = Office.context.mailbox.item.itemType; + + switch (itemType) { + case Office.MailboxEnums.ItemType.Appointment: + console.log(`Current item is an ${itemType}.`); + break; + case Office.MailboxEnums.ItemType.Message: + console.log(`Current item is a ${itemType}. A message could be an email, meeting request, meeting response, or meeting cancellation.`); + break; + } +Office.MailboxEnums.LocationType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + + + const locations = [ + { + id: "Contoso", + type: Office.MailboxEnums.LocationType.Custom + }, + { + id: "room500@test.com", + type: Office.MailboxEnums.LocationType.Room + } + ]; + + Office.context.mailbox.item.enhancedLocation.addAsync(locations, (result) => + { + if (result.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully added locations ${JSON.stringify(locations)}`); + } else { + console.error(`Failed to add locations. Error message: ${result.error.message}`); + } + }); +Office.MailboxEnums.Month:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + + + // Important: Can only set the recurrence pattern of an appointment series. + + + const currentDate = new Date(); + + let seriesTimeObject: Office.SeriesTime; + + // Set series start date to tomorrow. + + seriesTimeObject.setStartDate(currentDate.getFullYear(), + currentDate.getMonth(), currentDate.getDay() + 1); + + // Set series end date to one year from now. + + seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, + currentDate.getMonth() + 1, currentDate.getDay()); + + // Set start time to 1:30 PM. + + seriesTimeObject.setStartTime(13, 30); + + // Set duration to 30 minutes. + + seriesTimeObject.setDuration(30); + + + const pattern: Office.Recurrence = { + seriesTime: seriesTimeObject, + recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, + recurrenceProperties: { + interval: 1, + dayOfWeek: Office.MailboxEnums.Days.Tue, + weekNumber: Office.MailboxEnums.WeekNumber.Second, + month: Office.MailboxEnums.Month.Sep + }, + recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } + }; + + + Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { + if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); + return; + } + console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); + }); +Office.MailboxEnums.OWAView:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-diagnostic-information.yaml + + + // This function gets a mailbox's diagnostic information, such as Outlook + client and version, and logs it to the console. + + const diagnostics = Office.context.mailbox.diagnostics; + + console.log(`Client application: ${diagnostics.hostName}`); + + console.log(`Client version: ${diagnostics.hostVersion}`); + + + switch (diagnostics.OWAView) { + case undefined: + console.log("Current view (Outlook on the web only): Not applicable. An Outlook desktop client is in use."); + break; + case Office.MailboxEnums.OWAView.OneColumnNarrow: + console.log("Current view (Outlook on the web only): Viewed from an older generation mobile phone"); + break; + case Office.MailboxEnums.OWAView.OneColumn: + console.log("Current view (Outlook on the web only): Viewed from a newer generation mobile phone"); + break; + case Office.MailboxEnums.OWAView.TwoColumns: + console.log("Current view (Outlook on the web only): Viewed from a tablet"); + break; + case Office.MailboxEnums.OWAView.ThreeColumns: + console.log("Current view (Outlook on the web only): Viewed from a desktop computer"); + break; + } +Office.MailboxEnums.RecipientType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-to-message-read.yaml + + + const msgTo = Office.context.mailbox.item.to; + + const distributionLists = []; + + const externalRecipients = []; + + const internalRecipients = []; + + const otherRecipients = []; + + for (let i = 0; i < msgTo.length; i++) { + switch (msgTo[i].recipientType) { + case Office.MailboxEnums.RecipientType.DistributionList: + distributionLists.push(msgTo[i]); + break; + case Office.MailboxEnums.RecipientType.ExternalUser: + externalRecipients.push(msgTo[i]); + break; + case Office.MailboxEnums.RecipientType.User: + internalRecipients.push(msgTo[i]); + break; + case Office.MailboxEnums.RecipientType.Other: + otherRecipients.push(msgTo[i]); + } + } + + + if (distributionLists.length > 0) { + console.log("Distribution Lists:"); + distributionLists.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); + } + + + if (externalRecipients.length > 0) { + console.log("External Recipients:"); + externalRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); + } + + + if (internalRecipients.length > 0) { + console.log("Internal Recipients:"); + internalRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); + } + + + if (otherRecipients.length > 0) { + console.log("Other Recipients:"); + otherRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); + } +Office.MailboxEnums.RecurrenceTimeZone:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + + + // Important: Can only set the recurrence pattern of an appointment series. + + + const currentDate = new Date(); + + let seriesTimeObject: Office.SeriesTime; + + // Set series start date to tomorrow. + + seriesTimeObject.setStartDate(currentDate.getFullYear(), + currentDate.getMonth(), currentDate.getDay() + 1); + + // Set series end date to one year from now. + + seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, + currentDate.getMonth() + 1, currentDate.getDay()); + + // Set start time to 1:30 PM. + + seriesTimeObject.setStartTime(13, 30); + + // Set duration to 30 minutes. + + seriesTimeObject.setDuration(30); + + + const pattern: Office.Recurrence = { + seriesTime: seriesTimeObject, + recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, + recurrenceProperties: { + interval: 1, + dayOfWeek: Office.MailboxEnums.Days.Tue, + weekNumber: Office.MailboxEnums.WeekNumber.Second, + month: Office.MailboxEnums.Month.Sep + }, + recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } + }; + + + Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { + if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); + return; + } + console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); + }); +Office.MailboxEnums.RecurrenceType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + + + // Important: Can only set the recurrence pattern of an appointment series. + + + const currentDate = new Date(); + + let seriesTimeObject: Office.SeriesTime; + + // Set series start date to tomorrow. + + seriesTimeObject.setStartDate(currentDate.getFullYear(), + currentDate.getMonth(), currentDate.getDay() + 1); + + // Set series end date to one year from now. + + seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, + currentDate.getMonth() + 1, currentDate.getDay()); + + // Set start time to 1:30 PM. + + seriesTimeObject.setStartTime(13, 30); + + // Set duration to 30 minutes. + + seriesTimeObject.setDuration(30); + + + const pattern: Office.Recurrence = { + seriesTime: seriesTimeObject, + recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, + recurrenceProperties: { + interval: 1, + dayOfWeek: Office.MailboxEnums.Days.Tue, + weekNumber: Office.MailboxEnums.WeekNumber.Second, + month: Office.MailboxEnums.Month.Sep + }, + recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } + }; + + + Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { + if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); + return; + } + console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); + }); +Office.MailboxEnums.ResponseType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-all-attendees.yaml + + + function organizeByResponse(attendees) { + const accepted = []; + const declined = []; + const noResponse = []; + const tentative = []; + attendees.forEach(attendee => { + switch (attendee.appointmentResponse) { + case Office.MailboxEnums.ResponseType.Accepted: + accepted.push(attendee); + break; + case Office.MailboxEnums.ResponseType.Declined: + declined.push(attendee); + break; + case Office.MailboxEnums.ResponseType.None: + noResponse.push(attendee); + break; + case Office.MailboxEnums.ResponseType.Tentative: + tentative.push(attendee); + break; + case Office.MailboxEnums.ResponseType.Organizer: + console.log(`Organizer: ${attendee.displayName}, ${attendee.emailAddress}`); + break; + } + }); + + // List attendees by their response. + console.log("Accepted: "); + printAttendees(accepted); + console.log("Declined: "); + printAttendees(declined); + console.log("Tentative: "); + printAttendees(tentative); + console.log("No response: "); + printAttendees(noResponse); + } +Office.MailboxEnums.RestVersion:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/ids-and-urls.yaml + + + // Get the EWS URL and EWS item ID. + + console.log("EWS URL: " + Office.context.mailbox.ewsUrl); + + const ewsId = Office.context.mailbox.item.itemId; + + console.log("EWS item ID: " + Office.context.mailbox.item.itemId); + + + // Convert the EWS item ID to a REST-formatted ID. + + const restId = Office.context.mailbox.convertToRestId(ewsId, + Office.MailboxEnums.RestVersion.v2_0); + + console.log("REST item ID: " + restId); + + + // Convert the REST-formatted ID back to an EWS-formatted ID. + + const ewsId2 = Office.context.mailbox.convertToEwsId(restId, + Office.MailboxEnums.RestVersion.v2_0); + + console.log("EWS ID (from REST ID): " + ewsId2); +Office.MailboxEnums.SourceProperty:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/get-selected-data.yaml + + + Office.context.mailbox.item.getSelectedDataAsync(Office.CoercionType.Text, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const text = asyncResult.value.data; + const prop = asyncResult.value.sourceProperty; + console.log("Selected text in " + prop + ": " + text); + } else { + console.error(asyncResult.error); + } + }); +Office.MailboxEnums.WeekNumber:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + + + // Important: Can only set the recurrence pattern of an appointment series. + + + const currentDate = new Date(); + + let seriesTimeObject: Office.SeriesTime; + + // Set series start date to tomorrow. + + seriesTimeObject.setStartDate(currentDate.getFullYear(), + currentDate.getMonth(), currentDate.getDay() + 1); + + // Set series end date to one year from now. + + seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, + currentDate.getMonth() + 1, currentDate.getDay()); + + // Set start time to 1:30 PM. + + seriesTimeObject.setStartTime(13, 30); + + // Set duration to 30 minutes. + + seriesTimeObject.setDuration(30); + + + const pattern: Office.Recurrence = { + seriesTime: seriesTimeObject, + recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, + recurrenceProperties: { + interval: 1, + dayOfWeek: Office.MailboxEnums.Days.Tue, + weekNumber: Office.MailboxEnums.WeekNumber.Second, + month: Office.MailboxEnums.Month.Sep + }, + recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } + }; + + + Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { + if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); + return; + } + console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); + }); +Office.MasterCategories#addAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + + + const masterCategoriesToAdd = [ + { + displayName: "TestCategory", + color: Office.MailboxEnums.CategoryColor.Preset0 + } + ]; + + + Office.context.mailbox.masterCategories.addAsync(masterCategoriesToAdd, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Successfully added categories to master list"); + } else { + console.log("masterCategories.addAsync call failed with error: " + asyncResult.error.message); + } + }); +Office.MasterCategories#getAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + + + Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + console.log("Master categories:"); + console.log(JSON.stringify(categories)); + } else { + console.log("There are no categories in the master list."); + } + } else { + console.error(asyncResult.error); + } + }); +Office.MasterCategories#removeAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + + + const masterCategoriesToRemove = ["TestCategory"]; + + + Office.context.mailbox.masterCategories.removeAsync(masterCategoriesToRemove, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Successfully removed categories from master list"); + } else { + console.log("masterCategories.removeAsync call failed with error: " + asyncResult.error.message); + } + }); +Office.MessageCompose:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + + + const attachmentUrl = (document.getElementById("attachmentUrl") as + HTMLInputElement).value; + + Office.context.mailbox.item.addFileAttachmentAsync( + attachmentUrl, + getFileName(attachmentUrl), + { isInline: false }, + (result) => { + console.log(result); + } + ); +Office.MessageCompose#addFileAttachmentAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + + + const attachmentUrl = (document.getElementById("attachmentUrl") as + HTMLInputElement).value; + + Office.context.mailbox.item.addFileAttachmentAsync( + attachmentUrl, + getFileName(attachmentUrl), + { isInline: false }, + (result) => { + console.log(result); + } + ); +Office.MessageCompose#addFileAttachmentFromBase64Async:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + + + const base64String = + "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAACRUlEQVRYw82XzXHbMBCFP2F8tzsQc8Ixyh0zoiuIXIGdCsxUYKqC0B04FdiuwMoM7mGOOIXqQGoAymXhgSX+itJM9kIRFLAP+3YXD5Pdbscx5oxaAIW8Ztr6l2PWmQwF4IyaieP53qdfAqQ8CwBn1JU4vpWhrbxXQA5MZfynANmcDIAzKgcy4FKGXsVJFf3nLgKyBQptfT4KQMRz2N0fcbxqmRMDWXflx0VPnrdArq0vekQ1Dv0UeHZGNebHhwjU8AzwKM43RyZnbAf58Q6ghudeWd0Aus0+5EcMIIRi3beua0D3Nm39BEAx3i7HTK4DEBJn5YxKOnaRA5+ErpMBWMpzDvx1RuXCcxOISlufAjfC7zgAsqsvUvMAD0ApPaEtGi9AIlUzKgJo60tt/SyKRkzLrAXERluf7W1gOICWaMyB386oooOWsIHvXbSoHuUSFovtHqicUVnH3EJoeT0aQEf5/XBGlc6otIOWBXAtPeZkAIJ9Bt6cUU9tZautX2nrk3MACHYr1ZKProKRtDw4o8pzAPjWo+NtpXTTvoteDDg8noDAcwbcRedAkGdFXyk2GEDcegVAFp2gyVDHjRQ4o6q2smoqtR5Hd+qMqtoALCWUUymr1m43QMZfOaMK4C0SrMsDANJ2E5FNcbdbjHC+ENl+H0myJFbLtaq4Rt8dyPBYRQV1E40nMv9rl7xrOw3DGb+Whcqu3i/OM6CUOWvgRlufNmnLYy4m77uJI7AXtdNcTDrU71LEyv7v01/N/ovL6bmu5/8A1tNWZldH0W4AAAAASUVORK5CYII="; + Office.context.mailbox.item.addFileAttachmentFromBase64Async( + base64String, + "logo.png", + { isInline: false }, + (result) => { + console.log(result); + } + ); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + + + // Set the signature for the current item with inline image. + + const modIcon1Base64 = + "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpDRDMxMDg1MjBCNDZFMTExODE2MkM1RUI2M0M4MDYxRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFMTUxQjgyRjQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFMTUxQjgyRTQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkQxMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkNEMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+uC/WfAAAAehJREFUeNpilCzfwEAEkAbiECA2A2J1IOaHin8E4ptAfBaIVwLxU0IGMRKw0B6IW4DYhoE4cASIK6E0VsCEQ1wUiNcB8QESLGOAqj0MxBuhZhBloS4QnwHiQAbygR/UDF1CFupCXSjHQDmQg5qli8tCUBBsQUoQ1AD8UDNFsVk4n0o+w+bT+egWglKjNymmeGhLkqLcG2oHAwtUoIuQDj5OVgZPLUmwRe5aEmAxqYqNpFgKssOcCeplM0KqdST5GfpDDRm0JfkYrj3/SE7QguyQY4ImYYLgCtAS10kHGMw6dzNsv/qC7OwCClJXYlR++v6b4er3j5QmIFcmaNlIL6AOslCIjhYKMTHQGTBBqxh6gXcgC6/R0cKbIAv30dHCfaAKGJTxHxJSqS3Fz9DkowNmywpyMcgA8fF7b8D8VWcfM6w8+4gYC+VB+RCk8hSh0gaUD4/dewvlvUWRe/z+GzGWgex4BGtiOAHxXhoHpzMoSGHZAhSPW2lo2VZYWkHOh4nEtLrIAE+hZmNUwK+B2BOIv1PRsu9QM1/jatNcBtVZ0IREKXgENesyoVYbzNIdFFi2A5tl+NqlL6BB4QBNzsSCU1A9nlAzMAALAQMOQl0qB23qWwKxIlIrDBQ394H4OBCvISYqAAIMACVibHDqsO7zAAAAAElFTkSuQmCC"; + + Office.context.mailbox.item.addFileAttachmentFromBase64Async( + modIcon1Base64, + "myImage.png", + { isInline: true }, + function(result) { + if (result.status == Office.AsyncResultStatus.Succeeded) { + const signature = (document.getElementById("signature") as HTMLInputElement).value + ""; + console.log(`Setting signature to "${signature}".`); + Office.context.mailbox.item.body.setSignatureAsync( + signature, + { coercionType: "html" }, + function(asyncResult) { + console.log(`setSignatureAsync: ${asyncResult.status}`); + } + ); + } else { + console.error(`addFileAttachmentFromBase64Async: ${result.error}`); + } + } + ); +Office.MessageCompose#bcc:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-bcc-message-compose.yaml + + + Office.context.mailbox.item.bcc.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const msgBcc = asyncResult.value; + console.log("Message being blind-copied to:"); + for (let i = 0; i < msgBcc.length; i++) { + console.log(msgBcc[i].displayName + " (" + msgBcc[i].emailAddress + ")"); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-bcc-message-compose.yaml + + + const email = (document.getElementById("emailBcc") as + HTMLInputElement).value; + + const emailArray = [email]; + + Office.context.mailbox.item.bcc.setAsync(emailArray, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Succeeded in setting Bcc field."); + } else { + console.error(asyncResult.error); + } + }); +Office.MessageCompose#categories:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + Office.context.mailbox.item.categories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + console.log("Categories assigned to this item:"); + console.log(JSON.stringify(categories)); + } else { + console.log("There are no categories assigned to this item."); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + // Note: In order for you to successfully add a category, + + // it must be in the mailbox categories master list. + + + Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const masterCategories = asyncResult.value; + if (masterCategories && masterCategories.length > 0) { + // Grab the first category from the master list. + const categoryToAdd = [masterCategories[0].displayName]; + Office.context.mailbox.item.categories.addAsync(categoryToAdd, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully assigned category '${categoryToAdd}' to item.`); + } else { + console.log("categories.addAsync call failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("There are no categories in the master list on this mailbox. You can add categories using Office.context.mailbox.masterCategories.addAsync."); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + Office.context.mailbox.item.categories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + // Grab the first category assigned to this item. + const categoryToRemove = [categories[0].displayName]; + Office.context.mailbox.item.categories.removeAsync(categoryToRemove, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully unassigned category '${categoryToRemove}' from this item.`); + } else { + console.log("categories.removeAsync call failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("There are no categories assigned to this item."); + } + } else { + console.error(asyncResult.error); + } + }); +Office.MessageCompose#cc:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-cc-message-compose.yaml + + + Office.context.mailbox.item.cc.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const msgCc = asyncResult.value; + console.log("Message being copied to:"); + for (let i = 0; i < msgCc.length; i++) { + console.log(msgCc[i].displayName + " (" + msgCc[i].emailAddress + ")"); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-cc-message-compose.yaml + + + const email = (document.getElementById("emailCc") as + HTMLInputElement).value; + + const emailArray = [email]; + + Office.context.mailbox.item.cc.setAsync(emailArray, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Succeeded in setting Cc field."); + } else { + console.error(asyncResult.error); + } + }); +Office.MessageCompose#close:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/25-item-save-and-close/close.yaml + + + Office.context.mailbox.item.close(); +Office.MessageCompose#closeAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/25-item-save-and-close/close-async.yaml + + + // This snippet closes the current message being composed and discards any + unsaved changes when the optional property, discardItem, is set to true. + + // The API call works on a new message being composed, a reply, or an + existing draft. + + // When discardItem is set to false or isn't defined on a new message with + unsaved changes, the user is prompted to save a draft, discard the changes, + or cancel the close operation. + + Office.context.mailbox.item.closeAsync( + { discardItem: true }, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + }); +Office.MessageCompose#conversationId:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-conversation-id-message.yaml + + + console.log(`Conversation ID: + ${Office.context.mailbox.item.conversationId}`); +Office.MessageCompose#delayDeliveryTime:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/delay-message-delivery.yaml + + + function setDeliveryDate(minutes) { + // This snippet sets the delivery date and time of a message. + const currentTime = new Date().getTime(); + const milliseconds = totalDelay * 60000; + const timeDelay = new Date(currentTime + milliseconds); + Office.context.mailbox.item.delayDeliveryTime.setAsync(timeDelay, (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + if (minutes === 1440) { + console.log(`Delayed delivery by an additional one day.`); + } else { + console.log(`Delayed delivery by an additional ${minutes} minutes.`); + } + }); + } +Office.MessageCompose#disableClientSignatureAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + + + // Disable the client signature. + + Office.context.mailbox.item.disableClientSignatureAsync(function(asyncResult) + { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("disableClientSignatureAsync succeeded"); + } else { + console.error(asyncResult.error); + } + }); +Office.MessageCompose#from:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-from-message-compose.yaml + + + Office.context.mailbox.item.from.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const msgFrom = asyncResult.value; + console.log("Message from: " + msgFrom.displayName + " (" + msgFrom.emailAddress + ")"); + } else { + console.error(asyncResult.error); + } + }); +Office.MessageCompose#getAttachmentContentAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachment-content.yaml + + + // Gets the attachments of the current message or appointment in compose + mode. The getAttachmentsAsync call can only be used in compose mode. + + Office.context.mailbox.item.getAttachmentsAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.log(result.error.message); + return; + } + + if (result.value.length <= 0) { + console.log("Mail item has no attachments."); + return; + } + + for (let i = 0; i < result.value.length; i++) { + // Log the attachment type and its contents to the console. + Office.context.mailbox.item.getAttachmentContentAsync(result.value[i].id, handleAttachmentsCallback); + } + }); +Office.MessageCompose#getAttachmentsAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + + + Office.context.mailbox.item.getAttachmentsAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(result.error.message); + return; + } + + if (result.value.length > 0) { + for (let i = 0; i < result.value.length; i++) { + const attachment = result.value[i]; + let attachmentType; + switch (attachment.attachmentType) { + case Office.MailboxEnums.AttachmentType.Cloud: + attachmentType = "Attachment is stored in a cloud location"; + break; + case Office.MailboxEnums.AttachmentType.File: + attachmentType = "Attachment is a file"; + break; + case Office.MailboxEnums.AttachmentType.Item: + attachmentType = "Attachment is an Exchange item"; + break; + } + console.log( + "ID: " + + attachment.id + + "\n" + + "Type: " + + attachmentType + + "\n" + + "Name: " + + attachment.name + + "\n" + + "Size: " + + attachment.size + + "\n" + + "isInline: " + + attachment.isInline + ); + } + } else { + console.log("No attachments on this message."); + } + }); +Office.MessageCompose#getComposeTypeAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + + + // Get the compose type of the current message. + + Office.context.mailbox.item.getComposeTypeAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log( + "getComposeTypeAsync succeeded with composeType: " + + asyncResult.value.composeType + + " and coercionType: " + + asyncResult.value.coercionType + ); + } else { + console.error(asyncResult.error); + } + }); +Office.MessageCompose#getConversationIndexAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-conversation-index.yaml + + + // This snippet returns the Base64-encoded position of the current message + in a conversation thread (PR_CONVERSATION_INDEX). + + // The API call is supported on a message being composed and isn't supported + on read items or appointments. + + Office.context.mailbox.item.getConversationIndexAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.log(result.error.message); + return; + } + + const conversationIndex = result.value; + if (conversationIndex) { + console.log("Position in the conversation thread: " + conversationIndex); + } else { + console.log("The current message doesn't belong to a conversation thread."); + } + }); +Office.MessageCompose#getItemClassAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-class-async.yaml + + + // This snippet returns the Exchange Web Services item class property + (PR_MESSAGE_CLASS) of the current message. + + // The API call is only supported on a message being composed. + + Office.context.mailbox.item.getItemClassAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + + console.log("Item class of the current message: " + asyncResult.value); + }); +Office.MessageCompose#getItemIdAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/item-id-compose.yaml + + + Office.context.mailbox.item.getItemIdAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`getItemIdAsync failed with message: ${result.error.message}`); + return; + } + + console.log(result.value); + }); +Office.MessageCompose#getSelectedDataAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/get-selected-data.yaml + + + Office.context.mailbox.item.getSelectedDataAsync(Office.CoercionType.Text, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const text = asyncResult.value.data; + const prop = asyncResult.value.sourceProperty; + console.log("Selected text in " + prop + ": " + text); + } else { + console.error(asyncResult.error); + } + }); +Office.MessageCompose#getSharedPropertiesAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + + + Office.context.mailbox.item.getSharedPropertiesAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error("The current folder or mailbox isn't shared."); + return; + } + const sharedProperties = result.value; + console.log(`Owner: ${sharedProperties.owner}`); + console.log(`Permissions: ${sharedProperties.delegatePermissions}`); + console.log(`Target mailbox: ${sharedProperties.targetMailbox}`); + }); +Office.MessageCompose#inReplyTo:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-in-reply-to.yaml + + + // This snippet gets the ID of the message being replied to by the current + message (PR_IN_REPLY_TO_ID). + + // The API call is supported on messages being composed and isn't supported + on read items. + + const inReplyTo = Office.context.mailbox.item.inReplyTo; + + if (inReplyTo) { + console.log("ID of the message being replied to: " + inReplyTo); + } else { + console.log("No InReplyTo property available for this message"); + } +Office.MessageCompose#internetHeaders:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml + + + Office.context.mailbox.item.internetHeaders.getAsync( + ["preferred-fruit", "preferred-vegetable", "best-vegetable", "nonexistent-header"], + function (asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Selected headers: " + JSON.stringify(asyncResult.value)); + } else { + console.log("Error getting selected headers: " + JSON.stringify(asyncResult.error)); + } + } + ); +Office.MessageCompose#isClientSignatureEnabledAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + + + // Check if the client signature is currently enabled. + + Office.context.mailbox.item.isClientSignatureEnabledAsync(function(asyncResult) + { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("isClientSignatureEnabledAsync succeeded with result: " + asyncResult.value); + } else { + console.error(asyncResult.error); + } + }); +Office.MessageCompose#itemType:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-type.yaml + + + const itemType = Office.context.mailbox.item.itemType; + + switch (itemType) { + case Office.MailboxEnums.ItemType.Appointment: + console.log(`Current item is an ${itemType}.`); + break; + case Office.MailboxEnums.ItemType.Message: + console.log(`Current item is a ${itemType}. A message could be an email, meeting request, meeting response, or meeting cancellation.`); + break; + } +Office.MessageCompose#loadCustomPropertiesAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + + + Office.context.mailbox.item.loadCustomPropertiesAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`loadCustomPropertiesAsync failed with message ${result.error.message}`); + return; + } + + customProps = result.value; + console.log("Loaded the CustomProperties object."); + }); +Office.MessageCompose#notificationMessages:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds a progress indicator to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.ProgressIndicator, + message: "Progress indicator with id = " + id + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds an informational notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Non-persistent informational notification message with id = " + id, + icon: "PG.Icon.16", + persistent: false + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds a persistent information notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Persistent informational notification message with id = " + id, + icon: "PG.Icon.16", + persistent: true + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Gets all the notification messages and their keys for the current mail + item. + + Office.context.mailbox.item.notificationMessages.getAllAsync((asyncResult) + => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + console.log(asyncResult.value); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Replaces a notification message of a given key with another message. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + Office.context.mailbox.item.notificationMessages.replaceAsync( + id, + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Notification message with id = " + id + " has been replaced with an informational message.", + icon: "icon2", + persistent: false + }, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Removes a notification message from the current mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + Office.context.mailbox.item.notificationMessages.removeAsync(id, + handleResult); +Office.MessageCompose#removeAttachmentAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + + + Office.context.mailbox.item.removeAttachmentAsync( + (document.getElementById("attachmentId") as HTMLInputElement).value, + (result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(result.error.message); + return; + } + + console.log(`Attachment removed successfully.`); + } + ); +Office.MessageCompose#sendAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/send-async.yaml + + + // This snippet sends the current message or appointment being composed. + + Office.context.mailbox.item.sendAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Action failed with error: " + asyncResult.error.message); + return; + } + }); +Office.MessageCompose#sensitivityLabel:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/60-sensitivity-label/sensitivity-label.yaml + + + // This snippet gets the current mail item's sensitivity label. + + Office.context.sensitivityLabelsCatalog.getIsEnabledAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded && asyncResult.value == true) { + Office.context.mailbox.item.sensitivityLabel.getAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(asyncResult.value); + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); +Office.MessageCompose#seriesId:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-series-id.yaml + + + const seriesId = Office.context.mailbox.item.seriesId; + + + if (seriesId === undefined) { + console.log("This is a message that's not a meeting request."); + } else if (seriesId === null) { + console.log("This is a single appointment, a parent series, or a meeting request for a series or single meeting."); + } else { + console.log("This is an instance belonging to series with ID " + seriesId); + } +Office.MessageCompose#sessionData:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + + + Office.context.mailbox.item.sessionData.getAllAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("The sessionData is " + JSON.stringify(asyncResult.value)); + } else { + console.log("Failed to get all sessionData. Error: " + JSON.stringify(asyncResult.error)); + } + }); +Office.MessageCompose#setSelectedDataAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/set-selected-data.yaml + + + Office.context.mailbox.item.setSelectedDataAsync("Replaced", + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Selected text has been updated successfully."); + } else { + console.error(asyncResult.error); + } + }); +Office.MessageCompose#subject:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-subject-compose.yaml + + + Office.context.mailbox.item.subject.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Subject: ${result.value}`); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-subject-compose.yaml + + + let subject = "Hello World!"; + + Office.context.mailbox.item.subject.setAsync(subject, (result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Successfully set subject to ${subject}`); + }); +Office.MessageCompose#to:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-to-message-compose.yaml + + + Office.context.mailbox.item.to.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const msgTo = asyncResult.value; + console.log("Message being sent to:"); + for (let i = 0; i < msgTo.length; i++) { + console.log(msgTo[i].displayName + " (" + msgTo[i].emailAddress + ")"); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-to-message-compose.yaml + + + const email = (document.getElementById("emailTo") as + HTMLInputElement).value; + + const emailArray = [email]; + + Office.context.mailbox.item.to.setAsync(emailArray, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Succeeded in setting To field."); + } else { + console.error(asyncResult.error); + } + }); +Office.MessageRead:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachments-read.yaml + + + const item = Office.context.mailbox.item; + + + if (item.attachments.length > 0) { + for (let i = 0; i < item.attachments.length; i++) { + const attachment = item.attachments[i]; + console.log(`${i+1}. Name: ${attachment.name}`); + console.log(`ID: ${attachment.id}`); + console.log(`Type: ${attachment.attachmentType}`); + console.log(`Inline content: ${attachment.isInline}`); + console.log(`Size: ${attachment.size}`); + } + } else { + console.log("This mail item doesn't contain any attachments."); + } +Office.MessageRead#attachments:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachments-read.yaml + + + const item = Office.context.mailbox.item; + + + if (item.attachments.length > 0) { + for (let i = 0; i < item.attachments.length; i++) { + const attachment = item.attachments[i]; + console.log(`${i+1}. Name: ${attachment.name}`); + console.log(`ID: ${attachment.id}`); + console.log(`Type: ${attachment.attachmentType}`); + console.log(`Inline content: ${attachment.isInline}`); + console.log(`Size: ${attachment.size}`); + } + } else { + console.log("This mail item doesn't contain any attachments."); + } +Office.MessageRead#categories:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + Office.context.mailbox.item.categories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + console.log("Categories assigned to this item:"); + console.log(JSON.stringify(categories)); + } else { + console.log("There are no categories assigned to this item."); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + // Note: In order for you to successfully add a category, + + // it must be in the mailbox categories master list. + + + Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const masterCategories = asyncResult.value; + if (masterCategories && masterCategories.length > 0) { + // Grab the first category from the master list. + const categoryToAdd = [masterCategories[0].displayName]; + Office.context.mailbox.item.categories.addAsync(categoryToAdd, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully assigned category '${categoryToAdd}' to item.`); + } else { + console.log("categories.addAsync call failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("There are no categories in the master list on this mailbox. You can add categories using Office.context.mailbox.masterCategories.addAsync."); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + + + Office.context.mailbox.item.categories.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const categories = asyncResult.value; + if (categories && categories.length > 0) { + // Grab the first category assigned to this item. + const categoryToRemove = [categories[0].displayName]; + Office.context.mailbox.item.categories.removeAsync(categoryToRemove, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(`Successfully unassigned category '${categoryToRemove}' from this item.`); + } else { + console.log("categories.removeAsync call failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("There are no categories assigned to this item."); + } + } else { + console.error(asyncResult.error); + } + }); +Office.MessageRead#cc:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-cc-message-read.yaml + + + const msgCc = Office.context.mailbox.item.cc; + + console.log("Message copied to:"); + + for (let i = 0; i < msgCc.length; i++) { + console.log(msgCc[i].displayName + " (" + msgCc[i].emailAddress + ")"); + } +Office.MessageRead#conversationId:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-conversation-id-message.yaml + + + console.log(`Conversation ID: + ${Office.context.mailbox.item.conversationId}`); +Office.MessageRead#dateTimeCreated:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-date-time-created-read.yaml + + + console.log(`Creation date and time: + ${Office.context.mailbox.item.dateTimeCreated}`); +Office.MessageRead#dateTimeModified:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-date-time-modified-read.yaml + + + console.log(`Date and time item last modified: + ${Office.context.mailbox.item.dateTimeModified}`); +Office.MessageRead#display:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml + + + // This snippet temporarily sets the content displayed in the body of a + message in read mode. + + // The set content will remain visible until the user switches to a + different message in the Reading Pane or closes the window of the current + message. + + const bodyText = (document.getElementById("body-text-field") as + HTMLInputElement).value; + + Office.context.mailbox.item.display.body.setAsync(bodyText, (asyncResult) => + { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Action failed with error: ${asyncResult.error.message}`); + return; + } + + console.log("Temporarily set the content displayed in the body."); + }); +Office.MessageRead#displayReplyAllForm:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + + + Office.context.mailbox.item.displayReplyAllForm("This is a reply ALL with + some bold text."); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + + + // Define attachments. + + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + + // Create the reply with attachments. + + Office.context.mailbox.item.displayReplyAllForm({ + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment], + callback: (result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + + console.log("Created a reply-all form with attachments."); + } + }); +Office.MessageRead#displayReplyAllFormAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + + + Office.context.mailbox.item.displayReplyAllFormAsync("This is a reply ALL + with some bold text.", function( + asyncResult + ) { + console.log(JSON.stringify(asyncResult)); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + + + // Define attachments. + + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + + // The async version was introduced in requirement set 1.9. + + // It provides a callback when the new appointment form has been created. + + Office.context.mailbox.item.displayReplyAllFormAsync( + { + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment] + }, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${asyncResult.error.message}`); + return; + } + + console.log("Created a reply-all form with attachments."); + } + ); +Office.MessageRead#displayReplyForm:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + + + Office.context.mailbox.item.displayReplyForm("This is a reply with some + text in italics."); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + + + // Define attachments. + + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + + // Create the reply with attachments. + + Office.context.mailbox.item.displayReplyForm({ + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment], + callback: (result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + + console.log("Created a reply with attachments."); + } + }); +Office.MessageRead#displayReplyFormAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + + + Office.context.mailbox.item.displayReplyFormAsync("This is a reply with + some text in italics.", function( + asyncResult + ) { + console.log(JSON.stringify(asyncResult)); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + + + // Define attachments. + + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + + // The async version was introduced in requirement set 1.9. + + // It provides a callback when the new appointment form has been created. + + Office.context.mailbox.item.displayReplyFormAsync( + { + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment] + }, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${asyncResult.error.message}`); + return; + } + + console.log("Created reply with attachments."); + } + ); +Office.MessageRead#end:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-end-read.yaml + + + console.log(`Appointment ends: ${Office.context.mailbox.item.end}`); +Office.MessageRead#from:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-from-message-read.yaml + + + const msgFrom = Office.context.mailbox.item.from; + + console.log("Message received from: " + msgFrom.displayName + " (" + + msgFrom.emailAddress + ")"); +Office.MessageRead#getAllInternetHeadersAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/get-internet-headers-message-read.yaml + + + Office.context.mailbox.item.getAllInternetHeadersAsync(function + (asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Internet headers received successfully"); + if (asyncResult.value.match(/preferred-fruit:.*/gim)) { + console.log("Sender's preferred fruit: " + asyncResult.value.match(/preferred-fruit:.*/gim)[0].slice(17)); + } else { + console.log("Didn't receive header with sender's preferred fruit"); + } + if (asyncResult.value.match(/preferred-vegetable:.*/gim)) { + console.log( + "Sender's preferred vegetable: " + asyncResult.value.match(/preferred-vegetable:.*/gim)[0].slice(21) + ); + } else { + console.log("Didn't receive header with sender's preferred vegetable"); + } + } else { + console.log("Error getting internet headers: " + JSON.stringify(asyncResult.error)); + } + }); +Office.MessageRead#getAsFileAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-eml-format.yaml + + + Office.context.mailbox.item.getAsFileAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(`Error encountered during processing: ${asyncResult.error.message}`); + return; + } + + console.log(asyncResult.value); + }); +Office.MessageRead#getAttachmentContentAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachment-content.yaml + + + // Gets the attachments of the current message or appointment in read mode. + The item.attachments call can only be used in read mode. + + const item = Office.context.mailbox.item; + + const attachments = item.attachments; + + if (attachments.length <= 0) { + console.log("Mail item has no attachments."); + return; + } + + + for (let i = 0; i < attachments.length; i++) { + // Log the attachment type and its contents to the console. + item.getAttachmentContentAsync(attachments[i].id, handleAttachmentsCallback); + } +Office.MessageRead#getRegExMatches:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-regex-matches/contextual.yaml + + + // This API only works when you click on the highlighted word "ScriptLab". + + console.log(Office.context.mailbox.item.getRegExMatches()); +Office.MessageRead#getRegExMatchesByName:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-regex-matches/contextual.yaml + + + // This API only works when you click on the highlighted word "ScriptLab". + + console.log(Office.context.mailbox.item.getRegExMatchesByName("sampleRegexName")); +Office.MessageRead#getSelectedRegExMatches:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-regex-matches/contextual.yaml + + + const matches = Office.context.mailbox.item.getSelectedRegExMatches(); + + if (matches) { + console.log(matches); + } else { + console.error("Open add-in by clicking on a highlighted regex match, for this API to return something useful."); + } +Office.MessageRead#getSharedPropertiesAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + + + Office.context.mailbox.item.getSharedPropertiesAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error("The current folder or mailbox isn't shared."); + return; + } + const sharedProperties = result.value; + console.log(`Owner: ${sharedProperties.owner}`); + console.log(`Permissions: ${sharedProperties.delegatePermissions}`); + console.log(`Target mailbox: ${sharedProperties.targetMailbox}`); + }); +Office.MessageRead#internetMessageId:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-internet-message-id-read.yaml + + + console.log(`Internet message ID: + ${Office.context.mailbox.item.internetMessageId}`); +Office.MessageRead#itemClass:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-class-read.yaml + + + console.log(`Item class: ${Office.context.mailbox.item.itemClass}`); +Office.MessageRead#itemType:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-type.yaml + + + const itemType = Office.context.mailbox.item.itemType; + + switch (itemType) { + case Office.MailboxEnums.ItemType.Appointment: + console.log(`Current item is an ${itemType}.`); + break; + case Office.MailboxEnums.ItemType.Message: + console.log(`Current item is a ${itemType}. A message could be an email, meeting request, meeting response, or meeting cancellation.`); + break; + } +Office.MessageRead#loadCustomPropertiesAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + + + Office.context.mailbox.item.loadCustomPropertiesAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error(`loadCustomPropertiesAsync failed with message ${result.error.message}`); + return; + } + + customProps = result.value; + console.log("Loaded the CustomProperties object."); + }); +Office.MessageRead#location:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-location-read.yaml + + + console.log(`Appointment location: + ${Office.context.mailbox.item.location}`); +Office.MessageRead#normalizedSubject:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-normalized-subject-read.yaml + + + console.log(`Normalized subject: + ${Office.context.mailbox.item.normalizedSubject}`); +Office.MessageRead#notificationMessages:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds a progress indicator to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.ProgressIndicator, + message: "Progress indicator with id = " + id + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds an informational notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Non-persistent informational notification message with id = " + id, + icon: "PG.Icon.16", + persistent: false + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds a persistent information notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Persistent informational notification message with id = " + id, + icon: "PG.Icon.16", + persistent: true + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Gets all the notification messages and their keys for the current mail + item. + + Office.context.mailbox.item.notificationMessages.getAllAsync((asyncResult) + => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + console.log(asyncResult.value); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Replaces a notification message of a given key with another message. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + Office.context.mailbox.item.notificationMessages.replaceAsync( + id, + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Notification message with id = " + id + " has been replaced with an informational message.", + icon: "icon2", + persistent: false + }, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Removes a notification message from the current mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + Office.context.mailbox.item.notificationMessages.removeAsync(id, + handleResult); +Office.MessageRead#recurrence:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-recurrence-read.yaml + + + const recurrence = Office.context.mailbox.item.recurrence; + + + if (recurrence === undefined) { + console.log("This item is a message but not a meeting request."); + } else if (recurrence === null) { + console.log("This is a single appointment."); + } else { + console.log(JSON.stringify(recurrence)); + } +Office.MessageRead#sender:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-sender-message-read.yaml + + + const msgSender = Office.context.mailbox.item.sender; + + console.log("Sender: " + msgSender.displayName + " (" + + msgSender.emailAddress + ")"); +Office.MessageRead#seriesId:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-series-id.yaml + + + const seriesId = Office.context.mailbox.item.seriesId; + + + if (seriesId === undefined) { + console.log("This is a message that's not a meeting request."); + } else if (seriesId === null) { + console.log("This is a single appointment, a parent series, or a meeting request for a series or single meeting."); + } else { + console.log("This is an instance belonging to series with ID " + seriesId); + } +Office.MessageRead#start:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-start-read.yaml + + + console.log(`Appointment starts: ${Office.context.mailbox.item.start}`); +Office.MessageRead#subject:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-subject-read.yaml + + + console.log(`Subject: ${Office.context.mailbox.item.subject}`); +Office.MessageRead#to:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-to-message-read.yaml + + + const msgTo = Office.context.mailbox.item.to; + + const distributionLists = []; + + const externalRecipients = []; + + const internalRecipients = []; + + const otherRecipients = []; + + for (let i = 0; i < msgTo.length; i++) { + switch (msgTo[i].recipientType) { + case Office.MailboxEnums.RecipientType.DistributionList: + distributionLists.push(msgTo[i]); + break; + case Office.MailboxEnums.RecipientType.ExternalUser: + externalRecipients.push(msgTo[i]); + break; + case Office.MailboxEnums.RecipientType.User: + internalRecipients.push(msgTo[i]); + break; + case Office.MailboxEnums.RecipientType.Other: + otherRecipients.push(msgTo[i]); + } + } + + + if (distributionLists.length > 0) { + console.log("Distribution Lists:"); + distributionLists.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); + } + + + if (externalRecipients.length > 0) { + console.log("External Recipients:"); + externalRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); + } + + + if (internalRecipients.length > 0) { + console.log("Internal Recipients:"); + internalRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); + } + + + if (otherRecipients.length > 0) { + console.log("Other Recipients:"); + otherRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); + } +Office.NotificationMessageAction:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds an informational message with actions to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + + const itemId = Office.context.mailbox.item.itemId; + + const details = { + type: Office.MailboxEnums.ItemNotificationMessageType.InsightMessage, + message: "This is an insight notification with id = " + id, + icon: "PG.Icon.16", + actions: [ + { + actionText: "Open insight", + actionType: Office.MailboxEnums.ActionType.ShowTaskPane, + // Identify whether the current mail item is in read or compose mode to set the appropriate commandId value. + commandId: (itemId == undefined ? "PG.HelpCommand.Compose" : "PG.HelpCommand.Read"), + contextData: { a: "aValue", b: "bValue" } + } + ] + }; + + + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); +Office.NotificationMessageDetails:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Gets all the notification messages and their keys for the current mail + item. + + Office.context.mailbox.item.notificationMessages.getAllAsync((asyncResult) + => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + console.log(asyncResult.value); + }); +Office.NotificationMessages#addAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds a progress indicator to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.ProgressIndicator, + message: "Progress indicator with id = " + id + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds an informational notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Non-persistent informational notification message with id = " + id, + icon: "PG.Icon.16", + persistent: false + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds a persistent information notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Persistent informational notification message with id = " + id, + icon: "PG.Icon.16", + persistent: true + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Adds an error notification to the mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + const details = + { + type: Office.MailboxEnums.ItemNotificationMessageType.ErrorMessage, + message: "Error notification message with id = " + id + }; + Office.context.mailbox.item.notificationMessages.addAsync(id, details, + handleResult); +Office.NotificationMessages#getAllAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Gets all the notification messages and their keys for the current mail + item. + + Office.context.mailbox.item.notificationMessages.getAllAsync((asyncResult) + => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + console.log(asyncResult.value); + }); +Office.NotificationMessages#removeAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Removes a notification message from the current mail item. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + Office.context.mailbox.item.notificationMessages.removeAsync(id, + handleResult); +Office.NotificationMessages#replaceAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + + + // Replaces a notification message of a given key with another message. + + const id = (document.getElementById("notificationId") as + HTMLInputElement).value; + + Office.context.mailbox.item.notificationMessages.replaceAsync( + id, + { + type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, + message: "Notification message with id = " + id + " has been replaced with an informational message.", + icon: "icon2", + persistent: false + }, + handleResult); +Office.Organizer#getAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-organizer-appointment-organizer.yaml + + + Office.context.mailbox.item.organizer.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const apptOrganizer = asyncResult.value; + console.log("Organizer: " + apptOrganizer.displayName + " (" + apptOrganizer.emailAddress + ")"); + } else { + console.error(asyncResult.error); + } + }); +Office.Recipients#getAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-bcc-message-compose.yaml + + + Office.context.mailbox.item.bcc.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const msgBcc = asyncResult.value; + console.log("Message being blind-copied to:"); + for (let i = 0; i < msgBcc.length; i++) { + console.log(msgBcc[i].displayName + " (" + msgBcc[i].emailAddress + ")"); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-cc-message-compose.yaml + + + Office.context.mailbox.item.cc.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const msgCc = asyncResult.value; + console.log("Message being copied to:"); + for (let i = 0; i < msgCc.length; i++) { + console.log(msgCc[i].displayName + " (" + msgCc[i].emailAddress + ")"); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-optional-attendees-appointment-organizer.yaml + + + Office.context.mailbox.item.optionalAttendees.getAsync(function(asyncResult) + { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const apptOptionalAttendees = asyncResult.value; + for (let i = 0; i < apptOptionalAttendees.length; i++) { + console.log( + "Optional attendees: " + + apptOptionalAttendees[i].displayName + + " (" + + apptOptionalAttendees[i].emailAddress + + ") - response: " + + apptOptionalAttendees[i].appointmentResponse + ); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-required-attendees-appointment-organizer.yaml + + + Office.context.mailbox.item.requiredAttendees.getAsync(function(asyncResult) + { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const apptRequiredAttendees = asyncResult.value; + for (let i = 0; i < apptRequiredAttendees.length; i++) { + console.log( + "Required attendees: " + + apptRequiredAttendees[i].displayName + + " (" + + apptRequiredAttendees[i].emailAddress + + ") - response: " + + apptRequiredAttendees[i].appointmentResponse + ); + } + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-to-message-compose.yaml + + + Office.context.mailbox.item.to.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const msgTo = asyncResult.value; + console.log("Message being sent to:"); + for (let i = 0; i < msgTo.length; i++) { + console.log(msgTo[i].displayName + " (" + msgTo[i].emailAddress + ")"); + } + } else { + console.error(asyncResult.error); + } + }); +Office.Recipients#setAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-bcc-message-compose.yaml + + + const email = (document.getElementById("emailBcc") as + HTMLInputElement).value; + + const emailArray = [email]; + + Office.context.mailbox.item.bcc.setAsync(emailArray, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Succeeded in setting Bcc field."); + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-cc-message-compose.yaml + + + const email = (document.getElementById("emailCc") as + HTMLInputElement).value; + + const emailArray = [email]; + + Office.context.mailbox.item.cc.setAsync(emailArray, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Succeeded in setting Cc field."); + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-optional-attendees-appointment-organizer.yaml + + + const email = (document.getElementById("emailOptional") as + HTMLInputElement).value; + + const emailArray = [email]; + + Office.context.mailbox.item.optionalAttendees.setAsync(emailArray, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Succeeded in setting optional attendees field."); + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-required-attendees-appointment-organizer.yaml + + + const email = (document.getElementById("emailRequired") as + HTMLInputElement).value; + + const emailArray = [email]; + + Office.context.mailbox.item.requiredAttendees.setAsync(emailArray, + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Succeeded in setting required attendees field."); + } else { + console.error(asyncResult.error); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-to-message-compose.yaml + + + const email = (document.getElementById("emailTo") as + HTMLInputElement).value; + + const emailArray = [email]; + + Office.context.mailbox.item.to.setAsync(emailArray, function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Succeeded in setting To field."); + } else { + console.error(asyncResult.error); + } + }); +Office.Recurrence#getAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + + + Office.context.mailbox.item.recurrence.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const recurrence = asyncResult.value; + if (recurrence === null) { + console.log("This is a single appointment."); + } else { + console.log(`Recurrence pattern: ${JSON.stringify(recurrence)}`); + } + } else { + console.error(asyncResult.error); + } + }); +Office.Recurrence#setAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + + + // Important: Can only set the recurrence pattern of an appointment series. + + + const currentDate = new Date(); + + let seriesTimeObject: Office.SeriesTime; + + // Set series start date to tomorrow. + + seriesTimeObject.setStartDate(currentDate.getFullYear(), + currentDate.getMonth(), currentDate.getDay() + 1); + + // Set series end date to one year from now. + + seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, + currentDate.getMonth() + 1, currentDate.getDay()); + + // Set start time to 1:30 PM. + + seriesTimeObject.setStartTime(13, 30); + + // Set duration to 30 minutes. + + seriesTimeObject.setDuration(30); + + + const pattern: Office.Recurrence = { + seriesTime: seriesTimeObject, + recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, + recurrenceProperties: { + interval: 1, + dayOfWeek: Office.MailboxEnums.Days.Tue, + weekNumber: Office.MailboxEnums.WeekNumber.Second, + month: Office.MailboxEnums.Month.Sep + }, + recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } + }; + + + Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { + if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); + return; + } + console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); + }); +Office.ReplyFormAttachment:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + + + // Define attachments. + + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + + // The async version was introduced in requirement set 1.9. + + // It provides a callback when the new appointment form has been created. + + Office.context.mailbox.item.displayReplyFormAsync( + { + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment] + }, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${asyncResult.error.message}`); + return; + } + + console.log("Created reply with attachments."); + } + ); +Office.ReplyFormData:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + + + // Define attachments. + + const base64Attachment = { + base64file: + "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", + inLine: true, + name: "script_lab.png", + type: Office.MailboxEnums.AttachmentType.Base64 + }; + + const fileAttachment = { + inLine: true, + name: "dog.jpg", + type: Office.MailboxEnums.AttachmentType.File, + url: "https://i.imgur.com/9S36xvA.jpg" + }; + + const itemAttachment = { + itemId: Office.context.mailbox.item.itemId, + name: "test_email.msg", + type: Office.MailboxEnums.AttachmentType.Item + }; + + + // The async version was introduced in requirement set 1.9. + + // It provides a callback when the new appointment form has been created. + + Office.context.mailbox.item.displayReplyFormAsync( + { + htmlBody: + "This is a reply with an inline Base64-encoded attachment, an inline image, and an item attachment.

", + attachments: [base64Attachment, fileAttachment, itemAttachment] + }, + (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.error(`Action failed with message ${asyncResult.error.message}`); + return; + } + + console.log("Created reply with attachments."); + } + ); +Office.RoamingSettings#get:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/10-roaming-settings/roaming-settings.yaml + + + const settingName = (document.getElementById("settingName") as + HTMLInputElement).value; + + const settingValue = Office.context.roamingSettings.get(settingName); + + (document.getElementById("settingValue") as HTMLInputElement).value = + settingValue; + + console.log(`The value of setting "${settingName}" is "${settingValue}".`); +Office.RoamingSettings#remove:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/10-roaming-settings/roaming-settings.yaml + + + // Remove the specified setting from the mailbox. + + const settingName = (document.getElementById("settingName") as + HTMLInputElement).value; + + Office.context.roamingSettings.remove(settingName); + + console.log(`The "${settingName}" setting has been removed.`); +Office.RoamingSettings#saveAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/10-roaming-settings/roaming-settings.yaml + + + // Save settings in the mailbox to make it available in future sessions. + + Office.context.roamingSettings.saveAsync(function(result) { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + } else { + console.log(`Settings saved with status: ${result.status}`); + } + }); +Office.RoamingSettings#set:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/10-roaming-settings/roaming-settings.yaml + + + const settingName = (document.getElementById("settingName") as + HTMLInputElement).value; + + const settingValue = (document.getElementById("settingValue") as + HTMLInputElement).value; + + Office.context.roamingSettings.set(settingName, settingValue); + + console.log(`Setting "${settingName}" set to value "${settingValue}".`); +Office.SelectedItemDetails:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-message-properties.yaml + + + // Retrieves the selected messages' properties and logs them to the console. + + Office.context.mailbox.getSelectedItemsAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log(asyncResult.error.message); + return; + } + + asyncResult.value.forEach((message) => { + console.log(`Item ID: ${message.itemId}`); + console.log(`Conversation ID: ${message.conversationId}`); + console.log(`Internet message ID: ${message.internetMessageId}`); + console.log(`Subject: ${message.subject}`); + console.log(`Item type: ${message.itemType}`); + console.log(`Item mode: ${message.itemMode}`); + console.log(`Has attachment: ${message.hasAttachment}`); + }); + }); +Office.Sensitivity#getAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-sensitivity-level.yaml + + + Office.context.mailbox.item.sensitivity.getAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("Sensitivity: " + asyncResult.value); + } else { + console.log("Failed to get sensitivity: " + JSON.stringify(asyncResult.error)); + } + }); +Office.Sensitivity#setAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-sensitivity-level.yaml + + + Office.context.mailbox.item.sensitivity.setAsync( + Office.MailboxEnums.AppointmentSensitivityType.Private, + function callback(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Failed) { + console.log("Failed to set appointment sensitivity: " + JSON.stringify(asyncResult.error)); + } else { + console.log("Successfully set appointment sensitivity."); + } + } + ); +Office.SensitivityLabel#getAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/60-sensitivity-label/sensitivity-label.yaml + + + // This snippet gets the current mail item's sensitivity label. + + Office.context.sensitivityLabelsCatalog.getIsEnabledAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded && asyncResult.value == true) { + Office.context.mailbox.item.sensitivityLabel.getAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(asyncResult.value); + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); +Office.SensitivityLabel#setAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/60-sensitivity-label/sensitivity-label.yaml + + + // This snippet sets the sensitivity label on the current mail item. + + Office.context.sensitivityLabelsCatalog.getIsEnabledAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded && asyncResult.value == true) { + Office.context.sensitivityLabelsCatalog.getAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const catalog = asyncResult.value; + if (catalog.length > 0) { + var id = catalog[0].id; + Office.context.mailbox.item.sensitivityLabel.setAsync(id, (asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(asyncResult.status); + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); + } + else { + console.log("Catalog list is empty"); + } + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); +Office.SensitivityLabelsCatalog#getAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/60-sensitivity-label/sensitivity-labels-catalog.yaml + + + // This snippet gets all available sensitivity labels from the catalog. + + Office.context.sensitivityLabelsCatalog.getIsEnabledAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded && asyncResult.value == true) { + Office.context.sensitivityLabelsCatalog.getAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + const catalog = asyncResult.value; + console.log("Sensitivity Labels Catalog:"); + console.log(JSON.stringify(catalog)); + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); +Office.SensitivityLabelsCatalog#getIsEnabledAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/60-sensitivity-label/sensitivity-labels-catalog.yaml + + + // This snippet determines if the sensitivity labels catalog is enabled on + the current mailbox. + + Office.context.sensitivityLabelsCatalog.getIsEnabledAsync((asyncResult) => { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log(asyncResult.value); + } else { + console.log("Action failed with error: " + asyncResult.error.message); + } + }); +Office.SessionData#clearAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + + + Office.context.mailbox.item.sessionData.clearAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("sessionData.clearAsync succeeded"); + } else { + console.log("Failed to clear sessionData. Error: " + JSON.stringify(asyncResult.error)); + } + }); +Office.SessionData#getAllAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + + + Office.context.mailbox.item.sessionData.getAllAsync(function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("The sessionData is " + JSON.stringify(asyncResult.value)); + } else { + console.log("Failed to get all sessionData. Error: " + JSON.stringify(asyncResult.error)); + } + }); +Office.SessionData#getAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + + + Office.context.mailbox.item.sessionData.getAsync( + "Date", + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("The sessionData value is " + JSON.stringify(asyncResult.value)); + } else { + console.log("Failed to get sessionData. Error: " + JSON.stringify(asyncResult.error)); + } + }); +Office.SessionData#removeAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + + + Office.context.mailbox.item.sessionData.removeAsync( + "Date", + function callback(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("sessionData.removeAsync succeeded"); + } else { + console.log("Failed to remove sessionData. Error: " + JSON.stringify(asyncResult.error)); + } + } + ); +Office.SessionData#setAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + + + Office.context.mailbox.item.sessionData.setAsync( + "Date", + "7/24/2020", + function(asyncResult) { + if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { + console.log("sessionData.setAsync succeeded"); + } else { + console.log("Failed to set sessionData. Error: " + JSON.stringify(asyncResult.error)); + } + }); +Office.SharedProperties:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + + + Office.context.mailbox.item.getSharedPropertiesAsync((result) => { + if (result.status === Office.AsyncResultStatus.Failed) { + console.error("The current folder or mailbox isn't shared."); + return; + } + const sharedProperties = result.value; + console.log(`Owner: ${sharedProperties.owner}`); + console.log(`Permissions: ${sharedProperties.delegatePermissions}`); + console.log(`Target mailbox: ${sharedProperties.targetMailbox}`); + }); +Office.Time#getAsync:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml + + + Office.context.mailbox.item.start.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Appointment starts: ${result.value}`); + }); +Office.Time#setAsync:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml + + + const start = new Date(); // Represents current date and time. + + start.setDate(start.getDate() + 2); // Add 2 days to current date. + + Office.context.mailbox.item.start.setAsync(start, (result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Action failed with message ${result.error.message}`); + return; + } + console.log(`Successfully set start date and time to ${start}`); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-end-appointment-organizer.yaml + + + Office.context.mailbox.item.start.getAsync((result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Get start date failed with message ${result.error.message}`); + return; + } + + const end = result.value; // Set end to current start date and time. + end.setDate(end.getDate() + 1); // Set end as 1 day later than start date. + Office.context.mailbox.item.end.setAsync(end, (result) => { + if (result.status !== Office.AsyncResultStatus.Succeeded) { + console.error(`Set end date failed with message ${result.error.message}`); + return; + } + console.log(`Successfully set end date and time to ${end}`); + }); + }); +PowerPoint.AddSlideOptions:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml + + + const chosenMaster = (document.getElementById("master-id") as + HTMLInputElement).value; + + const chosenLayout = (document.getElementById("layout-id") as + HTMLInputElement).value; + + + await PowerPoint.run(async function(context) { + // Create a new slide using an existing master slide and layout. + const newSlideOptions: PowerPoint.AddSlideOptions = { + slideMasterId: chosenMaster, /* An ID from `Presentation.slideMasters`. */ + layoutId: chosenLayout /* An ID from `SlideMaster.layouts`. */ + }; + context.presentation.slides.add(newSlideOptions); + await context.sync(); + }); +PowerPoint.Binding:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml + + + async function getShapeForBindingId(bindingId: string): + Promise { + // Gets shape associated with binding ID. + return PowerPoint.run(async (context) => { + const binding = context.presentation.bindings.getItem(bindingId); + const shape = binding.getShape(); + return shape; + }); + } +PowerPoint.Binding#getShape:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml + + + async function getShapeForBindingId(bindingId: string): + Promise { + // Gets shape associated with binding ID. + return PowerPoint.run(async (context) => { + const binding = context.presentation.bindings.getItem(bindingId); + const shape = binding.getShape(); + return shape; + }); + } +PowerPoint.BindingCollection:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml + + + // Loads bindings. + + await PowerPoint.run(async (context) => { + const bindings = context.presentation.bindings; + bindings.load("items"); + await context.sync(); + + const bindingCount = bindings.items.length; + if (bindingCount === 0) { + console.log(`There are no bindings.`); + } else if (bindingCount === 1) { + console.log("There's 1 binding."); + } else { + console.log(`There are ${bindingCount} bindings.`); + } + + bindings.items.forEach((binding) => { + getShapeForBindingId(binding.id).then((shape) => { + if (shape) { + console.log(`Binding ID: ${binding.id} refers to shape ID ${shape.id}`); + } else { + console.log(`Binding ID: ${binding.id} doesn't refers to shape.`); + } + }); + }); + + populateBindingsDropdown(bindings.items); + }); +PowerPoint.BindingCollection#add:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml + + + // Inserts an image with binding. + + await PowerPoint.run(async (context) => { + const bindingId = (document.getElementById("temp-binding-id") as HTMLInputElement).value; + const slide = context.presentation.getSelectedSlides().getItemAt(0); + const myShape = slide.shapes.addGeometricShape(PowerPoint.GeometricShapeType.rectangle, { + top: 100, + left: 30, + width: 200, + height: 200 + }); + + myShape.fill.setImage(flowerImage); + context.presentation.bindings.add(myShape, PowerPoint.BindingType.shape, bindingId); + await context.sync(); + + const bindingsDropdown = document.getElementById("bindings-dropdown") as HTMLSelectElement; + + const option = new Option(`Binding ${bindingId}`, bindingId); + + // When a binding ID already exists, the binding is updated to refer to the new shape + // so select the existing item rather than add a new one. + const foundIndex = findDropdownItem(bindingsDropdown, option.text); + if (foundIndex < 0) { + bindingsDropdown.add(option); + bindingsDropdown.selectedIndex = bindingsDropdown.options.length - 1; + } else { + bindingsDropdown.selectedIndex = foundIndex; + } + }); +PowerPoint.BindingCollection#getItem:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml + + + async function getShapeForBindingId(bindingId: string): + Promise { + // Gets shape associated with binding ID. + return PowerPoint.run(async (context) => { + const binding = context.presentation.bindings.getItem(bindingId); + const shape = binding.getShape(); + return shape; + }); + } +PowerPoint.BindingType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml + + + // Inserts an image with binding. + + await PowerPoint.run(async (context) => { + const bindingId = (document.getElementById("temp-binding-id") as HTMLInputElement).value; + const slide = context.presentation.getSelectedSlides().getItemAt(0); + const myShape = slide.shapes.addGeometricShape(PowerPoint.GeometricShapeType.rectangle, { + top: 100, + left: 30, + width: 200, + height: 200 + }); + + myShape.fill.setImage(flowerImage); + context.presentation.bindings.add(myShape, PowerPoint.BindingType.shape, bindingId); + await context.sync(); + + const bindingsDropdown = document.getElementById("bindings-dropdown") as HTMLSelectElement; + + const option = new Option(`Binding ${bindingId}`, bindingId); + + // When a binding ID already exists, the binding is updated to refer to the new shape + // so select the existing item rather than add a new one. + const foundIndex = findDropdownItem(bindingsDropdown, option.text); + if (foundIndex < 0) { + bindingsDropdown.add(option); + bindingsDropdown.selectedIndex = bindingsDropdown.options.length - 1; + } else { + bindingsDropdown.selectedIndex = foundIndex; + } + }); +PowerPoint.BorderProperties:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies a table's borders. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying border styles. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + borders: { + left: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + right: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + top: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 }, + bottom: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 } + } + } + }); + await context.sync(); + }); +PowerPoint.BorderProperties#color:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies a table's borders. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying border styles. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + borders: { + left: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + right: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + top: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 }, + bottom: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 } + } + } + }); + await context.sync(); + }); +PowerPoint.BorderProperties#dashStyle:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies a table's borders. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying border styles. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + borders: { + left: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + right: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + top: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 }, + bottom: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 } + } + } + }); + await context.sync(); + }); +PowerPoint.BorderProperties#weight:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies a table's borders. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying border styles. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + borders: { + left: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + right: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + top: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 }, + bottom: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 } + } + } + }); + await context.sync(); + }); +PowerPoint.ConnectorType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml + + + // This function gets the collection of shapes on the first slide, + + // and adds a line to the collection, while specifying its + + // start and end points. Then it names the shape. + + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + + // For a line, left and top are the coordinates of the start point, + // while height and width are the coordinates of the end point. + const line: PowerPoint.Shape = shapes.addLine(PowerPoint.ConnectorType.straight, + { + left: 400, + top: 200, + height: 20, + width: 150 + }); + line.name = "StraightLine"; + + await context.sync(); + }); +PowerPoint.FillProperties:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); + }); +PowerPoint.FillProperties#color:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); + }); +PowerPoint.FontProperties:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); + }); +PowerPoint.FontProperties#color:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); + }); +PowerPoint.FontProperties#doubleStrikethrough:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); + }); +PowerPoint.FontProperties#name:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); + }); +PowerPoint.FontProperties#strikethrough:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); + }); +PowerPoint.FontProperties#subscript:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); + }); +PowerPoint.FontProperties#superscript:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); + }); +PowerPoint.GeometricShapeType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml + + + // This function gets the collection of shapes on the first slide, + + // and adds a hexagon shape to the collection, while specifying its + + // location and size. Then it names the shape. + + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + const shapeOptions: PowerPoint.ShapeAddOptions = { + left: 100, + top: 100, + height: 150, + width: 150 + }; + const hexagon: PowerPoint.Shape = shapes.addGeometricShape(PowerPoint.GeometricShapeType.hexagon, shapeOptions); + hexagon.name = "Hexagon"; + + await context.sync(); + }); +PowerPoint.Hyperlink:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/hyperlinks/manage-hyperlinks.yaml + + + // Gets the hyperlinks found in the first selected slide. + + await PowerPoint.run(async (context) => { + const slide: PowerPoint.Slide = context.presentation.getSelectedSlides().getItemAt(0); + const hyperlinks: PowerPoint.HyperlinkCollection = slide.hyperlinks.load("address,screenTip"); + const hyperlinksCount = hyperlinks.getCount(); + await context.sync(); + + console.log(`${hyperlinksCount.value} hyperlinks found in first selected slide:`); + for (let link of hyperlinks.items) { + console.log(`Address: "${link.address}" (Screen tip: "${link.screenTip}")`); + } + }); +PowerPoint.HyperlinkCollection:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/hyperlinks/manage-hyperlinks.yaml + + + // Gets the hyperlinks found in the first selected slide. + + await PowerPoint.run(async (context) => { + const slide: PowerPoint.Slide = context.presentation.getSelectedSlides().getItemAt(0); + const hyperlinks: PowerPoint.HyperlinkCollection = slide.hyperlinks.load("address,screenTip"); + const hyperlinksCount = hyperlinks.getCount(); + await context.sync(); + + console.log(`${hyperlinksCount.value} hyperlinks found in first selected slide:`); + for (let link of hyperlinks.items) { + console.log(`Address: "${link.address}" (Screen tip: "${link.screenTip}")`); + } + }); +PowerPoint.InsertSlideFormatting:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/insert-slides.yaml + + + await PowerPoint.run(async function(context) { + // Get the ID of the first selected slide. + const presentation: PowerPoint.Presentation = context.presentation; + const selected: PowerPoint.Slide = presentation.getSelectedSlides().getItemAt(0); + selected.load("id"); + await context.sync(); + + // Insert the other presentation after the selected slide. + const insertOptions: PowerPoint.InsertSlideOptions = { + formatting: PowerPoint.InsertSlideFormatting.useDestinationTheme, + targetSlideId: selected.id + }; + presentation.insertSlidesFromBase64(chosenFileBase64, insertOptions); + await context.sync(); + }); +PowerPoint.InsertSlideOptions:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/insert-slides.yaml + + + await PowerPoint.run(async function(context) { + // Get the ID of the first selected slide. + const presentation: PowerPoint.Presentation = context.presentation; + const selected: PowerPoint.Slide = presentation.getSelectedSlides().getItemAt(0); + selected.load("id"); + await context.sync(); + + // Insert the other presentation after the selected slide. + const insertOptions: PowerPoint.InsertSlideOptions = { + formatting: PowerPoint.InsertSlideFormatting.useDestinationTheme, + targetSlideId: selected.id + }; + presentation.insertSlidesFromBase64(chosenFileBase64, insertOptions); + await context.sync(); + }); +PowerPoint.ParagraphHorizontalAlignment:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + + + // Specifies the horizontal and vertical alignments of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying horizontal and vertical alignment. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + horizontalAlignment: PowerPoint.ParagraphHorizontalAlignment.justify, + verticalAlignment: PowerPoint.TextVerticalAlignment.middle + } + }); + await context.sync(); + }); +PowerPoint.Presentation:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/insert-slides.yaml + + + await PowerPoint.run(async function(context) { + // Get the ID of the first selected slide. + const presentation: PowerPoint.Presentation = context.presentation; + const selected: PowerPoint.Slide = presentation.getSelectedSlides().getItemAt(0); + selected.load("id"); + await context.sync(); + + // Insert the other presentation after the selected slide. + const insertOptions: PowerPoint.InsertSlideOptions = { + formatting: PowerPoint.InsertSlideFormatting.useDestinationTheme, + targetSlideId: selected.id + }; + presentation.insertSlidesFromBase64(chosenFileBase64, insertOptions); + await context.sync(); + }); +PowerPoint.Presentation#getSelectedShapes:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + + + // Arranges the selected shapes in a line from left to right. + + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); + await context.sync(); + let maxHeight = 0; + shapes.items.map((shape) => { + shape.load("width,height"); + }); + await context.sync(); + shapes.items.map((shape) => { + shape.left = currentLeft; + shape.top = currentTop; + currentLeft += shape.width; + if (shape.height > maxHeight) maxHeight = shape.height; + }); + await context.sync(); + currentLeft = 0; + if (currentTop > slideHeight - 200) currentTop = 0; + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + + + // Gets the shapes you selected on the slide and displays their IDs on the + task pane. + + await PowerPoint.run(async (context) => { + let finalTable = ""; + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + await context.sync(); + finalTable += "
getSelectedShapes.getCount returned:" + shapeCount.value + "
"; + finalTable += + "
"; + shapes.load("items"); + await context.sync(); + shapes.items.map((shape, index) => { + finalTable += ""; + }); + finalTable += "
IndexId
" + index + "" + shape.id + "
"; + const outputSpan = document.getElementById("outputSpan"); + outputSpan.innerHTML = ""; + outputSpan.innerHTML += finalTable; + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + + + // Saves which shapes are selected so that they can be reselected later. + + await PowerPoint.run(async (context) => { + context.presentation.load("slides"); + await context.sync(); + const slides: PowerPoint.SlideScopedCollection = context.presentation.getSelectedSlides(); + const slideCount = slides.getCount(); + slides.load("items"); + await context.sync(); + savedSlideSelection = []; + slides.items.map((slide) => { + savedSlideSelection.push(slide.id); + }); + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); + await context.sync(); + shapes.items.map((shape) => { + savedShapeSelection.push(shape.id); + }); + }); +PowerPoint.Presentation#getSelectedSlides:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml + + + // Gets the selected slides and displays their IDs on the task pane. + + await PowerPoint.run(async (context) => { + let finalTable = ""; + context.presentation.load("slides"); + await context.sync(); + const allSlidesList = {}; + const allSlidesCount = context.presentation.slides.getCount(); + context.presentation.slides.load("items"); + await context.sync(); + let allSlideItems: PowerPoint.Slide[] = context.presentation.slides.items; + allSlideItems.map((slide, index) => { + allSlidesList[slide.id] = `Slide ${index + 1}`; + }); + + const checkbox = document.getElementById("id-check-usenative") as HTMLInputElement; + if (checkbox && checkbox.checked) { + context.presentation.load("tags"); + } + + const slides: PowerPoint.SlideScopedCollection = context.presentation.getSelectedSlides(); + const slideCount = slides.getCount(); + slides.load("items"); + await context.sync(); + finalTable += "
getSelectedSlides.getCount returned:" + slideCount.value + "
"; + finalTable += + "
"; + slides.items.map((slide, index) => { + finalTable += ""; + }); + finalTable += "
IndexId
" + index + " - " + allSlidesList[slide.id] + "" + slide.id + "
"; + const outputSpan = document.getElementById("outputSpan"); + outputSpan.innerHTML = "" + outputSpan.innerHTML += finalTable; + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml + + + // Saves which slides are currently selected so they can be reselected + later. + + await PowerPoint.run(async (context) => { + let finalTable = ""; + context.presentation.load("slides"); + await context.sync(); + const slides: PowerPoint.SlideScopedCollection = context.presentation.getSelectedSlides(); + const slideCount = slides.getCount(); + await context.sync(); + finalTable += "
getSelectedSlides.getCount returned:" + slideCount.value + "
"; + finalTable += + "
"; + savedSlideSelection = []; + slides.load("items"); + await context.sync(); + slides.items.map((slide, index) => { + finalTable += ""; + savedSlideSelection.push(slide.id); + }); + finalTable += "
IndexId
" + index + "" + slide.id + "
"; + const outputSpan = document.getElementById("outputSpan"); + outputSpan.innerHTML = "" + outputSpan.innerHTML += finalTable; + }); +PowerPoint.Presentation#getSelectedTextRange:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml + + + // Gets the selected text range and prints data about the range on the task + pane. + + await PowerPoint.run(async (context) => { + const textRange: PowerPoint.TextRange = context.presentation.getSelectedTextRange(); + try { + await context.sync(); + } catch (error) { + console.warn("You must select only one range of text for this action to work."); + return; + } + textRange.load("text"); + textRange.load("start"); + textRange.load("length"); + await context.sync(); + let txtHtml = textRange.text; + txtHtml = txtHtml.replace(/\n/g, "
"); + txtHtml = txtHtml.replace(/\r/g, "
"); + txtHtml = txtHtml.replace(/\v/g, "
"); + let txtExplained = textRange.text; + txtExplained = txtExplained.replace(/\n/g, "NL"); + txtExplained = txtExplained.replace(/\r/g, "CR"); + txtExplained = txtExplained.replace(/\v/g, "VV"); + let finalTable = ""; + finalTable += + "
"; + finalTable += ""; + finalTable += ""; + finalTable += ""; + finalTable += ""; + finalTable += ""; + finalTable += "
IndexId
Raw" + textRange.text + "
Html" + txtHtml + "
Exp" + txtExplained + "
Start" + textRange.start + "
Length" + textRange.length + "
"; + const outputSpan = document.getElementById("outputSpan"); + outputSpan.innerHTML = "" + outputSpan.innerHTML += finalTable; + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml - await Excel.run(async (context) => { - let style = context.workbook.styles.getItem("Normal"); - style.font.load("bold, color, italic, name, size"); - style.fill.load("color"); - await context.sync(); + // Sets the range selection to the range that was saved previously. - console.log("Bold: " + style.font.bold); - console.log("Font color: " + style.font.color); - console.log("Italic: " + style.font.italic); - console.log("Name: " + style.font.name); - console.log("Size: " + style.font.size); - console.log("Fill color: " + style.fill.color); + await PowerPoint.run(async (context) => { + const slide1: PowerPoint.Slide = context.presentation.slides.getItem(savedTextSlideSelection[0]); + const shape1: PowerPoint.Shape = slide1.shapes.getItem(savedTextShapeSelection[0]); + const textRange: PowerPoint.TextRange = shape1.textFrame.textRange.getSubstring(savedTextTextRangeStart, savedTextTextRangeLength); + textRange.setSelected(); + await context.sync(); }); -'Excel.Style#horizontalAlignment:member': +PowerPoint.Presentation#insertSlidesFromBase64:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/insert-slides.yaml - await Excel.run(async (context) => { - let worksheet = context.workbook.worksheets.getItem("Sample"); - let range = worksheet.getRange("A1:E1"); - // Apply built-in style. - // Styles are in the Home tab ribbon. - range.style = Excel.BuiltInStyle.neutral; - range.format.horizontalAlignment = "Right"; + await PowerPoint.run(async function(context) { + // Get the ID of the first selected slide. + const presentation: PowerPoint.Presentation = context.presentation; + const selected: PowerPoint.Slide = presentation.getSelectedSlides().getItemAt(0); + selected.load("id"); + await context.sync(); + // Insert the other presentation after the selected slide. + const insertOptions: PowerPoint.InsertSlideOptions = { + formatting: PowerPoint.InsertSlideFormatting.useDestinationTheme, + targetSlideId: selected.id + }; + presentation.insertSlidesFromBase64(chosenFileBase64, insertOptions); await context.sync(); }); -'Excel.Style#load:member(1)': +PowerPoint.Presentation#setSelectedSlides:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml - await Excel.run(async (context) => { - let style = context.workbook.styles.getItem("Diagonal Orientation Style"); - style.load("textOrientation, horizontalAlignment, autoIndent, readingOrder, wrapText, includeProtection, shrinkToFit, locked"); - await context.sync(); + // Sets selection to the slides that were saved. - console.log("Orientation: " + style.textOrientation); - console.log("Horizontal alignment: " + style.horizontalAlignment); - console.log("Add indent: " + style.autoIndent); - console.log("Reading order: " + style.readingOrder); - console.log("Wrap text: " + style.wrapText); - console.log("Include protection: " + style.includeProtection); - console.log("Shrink to fit: " + style.shrinkToFit); - console.log("Style locked: " + style.locked); + await PowerPoint.run(async (context) => { + context.presentation.setSelectedSlides(savedSlideSelection); + await context.sync(); }); -'Excel.StyleCollection#add:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml - await Excel.run(async (context) => { - let styles = context.workbook.styles; - // Add a new style to the style collection. - // Styles is in the Home tab ribbon. - styles.add("Diagonal Orientation Style"); - - let newStyle = styles.getItem("Diagonal Orientation Style"); - - // The "Diagonal Orientation Style" properties. - newStyle.textOrientation = 38; - newStyle.autoIndent = true; - newStyle.includeProtection = true; - newStyle.shrinkToFit = true; - newStyle.locked = false; - - await context.sync(); + // Selects slides 2, 4, and 5. - console.log("Successfully added a new style with diagonal orientation to the Home tab ribbon."); + await PowerPoint.run(async (context) => { + context.presentation.load("slides"); + await context.sync(); + const slide2: PowerPoint.Slide = context.presentation.slides.getItemAt(1); + const slide4: PowerPoint.Slide = context.presentation.slides.getItemAt(3); + const slide5: PowerPoint.Slide = context.presentation.slides.getItemAt(4); + slide2.load("id"); + slide4.load("id"); + slide5.load("id"); + try { + await context.sync(); + } catch (error) { + console.warn("This action requires at least 5 slides in the presentation."); + return; + } + await context.sync(); + context.presentation.setSelectedSlides([slide2.id, slide4.id, slide5.id]); + await context.sync(); }); -'Excel.StyleCollection#getItem:member(1)': +PowerPoint.Presentation#bindings:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml - await Excel.run(async (context) => { - let styles = context.workbook.styles; - // Add a new style to the style collection. - // Styles is in the Home tab ribbon. - styles.add("Diagonal Orientation Style"); - - let newStyle = styles.getItem("Diagonal Orientation Style"); - - // The "Diagonal Orientation Style" properties. - newStyle.textOrientation = 38; - newStyle.autoIndent = true; - newStyle.includeProtection = true; - newStyle.shrinkToFit = true; - newStyle.locked = false; - - await context.sync(); + // Loads bindings. - console.log("Successfully added a new style with diagonal orientation to the Home tab ribbon."); - }); -'Excel.Table#onChanged:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-table-changed.yaml + await PowerPoint.run(async (context) => { + const bindings = context.presentation.bindings; + bindings.load("items"); + await context.sync(); - await Excel.run(async (context) => { - let table = context.workbook.tables.getItemAt(0); - table.onChanged.add(onChange); + const bindingCount = bindings.items.length; + if (bindingCount === 0) { + console.log(`There are no bindings.`); + } else if (bindingCount === 1) { + console.log("There's 1 binding."); + } else { + console.log(`There are ${bindingCount} bindings.`); + } - await context.sync(); - console.log("A handler has been registered for the onChanged event"); + bindings.items.forEach((binding) => { + getShapeForBindingId(binding.id).then((shape) => { + if (shape) { + console.log(`Binding ID: ${binding.id} refers to shape ID ${shape.id}`); + } else { + console.log(`Binding ID: ${binding.id} doesn't refers to shape.`); + } + }); + }); + + populateBindingsDropdown(bindings.items); }); -'Excel.Table#onSelectionChanged:member': +PowerPoint.Shape:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-table-changed.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml - await Excel.run(async (context) => { - let table = context.workbook.tables.getItemAt(0); - table.onSelectionChanged.add(onSelectionChange); - await context.sync(); - console.log("A handler has been registered for table onSelectionChanged event"); - }); -'Excel.Table#resize:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/46-table/resize-table.yaml + // Changes the transparency of every geometric shape in the slide. - await Excel.run(async (context) => { - // Retrieve the worksheet and a table on that worksheet. - const sheet = context.workbook.worksheets.getItem("Sample"); - const expensesTable = sheet.tables.getItem("ExpensesTable"); - - // Resize the table. - expensesTable.resize("A1:D20"); - + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); + await context.sync(); + + // Change the shape transparency to be halfway transparent. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.geometricShape) { + shape.fill.transparency = 0.5; + } + }); await context.sync(); }); -'Excel.TableChangedEventArgs#details:member': +PowerPoint.Shape#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/data-change-event-details.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml - async function onTableChanged(eventArgs: Excel.TableChangedEventArgs) { - await Excel.run(async (context) => { - const details = eventArgs.details; - const address = eventArgs.address; - console.log(`Change at ${address}: was ${details.valueBefore}(${details.valueTypeBefore}),` - + ` now is ${details.valueAfter}(${details.valueTypeAfter})`); - }); - } -'Excel.TableChangedEventArgs#tableId:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-tablecollection-changed.yaml + // This function gets the collection of shapes on the first slide, - async function onChange(event) { - await Excel.run(async (context) => { - let table = context.workbook.tables.getItem(event.tableId); - let worksheet = context.workbook.worksheets.getItem(event.worksheetId); - worksheet.load("name"); + // and then iterates through them, deleting each one. - await context.sync(); + await PowerPoint.run(async (context) => { + const slide: PowerPoint.Slide = context.presentation.slides.getItemAt(0); + const shapes: PowerPoint.ShapeCollection = slide.shapes; - console.log("Handler for table collection onChanged event has been triggered. Data changed address: " + event.address); - console.log("Table Id : " + event.tableId); - console.log("Worksheet Id : " + worksheet.name); - }); - } -'Excel.TableChangedEventArgs#worksheetId:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-tablecollection-changed.yaml + // Load all the shapes in the collection without loading their properties. + shapes.load("items/$none"); - async function onChange(event) { - await Excel.run(async (context) => { - let table = context.workbook.tables.getItem(event.tableId); - let worksheet = context.workbook.worksheets.getItem(event.worksheetId); - worksheet.load("name"); + await context.sync(); - await context.sync(); + shapes.items.forEach((shape) => shape.delete()); - console.log("Handler for table collection onChanged event has been triggered. Data changed address: " + event.address); - console.log("Table Id : " + event.tableId); - console.log("Worksheet Id : " + worksheet.name); - }); - } -'Excel.TableCollection#onChanged:member': + await context.sync(); + }); +PowerPoint.Shape#getTable:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-tablecollection-changed.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - await Excel.run(async (context) => { - let tables = context.workbook.tables; - tables.onChanged.add(onChange); + // Gets the table from a shape. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); + await context.sync(); + + if (shapeCount.value > 0) { + const shape = shapes.getItemAt(0); + shape.load("type"); await context.sync(); - console.log("A handler has been registered for the table collection onChanged event"); - }); -'Excel.TableSelectionChangedEventArgs#address:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-table-changed.yaml - async function onSelectionChange(args) { - await Excel.run(async (context) => { - console.log("Handler for table onSelectionChanged event has been triggered. The new selection is: " + args.address); - }); - } -'Excel.TextConditionalFormat#format:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + // The shape type can indicate whether the shape is a table. + const isTable = shape.type === PowerPoint.ShapeType.table; - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const range = sheet.getRange("B16:D18"); - const conditionalFormat = range.conditionalFormats - .add(Excel.ConditionalFormatType.containsText); - conditionalFormat.textComparison.format.font.color = "red"; - conditionalFormat.textComparison.rule = { operator: Excel.ConditionalTextOperator.contains, text: "Delayed" }; + if (isTable) { + // Get the Table object for the Shape which is a table. + const table = shape.getTable(); + table.load(); + await context.sync(); - await context.sync(); + // Get the Table row and column count. + console.log("Table RowCount: " + table.rowCount + " and columnCount: " + table.columnCount); + } else console.log("Selected shape isn't table."); + } else console.log("No shape selected."); }); -'Excel.TextConditionalFormat#rule:member': +PowerPoint.Shape#setZOrder:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const range = sheet.getRange("B16:D18"); - const conditionalFormat = range.conditionalFormats - .add(Excel.ConditionalFormatType.containsText); - conditionalFormat.textComparison.format.font.color = "red"; - conditionalFormat.textComparison.rule = { operator: Excel.ConditionalTextOperator.contains, text: "Delayed" }; + async function changeZOrder(operation: PowerPoint.ShapeZOrder) { + // Changes the z-order position of the selected shapes. + return PowerPoint.run(async (context) => { + const selectedShapes = context.presentation.getSelectedShapes(); + selectedShapes.load(); await context.sync(); - }); -'Excel.TextFrame#deleteText:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-textboxes.yaml - await Excel.run(async (context) => { - const shapes = context.workbook.worksheets.getItem("Shapes").shapes; - const textbox = shapes.getItem("Textbox"); - textbox.textFrame.deleteText(); - await context.sync(); - }); -'Excel.ValueFilterCondition:enum': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-pivotfilters.yaml + if (selectedShapes.items.length === 0) { + console.log("No shapes are selected."); + } else { + let direction = 1; // Start with bottom-most (lowest number). + + // Start with top-most when sending to back or bringing forward. + + switch (operation) { + case PowerPoint.ShapeZOrder.bringForward: + + case PowerPoint.ShapeZOrder.sendToBack: + direction = -1; // Reverse direction. + + break; + } + + // Change the z-order position for each of the selected shapes, - await Excel.run(async (context) => { - // Add a PivotFilter to filter on the values correlated with a row. + // starting with the bottom-most when bringing to front or sending backward, - // Get the PivotTable. - const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); + // or top-most when sending to back or bringing forward, - // Get the "Farm" field. - const field = pivotTable.hierarchies.getItem("Farm").fields.getItem("Farm"); + // so the selected shapes retain their relative z-order positions after they're changed. - // Filter to only include rows with more than 500 wholesale crates sold. - const filter: Excel.PivotValueFilter = { - condition: Excel.ValueFilterCondition.greaterThan, - comparator: 500, - value: "Sum of Crates Sold Wholesale" - }; + selectedShapes.items + .sort((a, b) => (a.zOrderPosition - b.zOrderPosition) * direction) + .forEach((shape) => { + try { + const originalZOrderPosition = shape.zOrderPosition; + shape.setZOrder(operation); - // Apply the value filter to the field. - field.applyFilter({ valueFilter: filter }); + console.log(`Changed z-order of shape ${shape.id}.`); + } catch (err) { + console.log(`Unable to change z-order of shape ${shape.id}. ${err.message}`); + } + }); - await context.sync(); - }); -'Excel.VerticalAlignment:enum': + await context.sync(); + } + }); + } +PowerPoint.Shape#fill:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - await Excel.run(async (context) => { - let worksheet = context.workbook.worksheets.getItem("Sample"); - let range = worksheet.getRange("A1:E1"); - // Apply new style. - range.style = ("Diagonal Orientation Style"); - range.format.verticalAlignment = "Justify"; - await context.sync(); + // Changes the selected shapes fill color to red. + + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); + await context.sync(); + shapes.items.map((shape) => { + shape.fill.setSolidColor("red"); + }); + await context.sync(); }); -'Excel.WebImageCellValue#address:member': +PowerPoint.Shape#group:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-web-image.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/group-ungroup-shapes.yaml - // This function retrieves the image URL from the selected cell and opens - that image in a new browser tab. - await Excel.run(async (context) => { - // Load the active cell information. - const activeCell = context.workbook.getActiveCell(); - activeCell.load("valuesAsJson"); - await context.sync(); + await PowerPoint.run(async (context) => { + // Ungroups the first shape group on the current slide. - // Get image URL from the active cell. - const values = activeCell.valuesAsJson; - const webImageData = values[0][0] as Excel.WebImageCellValue; - const webImageUrl = webImageData.address; + // Get the shapes on the current slide. + context.presentation.load("slides"); + const slide: PowerPoint.Slide = context.presentation.getSelectedSlides().getItemAt(0); + slide.load("shapes/items/type,shapes/items/id"); + await context.sync(); - if (!webImageUrl) { - console.log("The selected cell is missing an image URL. Select a cell that contains an image."); + const shapes: PowerPoint.ShapeCollection = 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; } - // Open the image URL in a new browser tab. - const tab = window.open(webImageData.address, "_blank"); + // 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}`); }); -'Excel.WebImageCellValue#type:member': +PowerPoint.Shape#height:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-web-image.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - // This function inserts a web image into the currently selected cell. - await Excel.run(async (context) => { - // Retrieve image data from the task pane and then clear the input fields. - const imageUrl = $("#url").val() as string; - const imageAltText = $("#alt-text").val() as string; - clearForm(); + // Arranges the selected shapes in a line from left to right. - // Load the active cell. - const activeCell = context.workbook.getActiveCell(); - activeCell.load(); + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); await context.sync(); + let maxHeight = 0; + shapes.items.map((shape) => { + shape.load("width,height"); + }); + await context.sync(); + shapes.items.map((shape) => { + shape.left = currentLeft; + shape.top = currentTop; + currentLeft += shape.width; + if (shape.height > maxHeight) maxHeight = shape.height; + }); + await context.sync(); + currentLeft = 0; + if (currentTop > slideHeight - 200) currentTop = 0; + }); +PowerPoint.Shape#left:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - if (!imageUrl) { - console.log("Please enter an image URL."); - return; - } - - // Create a web image object and assign the image details. - const webImage: Excel.WebImageCellValue = { - type: "WebImage", /* The string equivalent of `Excel.CellValueType.webImage`. */ - address: imageUrl, - altText: imageAltText - }; - // Insert web image into the active cell. - activeCell.valuesAsJson = [[webImage]]; + // Arranges the selected shapes in a line from left to right. + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); + await context.sync(); + let maxHeight = 0; + shapes.items.map((shape) => { + shape.load("width,height"); + }); + await context.sync(); + shapes.items.map((shape) => { + shape.left = currentLeft; + shape.top = currentTop; + currentLeft += shape.width; + if (shape.height > maxHeight) maxHeight = shape.height; + }); await context.sync(); + currentLeft = 0; + if (currentTop > slideHeight - 200) currentTop = 0; }); -'Excel.Workbook#close:member(1)': +PowerPoint.Shape#top:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-save-and-close.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - await Excel.run(async (context) => { - context.workbook.close(Excel.CloseBehavior.save); + + // Arranges the selected shapes in a line from left to right. + + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); + await context.sync(); + let maxHeight = 0; + shapes.items.map((shape) => { + shape.load("width,height"); + }); + await context.sync(); + shapes.items.map((shape) => { + shape.left = currentLeft; + shape.top = currentTop; + currentLeft += shape.width; + if (shape.height > maxHeight) maxHeight = shape.height; + }); + await context.sync(); + currentLeft = 0; + if (currentTop > slideHeight - 200) currentTop = 0; }); -'Excel.Workbook#getActiveCell:member(1)': +PowerPoint.Shape#type:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-get-active-cell.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml - await Excel.run(async (context) => { - let myWorkbook = context.workbook; - let activeCell = myWorkbook.getActiveCell(); - activeCell.load("address"); + // Changes the transparency of every geometric shape in the slide. - await context.sync(); - - console.log("The active cell is " + activeCell.address); + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); + await context.sync(); + + // Change the shape transparency to be halfway transparent. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.geometricShape) { + shape.fill.transparency = 0.5; + } + }); + await context.sync(); }); -'Excel.Workbook#getSelectedRanges:member(1)': +PowerPoint.Shape#width:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-areas.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - await Excel.run(async (context) => { - const selectedRanges = context.workbook.getSelectedRanges(); - selectedRanges.format.fill.color = "lightblue"; + // Arranges the selected shapes in a line from left to right. - await context.sync(); - }) -'Excel.Workbook#insertWorksheetsFromBase64:member(1)': + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); + await context.sync(); + let maxHeight = 0; + shapes.items.map((shape) => { + shape.load("width,height"); + }); + await context.sync(); + shapes.items.map((shape) => { + shape.left = currentLeft; + shape.top = currentTop; + currentLeft += shape.width; + if (shape.height > maxHeight) maxHeight = shape.height; + }); + await context.sync(); + currentLeft = 0; + if (currentTop > slideHeight - 200) currentTop = 0; + }); +PowerPoint.Shape#zOrderPosition:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-insert-external-worksheets.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml - // Retrieve the file and set up an HTML FileReader element. - const myFile = document.getElementById("file"); + async function changeZOrder(operation: PowerPoint.ShapeZOrder) { + // Changes the z-order position of the selected shapes. + return PowerPoint.run(async (context) => { + const selectedShapes = context.presentation.getSelectedShapes(); + selectedShapes.load(); + await context.sync(); - const reader = new FileReader(); + if (selectedShapes.items.length === 0) { + console.log("No shapes are selected."); + } else { + let direction = 1; // Start with bottom-most (lowest number). + // Start with top-most when sending to back or bringing forward. - reader.onload = (event) => { - // Remove the metadata before the Base64-encoded string. - const startIndex = reader.result.toString().indexOf("base64,"); - externalWorkbook = reader.result.toString().substr(startIndex + 7); - }; + switch (operation) { + case PowerPoint.ShapeZOrder.bringForward: + case PowerPoint.ShapeZOrder.sendToBack: + direction = -1; // Reverse direction. - // Read the file as a data URL so that we can parse the Base64-encoded - string. + break; + } - reader.readAsDataURL(myFile.files[0]); + // Change the z-order position for each of the selected shapes, + + // starting with the bottom-most when bringing to front or sending backward, + + // or top-most when sending to back or bringing forward, + + // so the selected shapes retain their relative z-order positions after they're changed. + + selectedShapes.items + .sort((a, b) => (a.zOrderPosition - b.zOrderPosition) * direction) + .forEach((shape) => { + try { + const originalZOrderPosition = shape.zOrderPosition; + shape.setZOrder(operation); + + console.log(`Changed z-order of shape ${shape.id}.`); + } catch (err) { + console.log(`Unable to change z-order of shape ${shape.id}. ${err.message}`); + } + }); + + await context.sync(); + } + }); + } +PowerPoint.ShapeAddOptions:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-insert-external-worksheets.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml - await Excel.run(async (context) => { - // Retrieve the source workbook. - const workbook = context.workbook; - - // Set up the insert options. - const options = { - sheetNamesToInsert: [], // Insert all the worksheets from the source workbook. - positionType: Excel.WorksheetPositionType.after, // Insert after the `relativeTo` sheet. - relativeTo: "Sheet1" // The sheet relative to which the other worksheets will be inserted. Used with `positionType`. - }; - - // Insert the new worksheets. - workbook.insertWorksheetsFromBase64(externalWorkbook, options); - await context.sync(); + + // This function gets the collection of shapes on the first slide, + + // and adds a hexagon shape to the collection, while specifying its + + // location and size. Then it names the shape. + + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + const shapeOptions: PowerPoint.ShapeAddOptions = { + left: 100, + top: 100, + height: 150, + width: 150 + }; + const hexagon: PowerPoint.Shape = shapes.addGeometricShape(PowerPoint.GeometricShapeType.hexagon, shapeOptions); + hexagon.name = "Hexagon"; + + await context.sync(); }); -'Excel.Workbook#onActivated:member': +PowerPoint.ShapeCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-activated.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml - async function workbookActivated(event: Excel.WorkbookActivatedEventArgs) { - await Excel.run(async (context) => { - // Callback function for when the workbook is activated. - console.log("The workbook was activated."); + + // Changes the transparency of every geometric shape in the slide. + + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); + await context.sync(); + + // Change the shape transparency to be halfway transparent. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.geometricShape) { + shape.fill.transparency = 0.5; + } }); - } + await context.sync(); + }); +PowerPoint.ShapeCollection#addGeometricShape:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-activated.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml - await Excel.run(async (context) => { - const workbook = context.workbook; - // Register the workbook activated event handler. - workbook.onActivated.add(workbookActivated); + // This function gets the collection of shapes on the first slide, + + // and adds a hexagon shape to the collection, while specifying its + + // location and size. Then it names the shape. + + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + const shapeOptions: PowerPoint.ShapeAddOptions = { + left: 100, + top: 100, + height: 150, + width: 150 + }; + const hexagon: PowerPoint.Shape = shapes.addGeometricShape(PowerPoint.GeometricShapeType.hexagon, shapeOptions); + hexagon.name = "Hexagon"; await context.sync(); - console.log("Added event handler for workbook activated."); }); -'Excel.Workbook#pivotTables:member': +PowerPoint.ShapeCollection#addGroup:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-get-pivottables.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/group-ungroup-shapes.yaml - await Excel.run(async (context) => { - // Get the names of all the PivotTables in the workbook. - const pivotTables = context.workbook.pivotTables; - pivotTables.load("name"); + + await PowerPoint.run(async (context) => { + // Groups the geometric shapes on the current slide. + + // Get the shapes on the current slide. + context.presentation.load("slides"); + const slide: PowerPoint.Slide = context.presentation.getSelectedSlides().getItemAt(0); + slide.load("shapes/items/type,shapes/items/id"); await context.sync(); - // Display the names in the console. - console.log("PivotTables in the workbook:") - pivotTables.items.forEach((pivotTable) => { - console.log(`\t${pivotTable.name}`); - }); + const shapes: PowerPoint.ShapeCollection = 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}`); }); -'Excel.Workbook#properties:member': +PowerPoint.ShapeCollection#addLine:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/26-document/properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml - await Excel.run(async (context) => { - let titleValue = "Excel document properties API"; - let subjectValue = "Set and get document properties"; - let keywordsValue = "Set and get operations"; - let commentsValue = "This is an Excel document properties API code sample"; - let categoryValue = "Office Add-ins"; - let managerValue = "John"; - let companyValue = "Microsoft"; - let docProperties = context.workbook.properties; + // This function gets the collection of shapes on the first slide, - // Set the writeable document properties. - docProperties.title = titleValue; - docProperties.subject = subjectValue; - docProperties.keywords = keywordsValue; - docProperties.comments = commentsValue; - docProperties.category = categoryValue; - docProperties.manager = managerValue; - docProperties.company = companyValue; + // and adds a line to the collection, while specifying its - await context.sync(); + // start and end points. Then it names the shape. - console.log("Set the following document properties: title, subject, keywords, comments, category, manager, company."); + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + + // For a line, left and top are the coordinates of the start point, + // while height and width are the coordinates of the end point. + const line: PowerPoint.Shape = shapes.addLine(PowerPoint.ConnectorType.straight, + { + left: 400, + top: 200, + height: 20, + width: 150 + }); + line.name = "StraightLine"; + + await context.sync(); }); -'Excel.Workbook#save:member(1)': +PowerPoint.ShapeCollection#addTable:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-save-and-close.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - await Excel.run(async (context) => { - context.workbook.save(Excel.SaveBehavior.save); + + // Adds a basic table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a simple table, specifying the row and column count. + shapes.addTable(3, 4); + await context.sync(); }); -'Excel.Workbook#styles:member': +PowerPoint.ShapeCollection#addTextBox:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/style.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml - await Excel.run(async (context) => { - let styles = context.workbook.styles; - // Add a new style to the style collection. - // Styles is in the Home tab ribbon. - styles.add("Diagonal Orientation Style"); - - let newStyle = styles.getItem("Diagonal Orientation Style"); - - // The "Diagonal Orientation Style" properties. - newStyle.textOrientation = 38; - newStyle.autoIndent = true; - newStyle.includeProtection = true; - newStyle.shrinkToFit = true; - newStyle.locked = false; - - await context.sync(); + // This function gets the collection of shapes on the first slide, - console.log("Successfully added a new style with diagonal orientation to the Home tab ribbon."); + // and adds a text box to the collection, while specifying its text, + + // location, and size. Then it names the text box. + + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + const textbox: PowerPoint.Shape = shapes.addTextBox("Hello!", + { + left: 100, + top: 300, + height: 300, + width: 450 + }); + textbox.name = "Textbox"; + + return context.sync(); }); -'Excel.WorkbookProtection#protect:member(1)': +PowerPoint.ShapeCollection#getCount:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/data-protection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - let password = await passwordHandler(); - passwordHelper(password); + // Gets the table from a shape. - await Excel.run(async (context) => { - let workbook = context.workbook; - workbook.load("protection/protected"); + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); + await context.sync(); + if (shapeCount.value > 0) { + const shape = shapes.getItemAt(0); + shape.load("type"); await context.sync(); - if (!workbook.protection.protected) { - workbook.protection.protect(password); - } + // The shape type can indicate whether the shape is a table. + const isTable = shape.type === PowerPoint.ShapeType.table; + + if (isTable) { + // Get the Table object for the Shape which is a table. + const table = shape.getTable(); + table.load(); + await context.sync(); + + // Get the Table row and column count. + console.log("Table RowCount: " + table.rowCount + " and columnCount: " + table.columnCount); + } else console.log("Selected shape isn't table."); + } else console.log("No shape selected."); }); -'Excel.WorkbookProtection#unprotect:member(1)': +PowerPoint.ShapeCollection#getItemAt:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/data-protection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/tags/tags.yaml - let password = await passwordHandler(); - passwordHelper(password); + await PowerPoint.run(async function(context) { + const slide: PowerPoint.Slide = context.presentation.slides.getItemAt(0); + const shape: PowerPoint.Shape = slide.shapes.getItemAt(0); + shape.tags.add("MOUNTAIN", "Denali"); - await Excel.run(async (context) => { - let workbook = context.workbook; - workbook.protection.unprotect(password); + await context.sync(); + + const myShapeTag: PowerPoint.Tag = shape.tags.getItem("MOUNTAIN"); + myShapeTag.load("key, value"); + + await context.sync(); + + console.log("Added key " + JSON.stringify(myShapeTag.key) + " with value " + JSON.stringify(myShapeTag.value)); }); -'Excel.WorkbookRangeAreas#areas:member': +PowerPoint.ShapeCollection#load:member(2): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/precedents.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml - await Excel.run(async (context) => { - // Precedents are cells referenced by the formula in a cell. - // A "direct precedent" is a cell directly referenced by the selected formula. - let range = context.workbook.getActiveCell(); - let directPrecedents = range.getDirectPrecedents(); - range.load("address"); - directPrecedents.areas.load("address"); + + // Changes the transparency of every geometric shape in the slide. + + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); await context.sync(); - console.log(`Direct precedent cells of ${range.address}:`); + // Change the shape transparency to be halfway transparent. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.geometricShape) { + shape.fill.transparency = 0.5; + } + }); + await context.sync(); + }); +PowerPoint.ShapeFill:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml - // Use the direct precedents API to loop through precedents of the active cell. - for (let i = 0; i < directPrecedents.areas.items.length; i++) { - // Highlight and console the address of each precedent cell. - directPrecedents.areas.items[i].format.fill.color = "Yellow"; - console.log(` ${directPrecedents.areas.items[i].address}`); - } + + // Changes the transparency of every geometric shape in the slide. + + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); + await context.sync(); + + // Change the shape transparency to be halfway transparent. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.geometricShape) { + shape.fill.transparency = 0.5; + } + }); await context.sync(); }); -'Excel.Worksheet#autoFilter:member': +PowerPoint.ShapeFill#setImage:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-auto-filter.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml - // This function adds a percentage AutoFilter to the active worksheet - // and applies the filter to a column of the used range. + // Inserts an image with binding. - await Excel.run(async (context) => { - // Retrieve the active worksheet and the used range on that worksheet. - const sheet = context.workbook.worksheets.getActiveWorksheet(); - const farmData = sheet.getUsedRange(); + await PowerPoint.run(async (context) => { + const bindingId = (document.getElementById("temp-binding-id") as HTMLInputElement).value; + const slide = context.presentation.getSelectedSlides().getItemAt(0); + const myShape = slide.shapes.addGeometricShape(PowerPoint.GeometricShapeType.rectangle, { + top: 100, + left: 30, + width: 200, + height: 200 + }); - // Add a filter that will only show the rows with the top 50% of values in column 3. - sheet.autoFilter.apply(farmData, 3, { - criterion1: "50", - filterOn: Excel.FilterOn.topPercent - }); + myShape.fill.setImage(flowerImage); + context.presentation.bindings.add(myShape, PowerPoint.BindingType.shape, bindingId); + await context.sync(); - await context.sync(); + const bindingsDropdown = document.getElementById("bindings-dropdown") as HTMLSelectElement; + + const option = new Option(`Binding ${bindingId}`, bindingId); + + // When a binding ID already exists, the binding is updated to refer to the new shape + // so select the existing item rather than add a new one. + const foundIndex = findDropdownItem(bindingsDropdown, option.text); + if (foundIndex < 0) { + bindingsDropdown.add(option); + bindingsDropdown.selectedIndex = bindingsDropdown.options.length - 1; + } else { + bindingsDropdown.selectedIndex = foundIndex; + } }); -'Excel.Worksheet#copy:member(1)': +PowerPoint.ShapeFill#setSolidColor:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-copy.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - await Excel.run(async (context) => { - let myWorkbook = context.workbook; - let sampleSheet = myWorkbook.worksheets.getActiveWorksheet(); - let copiedSheet = sampleSheet.copy("End") + // Changes the selected shapes fill color to red. - sampleSheet.load("name"); - copiedSheet.load("name"); + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); + await context.sync(); + shapes.items.map((shape) => { + shape.fill.setSolidColor("red"); + }); + await context.sync(); + }); +PowerPoint.ShapeFill#foregroundColor:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - await context.sync(); - console.log("'" + sampleSheet.name + "' was copied to '" + copiedSheet.name + "'") + // Creates random shapes on the selected slide. + + await PowerPoint.run(async (context) => { + let finalTable = ""; + const currentSlide: PowerPoint.Slide = context.presentation.getSelectedSlides().getItemAt(0); + const maxNewShapeWidth = 200; + const maxNewShapeHeight = 200; + const minNewShapeWidth = 50; + const minNewShapeHeight = 50; + for (let i = 0; i < 20; i++) { + const rectangle: PowerPoint.Shape = currentSlide.shapes.addGeometricShape( + PowerPoint.GeometricShapeType.rectangle + ); + rectangle.height = getRandomBetween(minNewShapeWidth, maxNewShapeWidth); + rectangle.width = getRandomBetween(minNewShapeHeight, maxNewShapeHeight); + rectangle.left = getRandomBetween(0, slideWidth - rectangle.width); + rectangle.top = getRandomBetween(0, slideHeight - rectangle.height); + rectangle.fill.foregroundColor = generateRandomHexColor(); + } + finalTable += "Done
"; + const outputSpan = document.getElementById("outputSpan"); + outputSpan.innerHTML = ""; + outputSpan.innerHTML += finalTable; }); -'Excel.Worksheet#customProperties:member': +PowerPoint.ShapeFill#transparency:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/26-document/custom-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml - await Excel.run(async (context) => { - // Load the keys and values of all custom properties in the current worksheet. - const customWorksheetProperties = context.workbook.worksheets.getActiveWorksheet().customProperties; - customWorksheetProperties.load(["key", "value"]); + + // Changes the transparency of every geometric shape in the slide. + + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); await context.sync(); - // Log each custom property to the console. - // Note that your document may have more properties than those you have set using this snippet. - customWorksheetProperties.items.forEach((property) => { - console.log(`${property.key}:${property.value}`); + // Change the shape transparency to be halfway transparent. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.geometricShape) { + shape.fill.transparency = 0.5; + } }); + await context.sync(); }); -'Excel.Worksheet#findAllOrNullObject:member(1)': +PowerPoint.ShapeFont:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-find-all.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const foundRanges = sheet.findAllOrNullObject("Complete", { - completeMatch: true, - matchCase: false - }); - await context.sync(); + // Sets the color of the selected text range to green. + + await PowerPoint.run(async (context) => { + const textRange: PowerPoint.TextRange = context.presentation.getSelectedTextRange(); + textRange.font.color = "green"; + await context.sync(); + }); +PowerPoint.ShapeFont#color:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml + - if (foundRanges.isNullObject) { - console.log("No complete projects"); - } else { - foundRanges.format.fill.color = "green" - } + // Sets the color of the selected text range to green. + + await PowerPoint.run(async (context) => { + const textRange: PowerPoint.TextRange = context.presentation.getSelectedTextRange(); + textRange.font.color = "green"; + await context.sync(); }); -'Excel.Worksheet#getNext:member(1)': +PowerPoint.ShapeGroup:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/group-ungroup-shapes.yaml - await Excel.run(async (context) => { - const sheets = context.workbook.worksheets; - // We don't want to include the default worksheet that was created - // when the workbook was created, so our "firstSheet" will be the one - // after the literal first. Note chaining of navigation methods. - const firstSheet = sheets.getFirst().getNext(); - const lastSheet = sheets.getLast(); - const firstTaxRateRange = firstSheet.getRange("B2"); - const lastTaxRateRange = lastSheet.getRange("B2"); + await PowerPoint.run(async (context) => { + // Ungroups the first shape group on the current slide. - firstSheet.load("name"); - lastSheet.load("name"); - firstTaxRateRange.load("text"); - lastTaxRateRange.load("text"); + // Get the shapes on the current slide. + context.presentation.load("slides"); + const slide: PowerPoint.Slide = context.presentation.getSelectedSlides().getItemAt(0); + slide.load("shapes/items/type,shapes/items/id"); + await context.sync(); - await context.sync(); + const shapes: PowerPoint.ShapeCollection = 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; + } - let firstYear = firstSheet.name.substr(5, 4); - let lastYear = lastSheet.name.substr(5, 4); - console.log(`Tax Rate change from ${firstYear} to ${lastYear}`, `Tax rate for ${firstYear}: ${firstTaxRateRange.text[0][0]}\nTax rate for ${lastYear}: ${lastTaxRateRange.text[0][0]}`) + // Ungroup the first grouped shapes. + const firstGroupId = shapeGroups[0].id; + const shapeGroupToUngroup = shapes.getItem(firstGroupId); + shapeGroupToUngroup.group.ungroup(); + await context.sync(); - await context.sync(); + console.log(`Ungrouped shapes with group ID: ${firstGroupId}`); }); -'Excel.Worksheet#getPrevious:member(1)': +PowerPoint.ShapeGroup#ungroup:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/group-ungroup-shapes.yaml - await Excel.run(async (context) => { - const sheets = context.workbook.worksheets; - const currentSheet = sheets.getActiveWorksheet(); - const previousYearSheet = currentSheet.getPrevious(); - const currentTaxDueRange = currentSheet.getRange("C2"); - const previousTaxDueRange = previousYearSheet.getRange("C2"); - currentSheet.load("name"); - previousYearSheet.load("name"); - currentTaxDueRange.load("text"); - previousTaxDueRange.load("text"); + await PowerPoint.run(async (context) => { + // Ungroups the first shape group on the current slide. - await context.sync(); + // Get the shapes on the current slide. + context.presentation.load("slides"); + const slide: PowerPoint.Slide = context.presentation.getSelectedSlides().getItemAt(0); + slide.load("shapes/items/type,shapes/items/id"); + await context.sync(); - let currentYear = currentSheet.name.substr(5, 4); - let previousYear = previousYearSheet.name.substr(5, 4); - console.log("Two Year Tax Due Comparison", `Tax due for ${currentYear} was ${currentTaxDueRange.text[0][0]}\nTax due for ${previousYear} was ${previousTaxDueRange.text[0][0]}`) + const shapes: PowerPoint.ShapeCollection = 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; + } - await context.sync(); + // 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}`); }); -'Excel.Worksheet#getRanges:member(1)': +PowerPoint.ShapeLineDashStyle:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-areas.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); - const specifiedRanges = sheet.getRanges("D3:D5, G3:G5"); - specifiedRanges.format.fill.color = "pink"; + // Changes the dash style of every line in the slide. - await context.sync(); - }) -'Excel.Worksheet#onChanged:member': + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); + await context.sync(); + + // Change the dash style for shapes of the type `line`. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.line) { + shape.lineFormat.dashStyle = PowerPoint.ShapeLineDashStyle.dashDot; + } + }); + await context.sync(); + }); +PowerPoint.ShapeLineFormat:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml - await Excel.run(async (context) => { - let sheet = context.workbook.worksheets.getItem("Sample"); - sheet.onChanged.add(onChange); - await context.sync(); - console.log("Added a worksheet-level data-changed event handler."); + // Changes the dash style of every line in the slide. + + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); + await context.sync(); + + // Change the dash style for shapes of the type `line`. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.line) { + shape.lineFormat.dashStyle = PowerPoint.ShapeLineDashStyle.dashDot; + } + }); + await context.sync(); }); -'Excel.Worksheet#onColumnSorted:member': +PowerPoint.ShapeLineFormat#dashStyle:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-column-and-row-sort.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml - await Excel.run(async (context) => { - console.log("Adding column handler"); - const sheet = context.workbook.worksheets.getActiveWorksheet(); - // This will fire whenever a column has been moved as the result of a sort action. - sheet.onColumnSorted.add((event) => { - return Excel.run((context) => { - console.log("Column sorted: " + event.address); - const sheet = context.workbook.worksheets.getActiveWorksheet(); + // Changes the dash style of every line in the slide. - // Clear formatting for section, then highlight the sorted area. - sheet.getRange("A1:E5").format.fill.clear(); - if (event.address !== "") { - sheet.getRanges(event.address).format.fill.color = "yellow"; - } + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); + await context.sync(); - return context.sync(); - }); - }); + // Change the dash style for shapes of the type `line`. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.line) { + shape.lineFormat.dashStyle = PowerPoint.ShapeLineDashStyle.dashDot; + } + }); + await context.sync(); }); -'Excel.Worksheet#onFormulaChanged:member': +PowerPoint.ShapeScopedCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-formula-changed.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - await Excel.run(async (context) => { - // Retrieve the worksheet named "Sample". - let sheet = context.workbook.worksheets.getItem("Sample"); - - // Register the formula changed event handler for this worksheet. - sheet.onFormulaChanged.add(formulaChangeHandler); + + // Changes the selected shapes fill color to red. + + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); + await context.sync(); + shapes.items.map((shape) => { + shape.fill.setSolidColor("red"); + }); await context.sync(); - - console.log("Registered a formula changed event handler for this worksheet."); }); +PowerPoint.ShapeScopedCollection#getCount:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-formula-changed.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - async function formulaChangeHandler(event: - Excel.WorksheetFormulaChangedEventArgs) { - await Excel.run(async (context) => { - // Retrieve details about the formula change event. - const cellAddress = event.formulaDetails[0].cellAddress; - const previousFormula = event.formulaDetails[0].previousFormula; - const source = event.source; - - // Print out the change event details. - console.log( - `The formula in cell ${cellAddress} changed. - The previous formula was: ${previousFormula}. - The source of the change was: ${source}.` - ); + + // Gets the shapes you selected on the slide and displays their IDs on the + task pane. + + await PowerPoint.run(async (context) => { + let finalTable = ""; + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + await context.sync(); + finalTable += "
getSelectedShapes.getCount returned:" + shapeCount.value + "
"; + finalTable += + "
"; + shapes.load("items"); + await context.sync(); + shapes.items.map((shape, index) => { + finalTable += ""; }); - } -'Excel.Worksheet#onProtectionChanged:member': + finalTable += "
IndexId
" + index + "" + shape.id + "
"; + const outputSpan = document.getElementById("outputSpan"); + outputSpan.innerHTML = ""; + outputSpan.innerHTML += finalTable; + }); +PowerPoint.ShapeType:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet-protection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml - // This function registers an event handler for the onProtectionChanged - event of a worksheet. - await Excel.run(async (context) => { - // Set "Sample" as the active worksheet. - context.workbook.worksheets.getItemOrNullObject("Sample").delete(); - const sheet = context.workbook.worksheets.add("Sample"); - sheet.activate(); + // Changes the dash style of every line in the slide. - // Register the onProtectionChanged event handler. - sheet.onProtectionChanged.add(checkProtection); - await context.sync(); - console.log("Added a worksheet protection change event handler."); + await PowerPoint.run(async (context) => { + // Get the type of shape for every shape in the collection. + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + shapes.load("type"); + await context.sync(); + + // Change the dash style for shapes of the type `line`. + shapes.items.forEach((shape) => { + if (shape.type === PowerPoint.ShapeType.line) { + shape.lineFormat.dashStyle = PowerPoint.ShapeLineDashStyle.dashDot; + } + }); + await context.sync(); }); +PowerPoint.ShapeZOrder:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet-protection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml - async function checkProtection(event: - Excel.WorksheetProtectionChangedEventArgs) { - // This function is an event handler that returns the protection status of a worksheet - // and information about the changed worksheet. - await Excel.run(async (context) => { - const protectionStatus = event.isProtected; - const worksheetId = event.worksheetId; - const source = event.source; - console.log("Protection status changed. Protection status is now: " + protectionStatus + "."); - console.log(" ID of changed worksheet: " + worksheetId + "."); - console.log(" Source of change event: " + source + "."); - }); - } -'Excel.Worksheet#onRowSorted:member': + + // Sends the shape to the back. + + changeZOrder(PowerPoint.ShapeZOrder.sendToBack); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-column-and-row-sort.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml - await Excel.run(async (context) => { - console.log("Adding row handler"); - const sheet = context.workbook.worksheets.getActiveWorksheet(); - // This will fire whenever a row has been moved as the result of a sort action. - sheet.onRowSorted.add((event) => { - return Excel.run((context) => { - console.log("Row sorted: " + event.address); - const sheet = context.workbook.worksheets.getActiveWorksheet(); + async function changeZOrder(operation: PowerPoint.ShapeZOrder) { + // Changes the z-order position of the selected shapes. + return PowerPoint.run(async (context) => { + const selectedShapes = context.presentation.getSelectedShapes(); + selectedShapes.load(); + await context.sync(); - // Clear formatting for section, then highlight the sorted area. - sheet.getRange("A1:E5").format.fill.clear(); - if (event.address !== "") { - sheet.getRanges(event.address).format.fill.color = "yellow"; - } + if (selectedShapes.items.length === 0) { + console.log("No shapes are selected."); + } else { + let direction = 1; // Start with bottom-most (lowest number). - return context.sync(); - }); - }); - }); -'Excel.Worksheet#onSingleClicked:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-worksheet-single-click.yaml + // Start with top-most when sending to back or bringing forward. - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); - sheet.onSingleClicked.add((event) => { - return Excel.run((context) => { - console.log(`Click detected at ${event.address} (pixel offset from upper-left cell corner: ${event.offsetX}, ${event.offsetY})`); - return context.sync(); - }); - }); + switch (operation) { + case PowerPoint.ShapeZOrder.bringForward: - console.log("The worksheet click handler is registered."); + case PowerPoint.ShapeZOrder.sendToBack: + direction = -1; // Reverse direction. - await context.sync(); - }); -'Excel.Worksheet#pivotTables:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-get-pivottables.yaml + break; + } - await Excel.run(async (context) => { - // Get the names of all the PivotTables in the current worksheet. - const pivotTables = context.workbook.worksheets.getActiveWorksheet().pivotTables; - pivotTables.load("name"); - await context.sync(); + // Change the z-order position for each of the selected shapes, - // Display the names in the console. - console.log("PivotTables in the current worksheet:") - pivotTables.items.forEach((pivotTable) => { - console.log(`\t${pivotTable.name}`); + // starting with the bottom-most when bringing to front or sending backward, + + // or top-most when sending to back or bringing forward, + + // so the selected shapes retain their relative z-order positions after they're changed. + + selectedShapes.items + .sort((a, b) => (a.zOrderPosition - b.zOrderPosition) * direction) + .forEach((shape) => { + try { + const originalZOrderPosition = shape.zOrderPosition; + shape.setZOrder(operation); + + console.log(`Changed z-order of shape ${shape.id}.`); + } catch (err) { + console.log(`Unable to change z-order of shape ${shape.id}. ${err.message}`); + } + }); + + await context.sync(); + } }); - }); -'Excel.Worksheet#showGridlines:member': + } +PowerPoint.Slide:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/gridlines.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); - sheet.showGridlines = true; - await context.sync(); + // Reselects shapes that were saved previously. + + await PowerPoint.run(async (context) => { + const slide1: PowerPoint.Slide = context.presentation.slides.getItem(savedSlideSelection[0]); + await context.sync(); + slide1.setSelectedShapes(savedShapeSelection); + await context.sync(); }); -'Excel.Worksheet#showOutlineLevels:member(1)': +PowerPoint.Slide#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/outline.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml - Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); - // This shows the top 3 outline levels; collapsing any additional sublevels. - sheet.showOutlineLevels(3, 3); - await context.sync(); - }); -'Excel.Worksheet#slicers:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-slicer.yaml + // Deletes the selected slides. - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Pivot"); - const slicer = sheet.slicers.add( - "Farm Sales", /* The slicer data source. For PivotTables, this can be the PivotTable object reference or name. */ - "Type" /* The field in the data source to filter by. For PivotTables, this can be a PivotField object reference or ID. */ - ); - slicer.name = "Fruit Slicer"; - await context.sync(); + await PowerPoint.run(async (context) => { + context.presentation.load("slides"); + await context.sync(); + const slides: PowerPoint.SlideScopedCollection = context.presentation.getSelectedSlides(); + const slideCount = slides.getCount(); + slides.load("items"); + await context.sync(); + slides.items.map((slide) => { + slide.delete(); + }); }); -'Excel.Worksheet#tabColor:member': +PowerPoint.Slide#exportAsBase64:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/tab-color.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/export-import-slide.yaml - await Excel.run(async (context) => { - const activeSheet = context.workbook.worksheets.getActiveWorksheet(); - activeSheet.tabColor = "#FF0000"; - await context.sync(); + // Exports current slide. + + await PowerPoint.run(async (context) => { + const slide = context.presentation.getSelectedSlides().getItemAt(0); + const slideBase64DataResult = slide.exportAsBase64(); + const imageBase64DataResult = slide.getImageAsBase64({ height: 300 }); + await context.sync(); + + localStorage.setItem("exportedSlide", slideBase64DataResult.value); + localStorage.setItem("exportedSlideImage", imageBase64DataResult.value); + + updateSlideImage(imageBase64DataResult.value); + + console.log("Slide was exported."); }); -'Excel.WorksheetAddedEventArgs#worksheetId:member': +PowerPoint.Slide#getImageAsBase64:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/export-import-slide.yaml - async function onWorksheetAdd(event) { - await Excel.run(async (context) => { - console.log( - "Handler for worksheet onAdded event has been triggered. Newly added worksheet Id : " + - event.worksheetId - ); - }); - } -'Excel.WorksheetChangedEventArgs#changeDirectionState:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet.yaml - async function onChange(event: Excel.WorksheetChangedEventArgs) { - // This function is an event handler that returns the address, trigger source, - // and insert or delete shift directions of the change. - await Excel.run(async (context) => { - // Return the address where change occurred. - console.log(`Handler for worksheet onChanged event has been triggered.`); - console.log(` Data changed address: ` + event.address); + // Exports current slide. - // Return the source of the event that triggered the change. - console.log(` Data change trigger source: ` + event.triggerSource); + await PowerPoint.run(async (context) => { + const slide = context.presentation.getSelectedSlides().getItemAt(0); + const slideBase64DataResult = slide.exportAsBase64(); + const imageBase64DataResult = slide.getImageAsBase64({ height: 300 }); + await context.sync(); - // Note:insertShiftDirection and deleteShiftDirection are exclusive and both enums can't have a value at the same time. - // If one has a value, then the other will return undefined. + localStorage.setItem("exportedSlide", slideBase64DataResult.value); + localStorage.setItem("exportedSlideImage", imageBase64DataResult.value); - // If the insert shift direction is defined, return it. - if (event.changeDirectionState.insertShiftDirection) { - console.log(` Cells inserted shift direction: ` + event.changeDirectionState.insertShiftDirection); - } + updateSlideImage(imageBase64DataResult.value); - // If the delete shift direction is defined, return it. - if (event.changeDirectionState.deleteShiftDirection) { - console.log(` Cells deleted shift direction: ` + event.changeDirectionState.deleteShiftDirection); - } - }); - } + console.log("Slide was exported."); + }); +PowerPoint.Slide#setSelectedShapes:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - // This function deletes data from a range and sets the delete shift - direction to "up". - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const range = sheet.getRange("A5:F5"); - range.delete(Excel.DeleteShiftDirection.up); + // Reselects shapes that were saved previously. + + await PowerPoint.run(async (context) => { + const slide1: PowerPoint.Slide = context.presentation.slides.getItem(savedSlideSelection[0]); + await context.sync(); + slide1.setSelectedShapes(savedShapeSelection); + await context.sync(); }); -'Excel.WorksheetChangedEventArgs#triggerSource:member': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - async function onChange(event: Excel.WorksheetChangedEventArgs) { - // This function is an event handler that returns the address, trigger source, - // and insert or delete shift directions of the change. - await Excel.run(async (context) => { - // Return the address where change occurred. - console.log(`Handler for worksheet onChanged event has been triggered.`); - console.log(` Data changed address: ` + event.address); - // Return the source of the event that triggered the change. - console.log(` Data change trigger source: ` + event.triggerSource); + // Selects the first two shapes on slide 1. - // Note:insertShiftDirection and deleteShiftDirection are exclusive and both enums can't have a value at the same time. - // If one has a value, then the other will return undefined. + await PowerPoint.run(async (context) => { + context.presentation.load("slides"); + await context.sync(); + const slide1 = context.presentation.slides.getItemAt(0); + slide1.load("shapes/items/type"); + await context.sync(); - // If the insert shift direction is defined, return it. - if (event.changeDirectionState.insertShiftDirection) { - console.log(` Cells inserted shift direction: ` + event.changeDirectionState.insertShiftDirection); - } + const shapes = slide1.shapes.items.filter((item) => item.type === PowerPoint.ShapeType.geometricShape); + const shape1: PowerPoint.Shape = shapes[0]; + const shape2: PowerPoint.Shape = shapes[1]; + shape1.load("id"); + shape2.load("id"); + await context.sync(); - // If the delete shift direction is defined, return it. - if (event.changeDirectionState.deleteShiftDirection) { - console.log(` Cells deleted shift direction: ` + event.changeDirectionState.deleteShiftDirection); - } - }); - } -'Excel.WorksheetCollection#getFirst:member(1)': + console.log(`IDs: ${shape1.id}, ${shape2.id}`) + slide1.setSelectedShapes([shape1.id, shape2.id]); + await context.sync(); + }); +PowerPoint.SlideCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml - - await Excel.run(async (context) => { - const sheets = context.workbook.worksheets; + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml - // We don't want to include the default worksheet that was created - // when the workbook was created, so our "firstSheet" will be the one - // after the literal first. Note chaining of navigation methods. - const firstSheet = sheets.getFirst().getNext(); - const lastSheet = sheets.getLast(); - const firstTaxRateRange = firstSheet.getRange("B2"); - const lastTaxRateRange = lastSheet.getRange("B2"); - firstSheet.load("name"); - lastSheet.load("name"); - firstTaxRateRange.load("text"); - lastTaxRateRange.load("text"); + const chosenMaster = (document.getElementById("master-id") as + HTMLInputElement).value; - await context.sync(); + const chosenLayout = (document.getElementById("layout-id") as + HTMLInputElement).value; - let firstYear = firstSheet.name.substr(5, 4); - let lastYear = lastSheet.name.substr(5, 4); - console.log(`Tax Rate change from ${firstYear} to ${lastYear}`, `Tax rate for ${firstYear}: ${firstTaxRateRange.text[0][0]}\nTax rate for ${lastYear}: ${lastTaxRateRange.text[0][0]}`) - await context.sync(); + await PowerPoint.run(async function(context) { + // Create a new slide using an existing master slide and layout. + const newSlideOptions: PowerPoint.AddSlideOptions = { + slideMasterId: chosenMaster, /* An ID from `Presentation.slideMasters`. */ + layoutId: chosenLayout /* An ID from `SlideMaster.layouts`. */ + }; + context.presentation.slides.add(newSlideOptions); + await context.sync(); }); -'Excel.WorksheetCollection#getLast:member(1)': +PowerPoint.SlideCollection#add:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/reference-worksheets-by-relative-position.yaml - - await Excel.run(async (context) => { - const sheets = context.workbook.worksheets; + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml - // We don't want to include the default worksheet that was created - // when the workbook was created, so our "firstSheet" will be the one - // after the literal first. Note chaining of navigation methods. - const firstSheet = sheets.getFirst().getNext(); - const lastSheet = sheets.getLast(); - const firstTaxRateRange = firstSheet.getRange("B2"); - const lastTaxRateRange = lastSheet.getRange("B2"); - firstSheet.load("name"); - lastSheet.load("name"); - firstTaxRateRange.load("text"); - lastTaxRateRange.load("text"); + const chosenMaster = (document.getElementById("master-id") as + HTMLInputElement).value; - await context.sync(); + const chosenLayout = (document.getElementById("layout-id") as + HTMLInputElement).value; - let firstYear = firstSheet.name.substr(5, 4); - let lastYear = lastSheet.name.substr(5, 4); - console.log(`Tax Rate change from ${firstYear} to ${lastYear}`, `Tax rate for ${firstYear}: ${firstTaxRateRange.text[0][0]}\nTax rate for ${lastYear}: ${lastTaxRateRange.text[0][0]}`) - await context.sync(); + await PowerPoint.run(async function(context) { + // Create a new slide using an existing master slide and layout. + const newSlideOptions: PowerPoint.AddSlideOptions = { + slideMasterId: chosenMaster, /* An ID from `Presentation.slideMasters`. */ + layoutId: chosenLayout /* An ID from `SlideMaster.layouts`. */ + }; + context.presentation.slides.add(newSlideOptions); + await context.sync(); }); -'Excel.WorksheetCollection#onActivated:member': +PowerPoint.SlideCollection#getItemAt:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml - await Excel.run(async (context) => { - let sheets = context.workbook.worksheets; - sheets.onActivated.add(onActivate); + // Selects slides 2, 4, and 5. + + await PowerPoint.run(async (context) => { + context.presentation.load("slides"); + await context.sync(); + const slide2: PowerPoint.Slide = context.presentation.slides.getItemAt(1); + const slide4: PowerPoint.Slide = context.presentation.slides.getItemAt(3); + const slide5: PowerPoint.Slide = context.presentation.slides.getItemAt(4); + slide2.load("id"); + slide4.load("id"); + slide5.load("id"); + try { await context.sync(); - console.log("A handler has been registered for the OnActivate event."); + } catch (error) { + console.warn("This action requires at least 5 slides in the presentation."); + return; + } + await context.sync(); + context.presentation.setSelectedSlides([slide2.id, slide4.id, slide5.id]); + await context.sync(); }); -'Excel.WorksheetCollection#onAdded:member': +PowerPoint.SlideGetImageOptions:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/export-import-slide.yaml - await Excel.run(async (context) => { - let sheet = context.workbook.worksheets; - sheet.onAdded.add(onWorksheetAdd); - await context.sync(); - console.log("A handler has been registered for the OnAdded event."); + // Exports current slide. + + await PowerPoint.run(async (context) => { + const slide = context.presentation.getSelectedSlides().getItemAt(0); + const slideBase64DataResult = slide.exportAsBase64(); + const imageBase64DataResult = slide.getImageAsBase64({ height: 300 }); + await context.sync(); + + localStorage.setItem("exportedSlide", slideBase64DataResult.value); + localStorage.setItem("exportedSlideImage", imageBase64DataResult.value); + + updateSlideImage(imageBase64DataResult.value); + + console.log("Slide was exported."); }); -'Excel.WorksheetCollection#onDeactivated:member': +PowerPoint.SlideLayout:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-workbook-and-worksheet-collection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml - await Excel.run(async (context) => { - let sheets = context.workbook.worksheets; - sheets.onDeactivated.add(onDeactivate); - await context.sync(); - console.log("A handler has been registered for the OnDeactivate event."); + await PowerPoint.run(async function(context) { + // Load information about all the slide masters and associated layouts. + const slideMasters: PowerPoint.SlideMasterCollection = context.presentation.slideMasters.load("id, name, layouts/items/name, layouts/items/id"); + await context.sync(); + + // Log the name and ID of each slide master. + for (let i = 0; i < slideMasters.items.length; i++) { + console.log("Master name: " + slideMasters.items[i].name); + console.log("Master ID: " + slideMasters.items[i].id); + + // Log the name and ID of each slide layout in the slide master. + const layoutsInMaster: PowerPoint.SlideLayoutCollection = slideMasters.items[i].layouts; + for (let j = 0; j < layoutsInMaster.items.length; j++) { + console.log(" Layout name: " + layoutsInMaster.items[j].name + " Layout ID: " + layoutsInMaster.items[j].id); + } + } }); -'Excel.WorksheetCustomPropertyCollection#add:member(1)': +PowerPoint.SlideLayout#id:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/26-document/custom-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml - await Excel.run(async (context) => { - // Get the key/value pair from the task pane. - const userKey = $("#key").text(); - const userValue = $("#value").text(); - // Add the custom property. - const customWorksheetProperties = context.workbook.worksheets.getActiveWorksheet().customProperties; - customWorksheetProperties.add(userKey, userValue); + await PowerPoint.run(async function(context) { + // Load information about all the slide masters and associated layouts. + const slideMasters: PowerPoint.SlideMasterCollection = context.presentation.slideMasters.load("id, name, layouts/items/name, layouts/items/id"); + await context.sync(); + + // Log the name and ID of each slide master. + for (let i = 0; i < slideMasters.items.length; i++) { + console.log("Master name: " + slideMasters.items[i].name); + console.log("Master ID: " + slideMasters.items[i].id); + + // Log the name and ID of each slide layout in the slide master. + const layoutsInMaster: PowerPoint.SlideLayoutCollection = slideMasters.items[i].layouts; + for (let j = 0; j < layoutsInMaster.items.length; j++) { + console.log(" Layout name: " + layoutsInMaster.items[j].name + " Layout ID: " + layoutsInMaster.items[j].id); + } + } + }); +PowerPoint.SlideLayoutCollection:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml + + await PowerPoint.run(async function(context) { + // Load information about all the slide masters and associated layouts. + const slideMasters: PowerPoint.SlideMasterCollection = context.presentation.slideMasters.load("id, name, layouts/items/name, layouts/items/id"); await context.sync(); - console.log(`Successfully set custom worksheet property ${userKey}:${userValue}.`); + // Log the name and ID of each slide master. + for (let i = 0; i < slideMasters.items.length; i++) { + console.log("Master name: " + slideMasters.items[i].name); + console.log("Master ID: " + slideMasters.items[i].id); + + // Log the name and ID of each slide layout in the slide master. + const layoutsInMaster: PowerPoint.SlideLayoutCollection = slideMasters.items[i].layouts; + for (let j = 0; j < layoutsInMaster.items.length; j++) { + console.log(" Layout name: " + layoutsInMaster.items[j].name + " Layout ID: " + layoutsInMaster.items[j].id); + } + } }); -'Excel.WorksheetFreezePanes#freezeAt:member(1)': +PowerPoint.SlideLayoutCollection#load:member(2): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-freeze-panes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - // Freeze the specified range in top-and-left-most pane of the worksheet. - sheet.freezePanes.freezeAt(sheet.getRange("H2:K5")); + await PowerPoint.run(async function(context) { + // Load information about all the slide masters and associated layouts. + const slideMasters: PowerPoint.SlideMasterCollection = context.presentation.slideMasters.load("id, name, layouts/items/name, layouts/items/id"); + await context.sync(); - await context.sync(); + // Log the name and ID of each slide master. + for (let i = 0; i < slideMasters.items.length; i++) { + console.log("Master name: " + slideMasters.items[i].name); + console.log("Master ID: " + slideMasters.items[i].id); + + // Log the name and ID of each slide layout in the slide master. + const layoutsInMaster: PowerPoint.SlideLayoutCollection = slideMasters.items[i].layouts; + for (let j = 0; j < layoutsInMaster.items.length; j++) { + console.log(" Layout name: " + layoutsInMaster.items[j].name + " Layout ID: " + layoutsInMaster.items[j].id); + } + } }); -'Excel.WorksheetFreezePanes#freezeColumns:member(1)': +PowerPoint.SlideMaster:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-freeze-panes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - // Freeze the first two columns in the worksheet. - sheet.freezePanes.freezeColumns(2); + await PowerPoint.run(async function(context) { + // Load information about all the slide masters and associated layouts. + const slideMasters: PowerPoint.SlideMasterCollection = context.presentation.slideMasters.load("id, name, layouts/items/name, layouts/items/id"); + await context.sync(); - await context.sync(); + // Log the name and ID of each slide master. + for (let i = 0; i < slideMasters.items.length; i++) { + console.log("Master name: " + slideMasters.items[i].name); + console.log("Master ID: " + slideMasters.items[i].id); + + // Log the name and ID of each slide layout in the slide master. + const layoutsInMaster: PowerPoint.SlideLayoutCollection = slideMasters.items[i].layouts; + for (let j = 0; j < layoutsInMaster.items.length; j++) { + console.log(" Layout name: " + layoutsInMaster.items[j].name + " Layout ID: " + layoutsInMaster.items[j].id); + } + } }); -'Excel.WorksheetFreezePanes#freezeRows:member(1)': +PowerPoint.SlideMaster#id:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-freeze-panes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - // Freeze the top two rows in the worksheet. - sheet.freezePanes.freezeRows(2); + await PowerPoint.run(async function(context) { + // Load information about all the slide masters and associated layouts. + const slideMasters: PowerPoint.SlideMasterCollection = context.presentation.slideMasters.load("id, name, layouts/items/name, layouts/items/id"); + await context.sync(); - await context.sync(); + // Log the name and ID of each slide master. + for (let i = 0; i < slideMasters.items.length; i++) { + console.log("Master name: " + slideMasters.items[i].name); + console.log("Master ID: " + slideMasters.items[i].id); + + // Log the name and ID of each slide layout in the slide master. + const layoutsInMaster: PowerPoint.SlideLayoutCollection = slideMasters.items[i].layouts; + for (let j = 0; j < layoutsInMaster.items.length; j++) { + console.log(" Layout name: " + layoutsInMaster.items[j].name + " Layout ID: " + layoutsInMaster.items[j].id); + } + } }); -'Excel.WorksheetFreezePanes#getLocationOrNullObject:member(1)': +PowerPoint.SlideMasterCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-freeze-panes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const frozenRange = sheet.freezePanes.getLocationOrNullObject(); - frozenRange.load("address"); - await context.sync(); + await PowerPoint.run(async function(context) { + // Load information about all the slide masters and associated layouts. + const slideMasters: PowerPoint.SlideMasterCollection = context.presentation.slideMasters.load("id, name, layouts/items/name, layouts/items/id"); + await context.sync(); - if (frozenRange.isNullObject) { - console.log(`The worksheet does not contain a frozen pane.`); - } else { - console.log(`The address of the frozen range (cells that are frozen in the top-and-left-most pane) is "${frozenRange.address}"`); + // Log the name and ID of each slide master. + for (let i = 0; i < slideMasters.items.length; i++) { + console.log("Master name: " + slideMasters.items[i].name); + console.log("Master ID: " + slideMasters.items[i].id); + + // Log the name and ID of each slide layout in the slide master. + const layoutsInMaster: PowerPoint.SlideLayoutCollection = slideMasters.items[i].layouts; + for (let j = 0; j < layoutsInMaster.items.length; j++) { + console.log(" Layout name: " + layoutsInMaster.items[j].name + " Layout ID: " + layoutsInMaster.items[j].id); } + } }); -'Excel.WorksheetFreezePanes#unfreeze:member(1)': +PowerPoint.SlideMasterCollection#load:member(2): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-freeze-panes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - sheet.freezePanes.unfreeze(); - await context.sync(); + await PowerPoint.run(async function(context) { + // Load information about all the slide masters and associated layouts. + const slideMasters: PowerPoint.SlideMasterCollection = context.presentation.slideMasters.load("id, name, layouts/items/name, layouts/items/id"); + await context.sync(); + + // Log the name and ID of each slide master. + for (let i = 0; i < slideMasters.items.length; i++) { + console.log("Master name: " + slideMasters.items[i].name); + console.log("Master ID: " + slideMasters.items[i].id); + + // Log the name and ID of each slide layout in the slide master. + const layoutsInMaster: PowerPoint.SlideLayoutCollection = slideMasters.items[i].layouts; + for (let j = 0; j < layoutsInMaster.items.length; j++) { + console.log(" Layout name: " + layoutsInMaster.items[j].name + " Layout ID: " + layoutsInMaster.items[j].id); + } + } }); -'Excel.WorksheetPositionType:enum': +PowerPoint.SlideScopedCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-insert-external-worksheets.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml - await Excel.run(async (context) => { - // Retrieve the source workbook. - const workbook = context.workbook; - - // Set up the insert options. - const options = { - sheetNamesToInsert: [], // Insert all the worksheets from the source workbook. - positionType: Excel.WorksheetPositionType.after, // Insert after the `relativeTo` sheet. - relativeTo: "Sheet1" // The sheet relative to which the other worksheets will be inserted. Used with `positionType`. - }; - - // Insert the new worksheets. - workbook.insertWorksheetsFromBase64(externalWorkbook, options); - await context.sync(); + + // Saves which shapes are selected so that they can be reselected later. + + await PowerPoint.run(async (context) => { + context.presentation.load("slides"); + await context.sync(); + const slides: PowerPoint.SlideScopedCollection = context.presentation.getSelectedSlides(); + const slideCount = slides.getCount(); + slides.load("items"); + await context.sync(); + savedSlideSelection = []; + slides.items.map((slide) => { + savedSlideSelection.push(slide.id); + }); + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + shapes.load("items"); + await context.sync(); + shapes.items.map((shape) => { + savedShapeSelection.push(shape.id); + }); }); -'Excel.WorksheetProtection#protect:member(1)': +PowerPoint.Table:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/data-protection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - let password = await passwordHandler(); - passwordHelper(password); + // Updates a table's values. - await Excel.run(async (context) => { - let activeSheet = context.workbook.worksheets.getActiveWorksheet(); - activeSheet.load("protection/protected"); + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; - await context.sync(); + // Add a table (which is a type of Shape). + const shape = shapes.addTable(4, 3); + let table = shape.getTable(); + table.load(); + await context.sync(); - if (!activeSheet.protection.protected) { - activeSheet.protection.protect(null, password); + // Update values in the table. + for (let rowIndex = 0; rowIndex < table.rowCount; rowIndex++) { + for (let columnIndex = 0; columnIndex < table.columnCount; columnIndex++) { + const cell = table.getCellOrNullObject(rowIndex, columnIndex); + cell.text = generateRandomString(); } + } + + await context.sync(); }); -'Excel.WorksheetProtection#unprotect:member(1)': +PowerPoint.Table#getCellOrNullObject:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/data-protection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - let password = await passwordHandler(); - passwordHelper(password); + // Updates a table's values. - await Excel.run(async (context) => { - let activeSheet = context.workbook.worksheets.getActiveWorksheet(); - activeSheet.protection.unprotect(password); + 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(4, 3); + let table = shape.getTable(); + table.load(); + await context.sync(); + + // Update values in the table. + for (let rowIndex = 0; rowIndex < table.rowCount; rowIndex++) { + for (let columnIndex = 0; columnIndex < table.columnCount; columnIndex++) { + const cell = table.getCellOrNullObject(rowIndex, columnIndex); + cell.text = generateRandomString(); + } + } + + await context.sync(); }); -'Excel.WorksheetProtectionChangedEventArgs#isProtected:member': +PowerPoint.TableAddOptions:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet-protection.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - async function checkProtection(event: - Excel.WorksheetProtectionChangedEventArgs) { - // This function is an event handler that returns the protection status of a worksheet - // and information about the changed worksheet. - await Excel.run(async (context) => { - const protectionStatus = event.isProtected; - const worksheetId = event.worksheetId; - const source = event.source; - console.log("Protection status changed. Protection status is now: " + protectionStatus + "."); - console.log(" ID of changed worksheet: " + worksheetId + "."); - console.log(" Source of change event: " + source + "."); - }); - } -'Excel.WorksheetProtectionChangedEventArgs#source:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet-protection.yaml - async function checkProtection(event: - Excel.WorksheetProtectionChangedEventArgs) { - // This function is an event handler that returns the protection status of a worksheet - // and information about the changed worksheet. - await Excel.run(async (context) => { - const protectionStatus = event.isProtected; - const worksheetId = event.worksheetId; - const source = event.source; - console.log("Protection status changed. Protection status is now: " + protectionStatus + "."); - console.log(" ID of changed worksheet: " + worksheetId + "."); - console.log(" Source of change event: " + source + "."); - }); - } -'Excel.WorksheetProtectionChangedEventArgs#worksheetId:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet-protection.yaml + // Specifies the width and height of a table. - async function checkProtection(event: - Excel.WorksheetProtectionChangedEventArgs) { - // This function is an event handler that returns the protection status of a worksheet - // and information about the changed worksheet. - await Excel.run(async (context) => { - const protectionStatus = event.isProtected; - const worksheetId = event.worksheetId; - const source = event.source; - console.log("Protection status changed. Protection status is now: " + protectionStatus + "."); - console.log(" ID of changed worksheet: " + worksheetId + "."); - console.log(" Source of change event: " + source + "."); - }); - } -'Excel.WorksheetSingleClickedEventArgs#address:member': + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying the width and height. + shapes.addTable(3, 4, { + width: 600, + height: 400 + }); + await context.sync(); + }); +PowerPoint.TableAddOptions#columns:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/event-worksheet-single-click.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); - sheet.onSingleClicked.add((event) => { - return Excel.run((context) => { - console.log(`Click detected at ${event.address} (pixel offset from upper-left cell corner: ${event.offsetX}, ${event.offsetY})`); - return context.sync(); - }); - }); - console.log("The worksheet click handler is registered."); + // Specifies the column widths and row heights of a table. - await context.sync(); + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying column widths and row heights. + shapes.addTable(3, 4, { + columns: [{ columnWidth: 100 }, { columnWidth: 200 }, { columnWidth: 100 }, { columnWidth: 200 }], + rows: [{ rowHeight: 60 }, { rowHeight: 120 }, { rowHeight: 180 }] + }); + await context.sync(); }); -'Office.AppointmentCompose#addFileAttachmentAsync:member(1)': +PowerPoint.TableAddOptions#height:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - const attachmentUrl = $("#attachmentUrl").val(); - Office.context.mailbox.item.addFileAttachmentAsync( - attachmentUrl, - getFileName(attachmentUrl), - { "asyncContext" : { var1: 1, var2: true } }, - function(result) { console.log(result); }); -'Office.AppointmentCompose#addFileAttachmentFromBase64Async:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + // Specifies the width and height of a table. - base64String = - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAACRUlEQVRYw82XzXHbMBCFP2F8tzsQc8Ixyh0zoiuIXIGdCsxUYKqC0B04FdiuwMoM7mGOOIXqQGoAymXhgSX+itJM9kIRFLAP+3YXD5Pdbscx5oxaAIW8Ztr6l2PWmQwF4IyaieP53qdfAqQ8CwBn1JU4vpWhrbxXQA5MZfynANmcDIAzKgcy4FKGXsVJFf3nLgKyBQptfT4KQMRz2N0fcbxqmRMDWXflx0VPnrdArq0vekQ1Dv0UeHZGNebHhwjU8AzwKM43RyZnbAf58Q6ghudeWd0Aus0+5EcMIIRi3beua0D3Nm39BEAx3i7HTK4DEBJn5YxKOnaRA5+ErpMBWMpzDvx1RuXCcxOISlufAjfC7zgAsqsvUvMAD0ApPaEtGi9AIlUzKgJo60tt/SyKRkzLrAXERluf7W1gOICWaMyB386oooOWsIHvXbSoHuUSFovtHqicUVnH3EJoeT0aQEf5/XBGlc6otIOWBXAtPeZkAIJ9Bt6cUU9tZautX2nrk3MACHYr1ZKProKRtDw4o8pzAPjWo+NtpXTTvoteDDg8noDAcwbcRedAkGdFXyk2GEDcegVAFp2gyVDHjRQ4o6q2smoqtR5Hd+qMqtoALCWUUymr1m43QMZfOaMK4C0SrMsDANJ2E5FNcbdbjHC+ENl+H0myJFbLtaq4Rt8dyPBYRQV1E40nMv9rl7xrOw3DGb+Whcqu3i/OM6CUOWvgRlufNmnLYy4m77uJI7AXtdNcTDrU71LEyv7v01/N/ovL6bmu5/8A1tNWZldH0W4AAAAASUVORK5CYII="; + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; - Office.context.mailbox.item.addFileAttachmentFromBase64Async( - base64String, - "logo.png", - { isInline: false }, - function(result) { console.log(result); }); + // Add a table, specifying the width and height. + shapes.addTable(3, 4, { + width: 600, + height: 400 + }); + await context.sync(); + }); +PowerPoint.TableAddOptions#mergedAreas:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - // Set the signature for the current item with inline image. - const modIcon1Base64 = - "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpDRDMxMDg1MjBCNDZFMTExODE2MkM1RUI2M0M4MDYxRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFMTUxQjgyRjQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFMTUxQjgyRTQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkQxMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkNEMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+uC/WfAAAAehJREFUeNpilCzfwEAEkAbiECA2A2J1IOaHin8E4ptAfBaIVwLxU0IGMRKw0B6IW4DYhoE4cASIK6E0VsCEQ1wUiNcB8QESLGOAqj0MxBuhZhBloS4QnwHiQAbygR/UDF1CFupCXSjHQDmQg5qli8tCUBBsQUoQ1AD8UDNFsVk4n0o+w+bT+egWglKjNymmeGhLkqLcG2oHAwtUoIuQDj5OVgZPLUmwRe5aEmAxqYqNpFgKssOcCeplM0KqdST5GfpDDRm0JfkYrj3/SE7QguyQY4ImYYLgCtAS10kHGMw6dzNsv/qC7OwCClJXYlR++v6b4er3j5QmIFcmaNlIL6AOslCIjhYKMTHQGTBBqxh6gXcgC6/R0cKbIAv30dHCfaAKGJTxHxJSqS3Fz9DkowNmywpyMcgA8fF7b8D8VWcfM6w8+4gYC+VB+RCk8hSh0gaUD4/dewvlvUWRe/z+GzGWgex4BGtiOAHxXhoHpzMoSGHZAhSPW2lo2VZYWkHOh4nEtLrIAE+hZmNUwK+B2BOIv1PRsu9QM1/jatNcBtVZ0IREKXgENesyoVYbzNIdFFi2A5tl+NqlL6BB4QBNzsSCU1A9nlAzMAALAQMOQl0qB23qWwKxIlIrDBQ394H4OBCvISYqAAIMACVibHDqsO7zAAAAAElFTkSuQmCC"; + // Specifies the merge areas of a table. - Office.context.mailbox.item.addFileAttachmentFromBase64Async( - modIcon1Base64, - "myImage.png", - { isInline: true }, - function(result) { - if (result.status == Office.AsyncResultStatus.Succeeded) { - const signature = $("#signature").val() + ""; - console.log(`Setting signature to "${signature}".`); - Office.context.mailbox.item.body.setSignatureAsync( - signature, - { coercionType: "html" }, - function(asyncResult) { - console.log(`setSignatureAsync: ${asyncResult.status}`); - } - ); - } else { - console.error(`addFileAttachmentFromBase64Async: ${result.error}`); - } - } - ); -'Office.AppointmentCompose#addItemAttachmentAsync:member(1)': + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying one 2x2 merged area. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "", "HHHH"], + ["1", "", "", "1234"] + ], + mergedAreas: [{ rowIndex: 1, columnIndex: 1, rowCount: 2, columnCount: 2 }] + }); + await context.sync(); + }); +PowerPoint.TableAddOptions#rows:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml + - const attachmentItemId = $("#attachmentItemId").val(); + // Specifies the column widths and row heights of a table. - Office.context.mailbox.item.addItemAttachmentAsync( - attachmentItemId, - "My attachment", - { "asyncContext" : { var3: 3, var4: false } }, - function(result) { console.log(result); }); -'Office.AppointmentCompose#categories:member': + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying column widths and row heights. + shapes.addTable(3, 4, { + columns: [{ columnWidth: 100 }, { columnWidth: 200 }, { columnWidth: 100 }, { columnWidth: 200 }], + rows: [{ rowHeight: 60 }, { rowHeight: 120 }, { rowHeight: 180 }] + }); + await context.sync(); + }); +PowerPoint.TableAddOptions#specificCellProperties:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.categories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - console.log("Categories assigned to this item:"); - console.log(JSON.stringify(categories)); - } else { - console.log("There are no categories assigned to this item."); - } - } else { - console.error(asyncResult.error); - } + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); }); +PowerPoint.TableAddOptions#uniformCellProperties:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml - - // Note: In order for you to successfully add a category, + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - // it must be in the mailbox categories master list. + // Specifies a table's borders. - Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const masterCategories = asyncResult.value; - if (masterCategories && masterCategories.length > 0) { - // Grab the first category from the master list. - const categoryToAdd = [masterCategories[0].displayName]; - Office.context.mailbox.item.categories.addAsync(categoryToAdd, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully assigned category '${categoryToAdd}' to item.`); - } else { - console.log("categories.addAsync call failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("There are no categories in the master list on this mailbox. You can add categories using Office.context.mailbox.masterCategories.addAsync."); + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying border styles. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + borders: { + left: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + right: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + top: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 }, + bottom: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 } + } } - } else { - console.error(asyncResult.error); - } + }); + await context.sync(); }); +PowerPoint.TableAddOptions#values:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.categories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - // Grab the first category assigned to this item. - const categoryToRemove = [categories[0].displayName]; - Office.context.mailbox.item.categories.removeAsync(categoryToRemove, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully unassigned category '${categoryToRemove}' from this item.`); - } else { - console.log("categories.removeAsync call failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("There are no categories assigned to this item."); - } - } else { - console.error(asyncResult.error); - } + + // Specifies a table's values. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying cell values. + const shape = shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ] + }); + await context.sync(); }); -'Office.AppointmentCompose#close:member(1)': +PowerPoint.TableAddOptions#width:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/25-item-save-and-close/close.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.close(); -'Office.AppointmentCompose#disableClientSignatureAsync:member(1)': + + // Specifies the width and height of a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying the width and height. + shapes.addTable(3, 4, { + width: 600, + height: 400 + }); + await context.sync(); + }); +PowerPoint.TableCell:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - // Disable the client signature. - Office.context.mailbox.item.disableClientSignatureAsync(function(asyncResult) - { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("disableClientSignatureAsync succeeded"); - } else { - console.error(asyncResult.error); + // Updates a table's values. + + 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(4, 3); + let table = shape.getTable(); + table.load(); + await context.sync(); + + // Update values in the table. + for (let rowIndex = 0; rowIndex < table.rowCount; rowIndex++) { + for (let columnIndex = 0; columnIndex < table.columnCount; columnIndex++) { + const cell = table.getCellOrNullObject(rowIndex, columnIndex); + cell.text = generateRandomString(); + } } + + await context.sync(); }); -'Office.AppointmentCompose#end:member': +PowerPoint.TableCell#text:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-end-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.end.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; + + // Updates a table's values. + + 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(4, 3); + let table = shape.getTable(); + table.load(); + await context.sync(); + + // Update values in the table. + for (let rowIndex = 0; rowIndex < table.rowCount; rowIndex++) { + for (let columnIndex = 0; columnIndex < table.columnCount; columnIndex++) { + const cell = table.getCellOrNullObject(rowIndex, columnIndex); + cell.text = generateRandomString(); + } } - console.log(`Appointment ends: ${result.value}`); + + await context.sync(); }); +PowerPoint.TableCellBorders:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-end-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.start.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Get start date failed with message ${result.error.message}`); - return; - } - const end = result.value; // Set end to current start date and time. - end.setDate(end.getDate() + 1); // Set end as 1 day later than start date. - Office.context.mailbox.item.end.setAsync(end, (result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Set end date failed with message ${result.error.message}`); - return; + // Specifies a table's borders. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying border styles. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + borders: { + left: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + right: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + top: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 }, + bottom: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 } + } } - console.log(`Successfully set end date and time to ${end}`); }); + await context.sync(); }); -'Office.AppointmentCompose#enhancedLocation:member': +PowerPoint.TableCellBorders#bottom:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.enhancedLocation.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Failed to get locations. Error message: ${result.error.message}`); - return; - } - const places = result.value; - if (places && places.length > 0) { - result.value.forEach(function(place) { - console.log(`Location: ${place.displayName} (type: ${place.locationIdentifier.type})`); - if (place.locationIdentifier.type === Office.MailboxEnums.LocationType.Room) { - console.log("Email address: " + place.emailAddress); + + // Specifies a table's borders. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying border styles. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + borders: { + left: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + right: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + top: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 }, + bottom: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 } } - }); - } else { - console.log("There are no locations."); - } + } + }); + await context.sync(); }); +PowerPoint.TableCellBorders#left:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - const locations = [ - { - id: "Contoso", - type: Office.MailboxEnums.LocationType.Custom - }, - { - id: "room500@test.com", - type: Office.MailboxEnums.LocationType.Room - } - ]; - Office.context.mailbox.item.enhancedLocation.addAsync(locations, (result) => - { - if (result.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully added locations ${JSON.stringify(locations)}`); - } else { - console.error(`Failed to add locations. Error message: ${result.error.message}`); - } + // Specifies a table's borders. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying border styles. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + borders: { + left: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + right: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + top: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 }, + bottom: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 } + } + } + }); + await context.sync(); }); +PowerPoint.TableCellBorders#right:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - const locations = [ - { - id: "Contoso", - type: Office.MailboxEnums.LocationType.Custom - }, - { - id: "room500@test.com", - type: Office.MailboxEnums.LocationType.Room - } - ]; - Office.context.mailbox.item.enhancedLocation.removeAsync(locations, (result) - => { - if (result.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully removed locations ${JSON.stringify(locations)}`); - } else { - console.error(`Failed to remove locations. Error message: ${result.error.message}`); - } + // Specifies a table's borders. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying border styles. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + borders: { + left: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + right: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + top: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 }, + bottom: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 } + } + } + }); + await context.sync(); }); -'Office.AppointmentCompose#getAttachmentContentAsync:member(1)': +PowerPoint.TableCellBorders#top:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachment-content.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - // Gets the attachments of the current message or appointment in compose - mode. - const options = { asyncContext: { currentItem: item } }; + // Specifies a table's borders. - // The getAttachmentsAsync call can only be used in compose mode. + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying border styles. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + borders: { + left: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + right: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + top: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 }, + bottom: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 } + } + } + }); + await context.sync(); + }); +PowerPoint.TableCellProperties:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - item.getAttachmentsAsync(options, callback); + // Specifies the font formatting and fill colors of the cells in a table. - function callback(result) { - if (result.status === Office.AsyncResultStatus.Failed) { - console.log(result.error.message); - return; - } + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); + }); +PowerPoint.TableCellProperties#borders:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - if (result.value.length <= 0) { - console.log("Mail item has no attachments."); - return; - } - for (let i = 0; i < result.value.length; i++) { - // Log the attachment type and its contents to the console. - result.asyncContext.currentItem.getAttachmentContentAsync(result.value[i].id, handleAttachmentsCallback); - } - } -'Office.AppointmentCompose#getAttachmentsAsync:member(1)': + // Specifies a table's borders. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying border styles. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + borders: { + left: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + right: { color: "blue", dashStyle: PowerPoint.ShapeLineDashStyle.solid, weight: 4 }, + top: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 }, + bottom: { color: "red", dashStyle: PowerPoint.ShapeLineDashStyle.longDashDotDot, weight: 2 } + } + } + }); + await context.sync(); + }); +PowerPoint.TableCellProperties#fill:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.getAttachmentsAsync(function (result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(result.error.message); - } else { - if (result.value.length > 0) { - for (let i = 0; i < result.value.length; i++) { - const attachment = result.value[i]; - console.log("ID: " + attachment.id + "\n" + - "Name: " + attachment.name + "\n" + - "Size: " + attachment.size + "\n" + - "isInline: " + attachment.isInline); - switch (attachment.attachmentType) { - case Office.MailboxEnums.AttachmentType.Cloud: - console.log("Attachment type: Attachment is stored in a cloud location."); - break; - case Office.MailboxEnums.AttachmentType.File: - console.log("Attachment type: Attachment is a file."); - break; - case Office.MailboxEnums.AttachmentType.Item: - console.log("Attachment type: Attachment is an Exchange item."); - break; - } - } - } - else { - console.log("No attachments on this message."); - } - } + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); }); -'Office.AppointmentCompose#getItemIdAsync:member(2)': +PowerPoint.TableCellProperties#font:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/item-id-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.getItemIdAsync(function (result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`getItemIdAsync failed with message: ${result.error.message}`); - } else { - console.log(result.value); - } + + // Specifies the font formatting and fill colors of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying font formatting and fill colors. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [ + { fill: { color: "red" }, font: { color: "yellow", name: "Calibri" } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", name: "Coolvetica" } }, + { fill: { color: "red" }, font: { color: "yellow", italic: true } }, + { fill: { color: "red" }, font: { color: "#9966cc", strikethrough: true } } + ], + [ + { fill: { color: "#fbceb1" }, font: { color: "yellow", doubleStrikethrough: true } }, + { fill: { color: "red" }, font: { color: "yellow", subscript: true } }, + { fill: { color: "#0048ba" }, font: { color: "yellow", superscript: true } }, + { fill: { color: "red" }, font: { color: "yellow" } } + ], + [ + { fill: { color: "red" }, font: { color: "#b0bf1a" } }, + { fill: { color: "#9966cc" }, font: { color: "yellow" } }, + { fill: { color: "#b0bf1a" }, font: { color: "yellow" } }, + { fill: { color: "red" }, font: { color: "#fbceb1" } } + ] + ] + }); + await context.sync(); }); -'Office.AppointmentCompose#getSelectedDataAsync:member(2)': +PowerPoint.TableCellProperties#horizontalAlignment:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/get-selected-data.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.getSelectedDataAsync(Office.CoercionType.Text, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const text = asyncResult.value.data; - const prop = asyncResult.value.sourceProperty; - console.log("Selected text in " + prop + ": " + text); - } else { - console.error(asyncResult.error); - } + + // Specifies the horizontal and vertical alignments of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying horizontal and vertical alignment. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + horizontalAlignment: PowerPoint.ParagraphHorizontalAlignment.justify, + verticalAlignment: PowerPoint.TextVerticalAlignment.middle + } + }); + await context.sync(); }); -'Office.AppointmentCompose#getSharedPropertiesAsync:member(2)': +PowerPoint.TableCellProperties#indentLevel:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - if (!Office.context.mailbox.item.getSharedPropertiesAsync) { - console.error("Try this sample on an item from a shared folder."); - return; - } + // Specifying the indents for a table. - Office.context.mailbox.item.getSharedPropertiesAsync(function(result) { - console.log(result.value); + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying the indent level for cells. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + specificCellProperties: [ + [{ indentLevel: 0 }, { indentLevel: 1 }, { indentLevel: 2 }, { indentLevel: 3 }], + [{ indentLevel: 0 }, { indentLevel: 1 }, { indentLevel: 2 }, { indentLevel: 3 }], + [{ indentLevel: 0 }, { indentLevel: 1 }, { indentLevel: 2 }, { indentLevel: 3 }] + ] + }); + await context.sync(); }); -'Office.AppointmentCompose#getSharedPropertiesAsync:member(1)': +PowerPoint.TableCellProperties#textRuns:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - if (!Office.context.mailbox.item.getSharedPropertiesAsync) { - console.error("Try this sample on an appointment from a shared folder."); - return; - } + // Specifies the text runs of the cells in a table. - Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, - function(result) { - if (result.status === Office.AsyncResultStatus.Succeeded && result.value !== "") { - Office.context.mailbox.item.getSharedPropertiesAsync( - { - // Pass auth token along. - asyncContext: result.value - }, - function(result2) { - let sharedProperties = result2.value; - let delegatePermissions = sharedProperties.delegatePermissions; - - // Determine if user has the appropriate permission to do the operation. - if ((delegatePermissions & Office.MailboxEnums.DelegatePermissions.Read) != 0) { - const ewsId = Office.context.mailbox.item.itemId; - const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); - let rest_url = - sharedProperties.targetRestUrl + "/v2.0/users/" + sharedProperties.targetMailbox + "/events/" + restId; - - $.ajax({ - url: rest_url, - dataType: "json", - headers: { Authorization: "Bearer " + result2.asyncContext } - }) - .done(function(response) { - console.log(response); - }) - .fail(function(error) { - console.error(error); - }); - } - } - ); - } + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying text runs. + shapes.addTable(3, 4, { + specificCellProperties: [ + [ + { text: "Title text", font: { bold: true } }, + { text: "Title text", font: { bold: true } }, + { text: "Title text", font: { bold: true } }, + { text: "Title text", font: { bold: true } } + ], + [ + { text: "Bold text", font: { bold: true } }, + { + textRuns: [ + { text: "Text runs with " }, + { text: "Underlined text", font: { underline: PowerPoint.ShapeFontUnderlineStyle.double } }, + { text: " and plain text" } + ] + }, + { text: "Italicized text", font: { italic: true } }, + { text: "Plain text" } + ], + [ + { text: "Bold text", font: { bold: true } }, + { text: "Underlined text", font: { underline: PowerPoint.ShapeFontUnderlineStyle.dotted } }, + { + font: { bold: true }, + textRuns: [ + { text: "Text runs with " }, + { text: "italicized text", font: { italic: true } }, + { text: " and (inherited) bold text" } + ] + }, + { text: "Italicized text", font: { italic: true } } + ] + ] + }); + await context.sync(); }); -'Office.AppointmentCompose#isAllDayEvent:member': +PowerPoint.TableCellProperties#verticalAlignment:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/calendar-properties-apis.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.isAllDayEvent.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Is this an all-day event? " + asyncResult.value); - } else { - console.log("Failed to get if this is an all-day event. Error: " + JSON.stringify(asyncResult.error)); - } - }); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/calendar-properties-apis.yaml - Office.context.mailbox.item.isAllDayEvent.setAsync(true, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Failed to set all-day event: " + JSON.stringify(asyncResult.error)); - } else { - console.log("Appointment set to all-day event."); - } + // Specifies the horizontal and vertical alignments of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying horizontal and vertical alignment. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "GGG", "HHHH"], + ["1", "12", "123", "1234"] + ], + uniformCellProperties: { + horizontalAlignment: PowerPoint.ParagraphHorizontalAlignment.justify, + verticalAlignment: PowerPoint.TextVerticalAlignment.middle + } + }); + await context.sync(); }); -'Office.AppointmentCompose#isClientSignatureEnabledAsync:member(1)': +PowerPoint.TableColumnProperties:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - // Check if the client signature is currently enabled. - Office.context.mailbox.item.isClientSignatureEnabledAsync(function(asyncResult) - { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("isClientSignatureEnabledAsync succeeded with result: " + asyncResult.value); - } else { - console.error(asyncResult.error); - } + // Specifies the column widths and row heights of a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying column widths and row heights. + shapes.addTable(3, 4, { + columns: [{ columnWidth: 100 }, { columnWidth: 200 }, { columnWidth: 100 }, { columnWidth: 200 }], + rows: [{ rowHeight: 60 }, { rowHeight: 120 }, { rowHeight: 180 }] + }); + await context.sync(); }); -'Office.AppointmentCompose#itemType:member': +PowerPoint.TableColumnProperties#columnWidth:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-type.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - const itemType = Office.context.mailbox.item.itemType; - switch (itemType) { - case Office.MailboxEnums.ItemType.Appointment: - console.log(`Current item is an ${itemType}.`); - break; - case Office.MailboxEnums.ItemType.Message: - console.log(`Current item is a ${itemType}. A message could be an email, meeting request, meeting response, or meeting cancellation.`); - break; - } -'Office.AppointmentCompose#loadCustomPropertiesAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + // Specifies the column widths and row heights of a table. - Office.context.mailbox.item.loadCustomPropertiesAsync(function (result) { - if (result.status === Office.AsyncResultStatus.Succeeded) { - console.log("Loaded following custom properties:"); - customProps = result.value; - const dataKey = Object.keys(customProps)[0]; - const data = customProps[dataKey]; - for (let propertyName in data) - { - let propertyValue = data[propertyName]; - console.log(`${propertyName}: ${propertyValue}`); - } - } - else { - console.error(`loadCustomPropertiesAsync failed with message ${result.error.message}`); - } + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying column widths and row heights. + shapes.addTable(3, 4, { + columns: [{ columnWidth: 100 }, { columnWidth: 200 }, { columnWidth: 100 }, { columnWidth: 200 }], + rows: [{ rowHeight: 60 }, { rowHeight: 120 }, { rowHeight: 180 }] + }); + await context.sync(); }); -'Office.AppointmentCompose#location:member': +PowerPoint.TableMergedAreaProperties:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-location-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.location.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; - } - console.log(`Appointment location: ${result.value}`); + + // Specifies the merge areas of a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying one 2x2 merged area. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "", "HHHH"], + ["1", "", "", "1234"] + ], + mergedAreas: [{ rowIndex: 1, columnIndex: 1, rowCount: 2, columnCount: 2 }] + }); + await context.sync(); }); +PowerPoint.TableMergedAreaProperties#columnCount:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-location-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - const location = "my office"; - Office.context.mailbox.item.location.setAsync(location, (result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; - } - console.log(`Successfully set location to ${location}`); + // Specifies the merge areas of a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying one 2x2 merged area. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "", "HHHH"], + ["1", "", "", "1234"] + ], + mergedAreas: [{ rowIndex: 1, columnIndex: 1, rowCount: 2, columnCount: 2 }] + }); + await context.sync(); }); -'Office.AppointmentCompose#notificationMessages:member': +PowerPoint.TableMergedAreaProperties#columnIndex:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - const id = $("#notificationId").val(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.ProgressIndicator, - message: "Progress indicator with id = " + id - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); + // Specifies the merge areas of a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying one 2x2 merged area. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "", "HHHH"], + ["1", "", "", "1234"] + ], + mergedAreas: [{ rowIndex: 1, columnIndex: 1, rowCount: 2, columnCount: 2 }] + }); + await context.sync(); + }); +PowerPoint.TableMergedAreaProperties#rowCount:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - const id = $("#notificationId").val(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Non-persistent informational notification message with id = " + id, - icon: "icon1", - persistent: false - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); + // Specifies the merge areas of a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying one 2x2 merged area. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "", "HHHH"], + ["1", "", "", "1234"] + ], + mergedAreas: [{ rowIndex: 1, columnIndex: 1, rowCount: 2, columnCount: 2 }] + }); + await context.sync(); + }); +PowerPoint.TableMergedAreaProperties#rowIndex:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - const id = $("#notificationId").val(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Persistent informational notification message with id = " + id, - icon: "icon1", - persistent: true - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Specifies the merge areas of a table. - Office.context.mailbox.item.notificationMessages.getAllAsync(handleResult); + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying one 2x2 merged area. + shapes.addTable(3, 4, { + values: [ + ["A", "BB", "CCC", "DDDD"], + ["E", "FF", "", "HHHH"], + ["1", "", "", "1234"] + ], + mergedAreas: [{ rowIndex: 1, columnIndex: 1, rowCount: 2, columnCount: 2 }] + }); + await context.sync(); + }); +PowerPoint.TableRowProperties:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - const id = $("#notificationId").val(); - Office.context.mailbox.item.notificationMessages.replaceAsync( - id, - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Notification message with id = " + id + " has been replaced with an informational message.", - icon: "icon2", - persistent: false - }, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Specifies the column widths and row heights of a table. - const id = $("#notificationId").val(); + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; - Office.context.mailbox.item.notificationMessages.removeAsync(id, - handleResult); -'Office.AppointmentCompose#optionalAttendees:member': + // Add a table, specifying column widths and row heights. + shapes.addTable(3, 4, { + columns: [{ columnWidth: 100 }, { columnWidth: 200 }, { columnWidth: 100 }, { columnWidth: 200 }], + rows: [{ rowHeight: 60 }, { rowHeight: 120 }, { rowHeight: 180 }] + }); + await context.sync(); + }); +PowerPoint.TableRowProperties#rowHeight:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-optional-attendees-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.optionalAttendees.getAsync(function(asyncResult) - { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const apptOptionalAttendees = asyncResult.value; - for (let i = 0; i < apptOptionalAttendees.length; i++) { - console.log( - "Optional attendees: " + - apptOptionalAttendees[i].displayName + - " (" + - apptOptionalAttendees[i].emailAddress + - ") - response: " + - apptOptionalAttendees[i].appointmentResponse - ); - } - } else { - console.error(asyncResult.error); - } + + // Specifies the column widths and row heights of a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying column widths and row heights. + shapes.addTable(3, 4, { + columns: [{ columnWidth: 100 }, { columnWidth: 200 }, { columnWidth: 100 }, { columnWidth: 200 }], + rows: [{ rowHeight: 60 }, { rowHeight: 120 }, { rowHeight: 180 }] + }); + await context.sync(); }); +PowerPoint.Tag:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-optional-attendees-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/tags/tags.yaml - const email = $("#emailOptional") - .val() - .toString(); - const emailArray = [email]; - Office.context.mailbox.item.optionalAttendees.setAsync(emailArray, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Succeeded in setting optional attendees field."); - } else { - console.error(asyncResult.error); - } + await PowerPoint.run(async function (context) { + let presentationTags: PowerPoint.TagCollection = context.presentation.tags; + presentationTags.add("COLOR", "blue"); + + await context.sync(); + + const tag: PowerPoint.Tag = presentationTags.getItem("COLOR"); + tag.load("key, value"); + + await context.sync(); + + console.log("Added key " + JSON.stringify(tag.key) + " with value " + JSON.stringify(tag.value)); }); -'Office.AppointmentCompose#organizer:member': +PowerPoint.TagCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-organizer-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/tags/tags.yaml - Office.context.mailbox.item.organizer.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const apptOrganizer = asyncResult.value; - console.log("Organizer: " + apptOrganizer.displayName + " (" + apptOrganizer.emailAddress + ")"); - } else { - console.error(asyncResult.error); - } + + await PowerPoint.run(async function(context) { + let selectedSlideIndex = await getSelectedSlideIndex(); + + // Decrement because the getSelectedSlideByIndex method is 1-based, + // but the getItemAt method is 0-based. + selectedSlideIndex = selectedSlideIndex - 1; + const slide: PowerPoint.Slide = context.presentation.slides.getItemAt(selectedSlideIndex); + slide.tags.add("CUSTOMER_TYPE", "Premium"); + + await context.sync(); + + const audienceTag: PowerPoint.Tag = slide.tags.getItem("CUSTOMER_TYPE"); + audienceTag.load("key, value"); + + await context.sync(); + + console.log("Added key " + JSON.stringify(audienceTag.key) + " with value " + JSON.stringify(audienceTag.value)); }); -'Office.AppointmentCompose#recurrence:member': +PowerPoint.TagCollection#add:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/tags/tags.yaml - Office.context.mailbox.item.recurrence.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const recurrence = asyncResult.value; - if (recurrence === null) { - console.log("This is a single appointment."); - } else { - console.log(`Recurrence pattern: ${JSON.stringify(recurrence)}`); - } - } else { - console.error(asyncResult.error); + + await PowerPoint.run(async function(context) { + const slide: PowerPoint.Slide = context.presentation.slides.getItemAt(0); + slide.tags.add("OCEAN", "Indian"); + slide.tags.add("PLANET", "Jupiter"); + slide.tags.add("CONTINENT", "Antarctica"); + + await context.sync(); + + slide.tags.load("key, value"); + + await context.sync(); + + for (let i = 0; i < slide.tags.items.length; i++) { + console.log("Added key " + JSON.stringify(slide.tags.items[i].key) + " with value " + JSON.stringify(slide.tags.items[i].value)); } }); +PowerPoint.TagCollection#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml - - // Important: Can only set the recurrence pattern of an appointment series. + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/tags/tags.yaml - const currentDate = new Date(); + await PowerPoint.run(async function (context) { + let presentationTags: PowerPoint.TagCollection = context.presentation.tags; - let seriesTimeObject: Office.SeriesTime; + presentationTags.delete("COLOR"); - // Set series start date to tomorrow. + await context.sync(); - seriesTimeObject.setStartDate(currentDate.getFullYear(), - currentDate.getMonth(), currentDate.getDay() + 1); + console.log(JSON.stringify(presentationTags)); + }); +PowerPoint.TagCollection#getItem:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/tags/tags.yaml - // Set series end date to one year from now. - seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, - currentDate.getMonth() + 1, currentDate.getDay()); + await PowerPoint.run(async function(context) { + let selectedSlideIndex = await getSelectedSlideIndex(); - // Set start time to 1:30 PM. + // Decrement because the getSelectedSlideByIndex method is 1-based, + // but the getItemAt method is 0-based. + selectedSlideIndex = selectedSlideIndex - 1; + const slide: PowerPoint.Slide = context.presentation.slides.getItemAt(selectedSlideIndex); + slide.tags.add("CUSTOMER_TYPE", "Premium"); - seriesTimeObject.setStartTime(13, 30); + await context.sync(); - // Set duration to 30 minutes. + const audienceTag: PowerPoint.Tag = slide.tags.getItem("CUSTOMER_TYPE"); + audienceTag.load("key, value"); - seriesTimeObject.setDuration(30); + await context.sync(); + console.log("Added key " + JSON.stringify(audienceTag.key) + " with value " + JSON.stringify(audienceTag.value)); + }); +PowerPoint.TextFrame:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml - const pattern: Office.Recurrence = { - seriesTime: seriesTimeObject, - recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, - recurrenceProperties: { - interval: 1, - dayOfWeek: Office.MailboxEnums.Days.Tue, - weekNumber: Office.MailboxEnums.WeekNumber.Second, - month: Office.MailboxEnums.Month.Sep - }, - recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } - }; + // Selects the first 10 characters of the selected shape. - Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { - if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + await context.sync(); + if (shapeCount.value !== 1) { + console.warn("You must select only one shape with text in it."); return; } - console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); + const shape: PowerPoint.Shape = shapes.getItemAt(0); + const textFrame: PowerPoint.TextFrame = shape.textFrame.load("textRange,hasText"); + await context.sync(); + if (textFrame.hasText != true) { + console.warn("You must select only one shape with text in it."); + return; + } + const textRange: PowerPoint.TextRange = textFrame.textRange; + textRange.load("text"); + await context.sync(); + if (textRange.text.length < 10) { + console.warn("You must select only one shape with at least 10 characters in it."); + return; + } + const textRange10 = textRange.getSubstring(0, 10); + textRange10.setSelected(); + await context.sync(); }); -'Office.AppointmentCompose#removeAttachmentAsync:member(1)': +PowerPoint.TextRange:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml - Office.context.mailbox.item.removeAttachmentAsync( - $("#attachmentId").val(), - { asyncContext : null }, - function(result) - { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`${result.error.message}`); - } else { - console.log(`Attachment removed successfully.`); - } - } - ); -'Office.AppointmentCompose#requiredAttendees:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-required-attendees-appointment-organizer.yaml - Office.context.mailbox.item.requiredAttendees.getAsync(function(asyncResult) - { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const apptRequiredAttendees = asyncResult.value; - for (let i = 0; i < apptRequiredAttendees.length; i++) { - console.log( - "Required attendees: " + - apptRequiredAttendees[i].displayName + - " (" + - apptRequiredAttendees[i].emailAddress + - ") - response: " + - apptRequiredAttendees[i].appointmentResponse - ); - } - } else { - console.error(asyncResult.error); - } + // Sets the color of the selected text range to green. + + await PowerPoint.run(async (context) => { + const textRange: PowerPoint.TextRange = context.presentation.getSelectedTextRange(); + textRange.font.color = "green"; + await context.sync(); }); +PowerPoint.TextRange#font:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-required-attendees-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml - const email = $("#emailRequired") - .val() - .toString(); - const emailArray = [email]; - Office.context.mailbox.item.requiredAttendees.setAsync(emailArray, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Succeeded in setting required attendees field."); - } else { - console.error(asyncResult.error); - } + // Sets the color of the selected text range to green. + + await PowerPoint.run(async (context) => { + const textRange: PowerPoint.TextRange = context.presentation.getSelectedTextRange(); + textRange.font.color = "green"; + await context.sync(); }); -'Office.AppointmentCompose#saveAsync:member(1)': +PowerPoint.TextRange#setSelected:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/25-item-save-and-close/save.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml - Office.context.mailbox.item.saveAsync(function (result) { - if (result.status === Office.AsyncResultStatus.Succeeded) { - console.log(`saveAsync succeeded, itemId is ${result.value}`); + + // Selects the first 10 characters of the selected shape. + + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeScopedCollection = context.presentation.getSelectedShapes(); + const shapeCount = shapes.getCount(); + await context.sync(); + if (shapeCount.value !== 1) { + console.warn("You must select only one shape with text in it."); + return; } - else { - console.error(`saveAsync failed with message ${result.error.message}`); + const shape: PowerPoint.Shape = shapes.getItemAt(0); + const textFrame: PowerPoint.TextFrame = shape.textFrame.load("textRange,hasText"); + await context.sync(); + if (textFrame.hasText != true) { + console.warn("You must select only one shape with text in it."); + return; } - }); -'Office.AppointmentCompose#sensitivity:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/calendar-properties-apis.yaml - - Office.context.mailbox.item.sensitivity.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Sensitivity: " + asyncResult.value); - } else { - console.log("Failed to get sensitivity: " + JSON.stringify(asyncResult.error)); + const textRange: PowerPoint.TextRange = textFrame.textRange; + textRange.load("text"); + await context.sync(); + if (textRange.text.length < 10) { + console.warn("You must select only one shape with at least 10 characters in it."); + return; } + const textRange10 = textRange.getSubstring(0, 10); + textRange10.setSelected(); + await context.sync(); }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/calendar-properties-apis.yaml - - Office.context.mailbox.item.sensitivity.setAsync( - Office.MailboxEnums.AppointmentSensitivityType.Confidential, - function callback(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Failed to set appointment sensitivity: " + JSON.stringify(asyncResult.error)); - } else { - console.log("Successfully set appointment sensitivity."); - } - } - ); -'Office.AppointmentCompose#seriesId:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-series-id.yaml - - const seriesId = Office.context.mailbox.item.seriesId; + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml - if (seriesId === undefined) { - console.log("This is a message that's not a meeting request."); - } else if (seriesId === null) { - console.log("This is a single appointment, a parent series, or a meeting request for a series or single meeting."); - } else { - console.log("This is an instance belonging to series with ID " + seriesId); - } -'Office.AppointmentCompose#sessionData:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + // Sets the range selection to the range that was saved previously. - Office.context.mailbox.item.sessionData.getAllAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("The sessionData is " + JSON.stringify(asyncResult.value)); - } else { - console.log("Failed to get all sessionData. Error: " + JSON.stringify(asyncResult.error)); - } + await PowerPoint.run(async (context) => { + const slide1: PowerPoint.Slide = context.presentation.slides.getItem(savedTextSlideSelection[0]); + const shape1: PowerPoint.Shape = slide1.shapes.getItem(savedTextShapeSelection[0]); + const textRange: PowerPoint.TextRange = shape1.textFrame.textRange.getSubstring(savedTextTextRangeStart, savedTextTextRangeLength); + textRange.setSelected(); + await context.sync(); }); -'Office.AppointmentCompose#setSelectedDataAsync:member(1)': +PowerPoint.TextRun:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/set-selected-data.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml - Office.context.mailbox.item.setSelectedDataAsync("Replaced", - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Selected text has been updated successfully."); - } else { - console.error(asyncResult.error); - } - }); -'Office.AppointmentCompose#start:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml - Office.context.mailbox.item.start.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; - } - console.log(`Appointment starts: ${result.value}`); + // Specifies the text runs of the cells in a table. + + await PowerPoint.run(async (context) => { + const shapes = context.presentation.getSelectedSlides().getItemAt(0).shapes; + + // Add a table, specifying text runs. + shapes.addTable(3, 4, { + specificCellProperties: [ + [ + { text: "Title text", font: { bold: true } }, + { text: "Title text", font: { bold: true } }, + { text: "Title text", font: { bold: true } }, + { text: "Title text", font: { bold: true } } + ], + [ + { text: "Bold text", font: { bold: true } }, + { + textRuns: [ + { text: "Text runs with " }, + { text: "Underlined text", font: { underline: PowerPoint.ShapeFontUnderlineStyle.double } }, + { text: " and plain text" } + ] + }, + { text: "Italicized text", font: { italic: true } }, + { text: "Plain text" } + ], + [ + { text: "Bold text", font: { bold: true } }, + { text: "Underlined text", font: { underline: PowerPoint.ShapeFontUnderlineStyle.dotted } }, + { + font: { bold: true }, + textRuns: [ + { text: "Text runs with " }, + { text: "italicized text", font: { italic: true } }, + { text: " and (inherited) bold text" } + ] + }, + { text: "Italicized text", font: { italic: true } } + ] + ] + }); + await context.sync(); }); +PowerPoint.TextVerticalAlignment:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml - const start = new Date(); // Represents current date and time. - start.setDate(start.getDate() + 2); // Add 2 days to current date. + // This function gets the collection of shapes on the first slide, - Office.context.mailbox.item.start.setAsync(start, (result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; - } - console.log(`Successfully set start date and time to ${start}`); + // and adds a brace pair, {}, to the collection, while specifying its + + // location and size. Then it names the shape, sets its text and font + + // color, and centers it inside the braces. + + await PowerPoint.run(async (context) => { + const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes; + const braces: PowerPoint.Shape = shapes.addGeometricShape(PowerPoint.GeometricShapeType.bracePair, { + left: 100, + top: 400, + height: 50, + width: 150 + }); + braces.name = "Braces"; + braces.textFrame.textRange.text = "Shape text"; + braces.textFrame.textRange.font.color = "purple"; + braces.textFrame.verticalAlignment = PowerPoint.TextVerticalAlignment.middleCentered; + + return context.sync(); }); -'Office.AppointmentCompose#subject:member': +Word.Alignment:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-subject-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml - Office.context.mailbox.item.subject.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; - } - console.log(`Subject: ${result.value}`); + + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph( + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", + "Start" + ); + body.paragraphs + .getLast() + .insertText( + "Use add-in commands to extend the Word UI and launch task panes that run JavaScript that interacts with the content in a Word document. Any code that you can run in a browser can run in a Word add-in. Add-ins that interact with content in a Word document create requests to act on Word objects and synchronize object state.", + "Replace" + ); + body.paragraphs.getFirst().alignment = "Left"; + body.paragraphs.getLast().alignment = Word.Alignment.left; }); +Word.Annotation:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-subject-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - let subject = "Hello World!"; - Office.context.mailbox.item.subject.setAsync(subject, (result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; + // Accepts the first annotation found in the selected paragraph. + + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id,state,critiqueAnnotation"); + + await context.sync(); + + for (let i = 0; i < annotations.items.length; i++) { + const annotation: Word.Annotation = annotations.items[i]; + + if (annotation.state === Word.AnnotationState.created) { + console.log(`Accepting ID ${annotation.id}...`); + annotation.critiqueAnnotation.accept(); + + await context.sync(); + break; + } } - console.log(`Successfully set subject to ${subject}`); }); -'Office.AppointmentRead#attachments:member': +Word.Annotation#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachments-read.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - const attachments = Office.context.mailbox.item.attachments; - console.log(attachments); -'Office.AppointmentRead#categories:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + // Deletes all annotations found in the selected paragraph. - Office.context.mailbox.item.categories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - console.log("Categories assigned to this item:"); - console.log(JSON.stringify(categories)); - } else { - console.log("There are no categories assigned to this item."); - } - } else { - console.error(asyncResult.error); + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id"); + + await context.sync(); + + const ids = []; + for (let i = 0; i < annotations.items.length; i++) { + const annotation: Word.Annotation = annotations.items[i]; + + ids.push(annotation.id); + annotation.delete(); } + + await context.sync(); + + console.log("Annotations deleted:", ids); }); +Word.Annotation#critiqueAnnotation:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // Note: In order for you to successfully add a category, - // it must be in the mailbox categories master list. + // Gets annotations found in the selected paragraph. + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id,state,critiqueAnnotation"); - Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const masterCategories = asyncResult.value; - if (masterCategories && masterCategories.length > 0) { - // Grab the first category from the master list. - const categoryToAdd = [masterCategories[0].displayName]; - Office.context.mailbox.item.categories.addAsync(categoryToAdd, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully assigned category '${categoryToAdd}' to item.`); - } else { - console.log("categories.addAsync call failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("There are no categories in the master list on this mailbox. You can add categories using Office.context.mailbox.masterCategories.addAsync."); - } - } else { - console.error(asyncResult.error); + await context.sync(); + + console.log("Annotations found:"); + + for (let i = 0; i < annotations.items.length; i++) { + const annotation: Word.Annotation = annotations.items[i]; + + console.log(`ID ${annotation.id} - state '${annotation.state}':`, annotation.critiqueAnnotation.critique); } }); +Word.Annotation#id:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - Office.context.mailbox.item.categories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - // Grab the first category assigned to this item. - const categoryToRemove = [categories[0].displayName]; - Office.context.mailbox.item.categories.removeAsync(categoryToRemove, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully unassigned category '${categoryToRemove}' from this item.`); - } else { - console.log("categories.removeAsync call failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("There are no categories assigned to this item."); + + // Accepts the first annotation found in the selected paragraph. + + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id,state,critiqueAnnotation"); + + await context.sync(); + + for (let i = 0; i < annotations.items.length; i++) { + const annotation: Word.Annotation = annotations.items[i]; + + if (annotation.state === Word.AnnotationState.created) { + console.log(`Accepting ID ${annotation.id}...`); + annotation.critiqueAnnotation.accept(); + + await context.sync(); + break; } - } else { - console.error(asyncResult.error); } }); -'Office.AppointmentRead#dateTimeCreated:member': +Word.Annotation#state:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-date-time-created-read.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - console.log(`Creation date and time: - ${Office.context.mailbox.item.dateTimeCreated}`); -'Office.AppointmentRead#dateTimeModified:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-date-time-modified-read.yaml - console.log(`Date and time item last modified: - ${Office.context.mailbox.item.dateTimeModified}`); -'Office.AppointmentRead#displayReplyAllForm:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + // Rejects the last annotation found in the selected paragraph. - Office.context.mailbox.item.displayReplyAllForm("This is a reply ALL with - some bold text."); -'Office.AppointmentRead#displayReplyAllFormAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id,state,critiqueAnnotation"); - Office.context.mailbox.item.displayReplyAllFormAsync("This is a reply ALL - with some bold text.", function( - asyncResult - ) { - console.log(JSON.stringify(asyncResult)); - }); -'Office.AppointmentRead#displayReplyForm:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + await context.sync(); - Office.context.mailbox.item.displayReplyForm("This is a reply with some - text in italics."); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + for (let i = annotations.items.length - 1; i >= 0; i--) { + const annotation: Word.Annotation = annotations.items[i]; - Office.context.mailbox.item.displayReplyForm({ - htmlBody: "This is a reply with a couple of attachments - an inline image and an item
", - attachments: [ - { type: "file", url: "http://i.imgur.com/9S36xvA.jpg", name: "dog.jpg", isInline: true }, - { type: "item", itemId: Office.context.mailbox.item.itemId, name: "test_email.msg" } - ], - options: { asyncContext: null }, - callback: function(result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); + if (annotation.state === Word.AnnotationState.created) { + console.log(`Rejecting ID ${annotation.id}...`); + annotation.critiqueAnnotation.reject(); + + await context.sync(); + break; } } }); -'Office.AppointmentRead#displayReplyFormAsync:member(1)': +Word.AnnotationClickedEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - Office.context.mailbox.item.displayReplyFormAsync("This is a reply with - some text in italics.", function( - asyncResult - ) { - console.log(JSON.stringify(asyncResult)); + + // Registers event handlers. + + await Word.run(async (context) => { + eventContexts[0] = context.document.onParagraphAdded.add(paragraphChanged); + eventContexts[1] = context.document.onParagraphChanged.add(paragraphChanged); + + eventContexts[2] = context.document.onAnnotationClicked.add(onClickedHandler); + eventContexts[3] = context.document.onAnnotationHovered.add(onHoveredHandler); + eventContexts[4] = context.document.onAnnotationInserted.add(onInsertedHandler); + eventContexts[5] = context.document.onAnnotationRemoved.add(onRemovedHandler); + eventContexts[6] = context.document.onAnnotationPopupAction.add(onPopupActionHandler); + + await context.sync(); + + console.log("Event handlers registered."); }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // The async version is only available starting with requirement set 1.9, - // and provides a callback when the new appointment form has been created. + async function onClickedHandler(args: Word.AnnotationClickedEventArgs) { + await Word.run(async (context) => { + const annotation: Word.Annotation = context.document.getAnnotationById(args.id); + annotation.load("critiqueAnnotation"); - Office.context.mailbox.item.displayReplyFormAsync( - { - htmlBody: "This is a reply with a couple of attachments - an inline image and an item
", - attachments: [ - { type: "file", url: "http://i.imgur.com/9S36xvA.jpg", name: "dog.jpg", isInline: true }, - { type: "item", itemId: Office.context.mailbox.item.itemId, name: "test_email.msg" } - ] - }, - function(asyncResult) { - console.log(JSON.stringify(asyncResult)); - } - ); -'Office.AppointmentRead#end:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-end-read.yaml + await context.sync(); - console.log(`Appointment ends: ${Office.context.mailbox.item.end}`); -'Office.AppointmentRead#enhancedLocation:member': + console.log(`AnnotationClicked: ID ${args.id}:`, annotation.critiqueAnnotation.critique); + }); + } +Word.AnnotationCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - Office.context.mailbox.item.enhancedLocation.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Failed to get locations. Error message: ${result.error.message}`); - return; - } - const places = result.value; - if (places && places.length > 0) { - result.value.forEach(function(place) { - console.log(`Location: ${place.displayName} (type: ${place.locationIdentifier.type})`); - if (place.locationIdentifier.type === Office.MailboxEnums.LocationType.Room) { - console.log("Email address: " + place.emailAddress); - } - }); - } else { - console.log("There are no locations."); + + // Gets annotations found in the selected paragraph. + + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id,state,critiqueAnnotation"); + + await context.sync(); + + console.log("Annotations found:"); + + for (let i = 0; i < annotations.items.length; i++) { + const annotation: Word.Annotation = annotations.items[i]; + + console.log(`ID ${annotation.id} - state '${annotation.state}':`, annotation.critiqueAnnotation.critique); } }); -'Office.AppointmentRead#getAttachmentContentAsync:member(1)': +Word.AnnotationHoveredEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachment-content.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // Gets the attachments of the current message or appointment in read mode. - // The item.attachments call can only be used in read mode. + // Registers event handlers. - const attachments = item.attachments; + await Word.run(async (context) => { + eventContexts[0] = context.document.onParagraphAdded.add(paragraphChanged); + eventContexts[1] = context.document.onParagraphChanged.add(paragraphChanged); - if (attachments.length <= 0) { - console.log("Mail item has no attachments."); - return; - } + eventContexts[2] = context.document.onAnnotationClicked.add(onClickedHandler); + eventContexts[3] = context.document.onAnnotationHovered.add(onHoveredHandler); + eventContexts[4] = context.document.onAnnotationInserted.add(onInsertedHandler); + eventContexts[5] = context.document.onAnnotationRemoved.add(onRemovedHandler); + eventContexts[6] = context.document.onAnnotationPopupAction.add(onPopupActionHandler); + await context.sync(); - for (let i = 0; i < attachments.length; i++) { - // Log the attachment type and its contents to the console. - item.getAttachmentContentAsync(attachments[i].id, handleAttachmentsCallback); - } -'Office.AppointmentRead#getEntities:member(1)': + console.log("Event handlers registered."); + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/basic-entities.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - const entities = Office.context.mailbox.item.getEntities(); - let entityTypesFound = 0; - - if (entities.addresses.length > 0) { - console.warn("physical addresses: "); - console.log(entities.addresses); - entityTypesFound++; - } + async function onHoveredHandler(args: Word.AnnotationHoveredEventArgs) { + await Word.run(async (context) => { + const annotation: Word.Annotation = context.document.getAnnotationById(args.id); + annotation.load("critiqueAnnotation"); - if (entities.contacts.length > 0) { - console.warn("contacts: "); - entities.contacts.forEach(function (contact) { console.log(contact.personName); }) - entityTypesFound++; - } + await context.sync(); - if (entities.emailAddresses.length > 0) { - console.warn("email addresses: "); - console.log(entities.emailAddresses); - entityTypesFound++; + console.log(`AnnotationHovered: ID ${args.id}:`, annotation.critiqueAnnotation.critique); + }); } +Word.AnnotationInsertedEventArgs:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - if (entities.meetingSuggestions.length > 0) { - console.warn("meetings suggestions: "); - entities.meetingSuggestions.forEach(function (meetingSuggestion) { console.log(meetingSuggestion.meetingString); }) - entityTypesFound++; - } - if (entities.phoneNumbers.length > 0) { - console.warn("phone numbers: "); - entities.phoneNumbers.forEach(function (phoneNumber) { console.log(phoneNumber.originalPhoneString); }) - entityTypesFound++; - } + // Registers event handlers. - if (entities.taskSuggestions.length > 0) { - console.warn("task suggestions: "); - entities.taskSuggestions.forEach(function (taskSuggestion) { console.log(taskSuggestion.taskString); }) - entityTypesFound++; - } + await Word.run(async (context) => { + eventContexts[0] = context.document.onParagraphAdded.add(paragraphChanged); + eventContexts[1] = context.document.onParagraphChanged.add(paragraphChanged); - if (entities.urls.length > 0) { - console.warn("URLs: "); - console.log(entities.urls); - entityTypesFound++; - } + eventContexts[2] = context.document.onAnnotationClicked.add(onClickedHandler); + eventContexts[3] = context.document.onAnnotationHovered.add(onHoveredHandler); + eventContexts[4] = context.document.onAnnotationInserted.add(onInsertedHandler); + eventContexts[5] = context.document.onAnnotationRemoved.add(onRemovedHandler); + eventContexts[6] = context.document.onAnnotationPopupAction.add(onPopupActionHandler); - if (entityTypesFound == 0) + await context.sync(); - { - console.log("No entities found on this item."); - } -'Office.AppointmentRead#getEntitiesByType:member(1)': + console.log("Event handlers registered."); + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/basic-entities.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - console.log(Office.context.mailbox.item.getEntitiesByType(Office.MailboxEnums.EntityType.Address)); -'Office.AppointmentRead#getFilteredEntitiesByName:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/contextual.yaml - // This API would only work when you click on highlighted physical address - that has the word "Way" in it. + async function onInsertedHandler(args: Word.AnnotationInsertedEventArgs) { + await Word.run(async (context) => { + const annotations = []; + for (let i = 0; i < args.ids.length; i++) { + let annotation: Word.Annotation = context.document.getAnnotationById(args.ids[i]); + annotation.load("id,critiqueAnnotation"); - console.log(Office.context.mailbox.item.getFilteredEntitiesByName("sampleFilterName")); -'Office.AppointmentRead#getRegExMatches:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/contextual.yaml + annotations.push(annotation); + } - // This API would only work when you click on highlighted word "ScriptLab". + await context.sync(); - console.log(Office.context.mailbox.item.getRegExMatches()); -'Office.AppointmentRead#getRegExMatchesByName:member(1)': + for (let annotation of annotations) { + console.log(`AnnotationInserted: ID ${annotation.id}:`, annotation.critiqueAnnotation.critique); + } + }); + } +Word.AnnotationPopupActionEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/contextual.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // This API would only work when you click on highlighted word "ScriptLab". - console.log(Office.context.mailbox.item.getRegExMatchesByName("sampleRegexName")); -'Office.AppointmentRead#getSelectedEntities:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/selected.yaml + // Registers event handlers. - const entities = Office.context.mailbox.item.getSelectedEntities(); + await Word.run(async (context) => { + eventContexts[0] = context.document.onParagraphAdded.add(paragraphChanged); + eventContexts[1] = context.document.onParagraphChanged.add(paragraphChanged); - let entityTypesFound = 0; + eventContexts[2] = context.document.onAnnotationClicked.add(onClickedHandler); + eventContexts[3] = context.document.onAnnotationHovered.add(onHoveredHandler); + eventContexts[4] = context.document.onAnnotationInserted.add(onInsertedHandler); + eventContexts[5] = context.document.onAnnotationRemoved.add(onRemovedHandler); + eventContexts[6] = context.document.onAnnotationPopupAction.add(onPopupActionHandler); - if (entities.addresses.length > 0) { - console.warn("physical addresses: "); - console.log(entities.addresses); - entityTypesFound++; - } + await context.sync(); - if (entities.contacts.length > 0) { - console.warn("contacts: "); - entities.contacts.forEach(function (contact) { console.log(contact.personName); }) - entityTypesFound++; - } + console.log("Event handlers registered."); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml + + + async function onPopupActionHandler(args: + Word.AnnotationPopupActionEventArgs) { + await Word.run(async (context) => { + let message = `AnnotationPopupAction: ID ${args.id} = `; + if (args.action === "Accept") { + message += `Accepted: ${args.critiqueSuggestion}`; + } else { + message += "Rejected"; + } - if (entities.emailAddresses.length > 0) { - console.warn("email addresses: "); - console.log(entities.emailAddresses); - entityTypesFound++; + console.log(message); + }); } +Word.AnnotationRemovedEventArgs:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - if (entities.meetingSuggestions.length > 0) { - console.warn("meetings suggestions: "); - entities.meetingSuggestions.forEach(function (meetingSuggestion) { console.log(meetingSuggestion.meetingString); }) - entityTypesFound++; - } - if (entities.phoneNumbers.length > 0) { - console.warn("phone numbers: "); - entities.phoneNumbers.forEach(function (phoneNumber) { console.log(phoneNumber.originalPhoneString); }) - entityTypesFound++; - } + // Registers event handlers. - if (entities.taskSuggestions.length > 0) { - console.warn("task suggestions: "); - entities.taskSuggestions.forEach(function (taskSuggestion) { console.log(taskSuggestion.taskString); }) - entityTypesFound++; - } + await Word.run(async (context) => { + eventContexts[0] = context.document.onParagraphAdded.add(paragraphChanged); + eventContexts[1] = context.document.onParagraphChanged.add(paragraphChanged); - if (entities.urls.length > 0) { - console.warn("URLs: "); - console.log(entities.urls); - entityTypesFound++; - } + eventContexts[2] = context.document.onAnnotationClicked.add(onClickedHandler); + eventContexts[3] = context.document.onAnnotationHovered.add(onHoveredHandler); + eventContexts[4] = context.document.onAnnotationInserted.add(onInsertedHandler); + eventContexts[5] = context.document.onAnnotationRemoved.add(onRemovedHandler); + eventContexts[6] = context.document.onAnnotationPopupAction.add(onPopupActionHandler); - if (entityTypesFound == 0) + await context.sync(); - { - console.error("Open add-in by clicking on a highlighted entity, for this API to return something useful."); - } -'Office.AppointmentRead#getSelectedRegExMatches:member(1)': + console.log("Event handlers registered."); + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/selected.yaml - - const matches = Office.context.mailbox.item.getSelectedRegExMatches(); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - if (matches) { - console.log(matches); - } - else { - console.error("Open add-in by clicking on a highlighted regex match, for this API to return something useful."); + async function onRemovedHandler(args: Word.AnnotationRemovedEventArgs) { + await Word.run(async (context) => { + for (let id of args.ids) { + console.log(`AnnotationRemoved: ID ${id}`); + } + }); } -'Office.AppointmentRead#getSharedPropertiesAsync:member(2)': +Word.AnnotationSet:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - if (!Office.context.mailbox.item.getSharedPropertiesAsync) { - console.error("Try this sample on an item from a shared folder."); - return; - } + // Adds annotations to the selected paragraph. - Office.context.mailbox.item.getSharedPropertiesAsync(function(result) { - console.log(result.value); - }); -'Office.AppointmentRead#getSharedPropertiesAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const options: Word.CritiquePopupOptions = { + brandingTextResourceId: "PG.TabLabel", + subtitleResourceId: "PG.HelpCommand.TipTitle", + titleResourceId: "PG.HelpCommand.Label", + suggestions: ["suggestion 1", "suggestion 2", "suggestion 3"] + }; + const critique1: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.red, + start: 1, + length: 3, + popupOptions: options + }; + const critique2: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.green, + start: 6, + length: 1, + popupOptions: options + }; + const critique3: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.blue, + start: 10, + length: 3, + popupOptions: options + }; + const critique4: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.lavender, + start: 14, + length: 3, + popupOptions: options + }; + const critique5: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.berry, + start: 18, + length: 10, + popupOptions: options + }; + const annotationSet: Word.AnnotationSet = { + critiques: [critique1, critique2, critique3, critique4, critique5] + }; - if (!Office.context.mailbox.item.getSharedPropertiesAsync) { - console.error("Try this sample on an appointment from a shared folder."); - return; - } + const annotationIds = paragraph.insertAnnotations(annotationSet); + await context.sync(); - Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, - function(result) { - if (result.status === Office.AsyncResultStatus.Succeeded && result.value !== "") { - Office.context.mailbox.item.getSharedPropertiesAsync( - { - // Pass auth token along. - asyncContext: result.value - }, - function(result2) { - let sharedProperties = result2.value; - let delegatePermissions = sharedProperties.delegatePermissions; - - // Determine if user has the appropriate permission to do the operation. - if ((delegatePermissions & Office.MailboxEnums.DelegatePermissions.Read) != 0) { - const ewsId = Office.context.mailbox.item.itemId; - const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); - let rest_url = - sharedProperties.targetRestUrl + "/v2.0/users/" + sharedProperties.targetMailbox + "/events/" + restId; - - $.ajax({ - url: rest_url, - dataType: "json", - headers: { Authorization: "Bearer " + result2.asyncContext } - }) - .done(function(response) { - console.log(response); - }) - .fail(function(error) { - console.error(error); - }); - } - } - ); - } + console.log("Annotations inserted:", annotationIds.value); }); -'Office.AppointmentRead#itemClass:member': +Word.AnnotationState:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-class-read.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - console.log(`Item class: ${Office.context.mailbox.item.itemClass}`); -'Office.AppointmentRead#itemType:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-type.yaml - const itemType = Office.context.mailbox.item.itemType; + // Accepts the first annotation found in the selected paragraph. - switch (itemType) { - case Office.MailboxEnums.ItemType.Appointment: - console.log(`Current item is an ${itemType}.`); - break; - case Office.MailboxEnums.ItemType.Message: - console.log(`Current item is a ${itemType}. A message could be an email, meeting request, meeting response, or meeting cancellation.`); - break; - } -'Office.AppointmentRead#loadCustomPropertiesAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id,state,critiqueAnnotation"); - Office.context.mailbox.item.loadCustomPropertiesAsync(function (result) { - if (result.status === Office.AsyncResultStatus.Succeeded) { - console.log("Loaded following custom properties:"); - customProps = result.value; - const dataKey = Object.keys(customProps)[0]; - const data = customProps[dataKey]; - for (let propertyName in data) - { - let propertyValue = data[propertyName]; - console.log(`${propertyName}: ${propertyValue}`); - } - } - else { - console.error(`loadCustomPropertiesAsync failed with message ${result.error.message}`); + await context.sync(); + + for (let i = 0; i < annotations.items.length; i++) { + const annotation: Word.Annotation = annotations.items[i]; + + if (annotation.state === Word.AnnotationState.created) { + console.log(`Accepting ID ${annotation.id}...`); + annotation.critiqueAnnotation.accept(); + + await context.sync(); + break; + } } }); -'Office.AppointmentRead#location:member': +Word.Application:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-location-read.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-external-document.yaml - console.log(`Appointment location: - ${Office.context.mailbox.item.location}`); -'Office.AppointmentRead#normalizedSubject:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-normalized-subject-read.yaml - console.log(`Normalized subject: - ${Office.context.mailbox.item.normalizedSubject}`); -'Office.AppointmentRead#notificationMessages:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Updates the text of the current document with the text from another + document passed in as a Base64-encoded string. - const id = $("#notificationId").val(); + await Word.run(async (context) => { + // Use the Base64-encoded string representation of the selected .docx file. + const externalDoc: Word.DocumentCreated = context.application.createDocument(externalDocument); + await context.sync(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.ProgressIndicator, - message: "Progress indicator with id = " + id - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + if (!Office.context.requirements.isSetSupported("WordApiHiddenDocument", "1.3")) { + console.warn("The WordApiHiddenDocument 1.3 requirement set isn't supported on this client so can't proceed. Try this action on a platform that supports this requirement set."); + return; + } - const id = $("#notificationId").val(); + const externalDocBody: Word.Body = externalDoc.body; + externalDocBody.load("text"); + await context.sync(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Non-persistent informational notification message with id = " + id, - icon: "icon1", - persistent: false - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); + // Insert the external document's text at the beginning of the current document's body. + const externalDocBodyText = externalDocBody.text; + const currentDocBody: Word.Body = context.document.body; + currentDocBody.insertText(externalDocBodyText, Word.InsertLocation.start); + await context.sync(); + }); +Word.Application#createDocument:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml - - const id = $("#notificationId").val(); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-external-document.yaml - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Persistent informational notification message with id = " + id, - icon: "icon1", - persistent: true - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml - Office.context.mailbox.item.notificationMessages.getAllAsync(handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Updates the text of the current document with the text from another + document passed in as a Base64-encoded string. - const id = $("#notificationId").val(); + await Word.run(async (context) => { + // Use the Base64-encoded string representation of the selected .docx file. + const externalDoc: Word.DocumentCreated = context.application.createDocument(externalDocument); + await context.sync(); - Office.context.mailbox.item.notificationMessages.replaceAsync( - id, - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Notification message with id = " + id + " has been replaced with an informational message.", - icon: "icon2", - persistent: false - }, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + if (!Office.context.requirements.isSetSupported("WordApiHiddenDocument", "1.3")) { + console.warn("The WordApiHiddenDocument 1.3 requirement set isn't supported on this client so can't proceed. Try this action on a platform that supports this requirement set."); + return; + } - const id = $("#notificationId").val(); + const externalDocBody: Word.Body = externalDoc.body; + externalDocBody.load("text"); + await context.sync(); - Office.context.mailbox.item.notificationMessages.removeAsync(id, - handleResult); -'Office.AppointmentRead#optionalAttendees:member': + // Insert the external document's text at the beginning of the current document's body. + const externalDocBodyText = externalDocBody.text; + const currentDocBody: Word.Body = context.document.body; + currentDocBody.insertText(externalDocBodyText, Word.InsertLocation.start); + await context.sync(); + }); +Word.Application#retrieveStylesFromBase64:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-optional-attendees-appointment-attendee.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/get-external-styles.yaml - const apptOptionalAttendees = Office.context.mailbox.item.optionalAttendees; - console.log("Optional attendees:"); + // Gets style info from another document passed in as a Base64-encoded + string. - for (let i = 0; i < apptOptionalAttendees.length; i++) { - console.log( - apptOptionalAttendees[i].displayName + - " (" + - apptOptionalAttendees[i].emailAddress + - ") - response: " + - apptOptionalAttendees[i].appointmentResponse - ); - } -'Office.AppointmentRead#organizer:member': + await Word.run(async (context) => { + const retrievedStyles = context.application.retrieveStylesFromBase64(externalDocument); + await context.sync(); + + console.log("Styles from the other document:", retrievedStyles.value); + }); +Word.Body#clear:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-organizer-appointment-attendee.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - const apptOrganizer = Office.context.mailbox.item.organizer; - console.log("Organizer: " + apptOrganizer.displayName + " (" + - apptOrganizer.emailAddress + ")"); -'Office.AppointmentRead#recurrence:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-recurrence-read.yaml + // Clears out the content from the document body. - const recurrence = Office.context.mailbox.item.recurrence; + // Run a batch operation against the Word object model. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; - if (recurrence === undefined) { - console.log("This item is a message but not a meeting request."); - } else if (recurrence === null) { - console.log("This is a single appointment."); - } else { - console.log(JSON.stringify(recurrence)); - } -'Office.AppointmentRead#requiredAttendees:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-required-attendees-appointment-attendee.yaml + // Queue a command to clear the contents of the body. + body.clear(); - const apptRequiredAttendees = Office.context.mailbox.item.requiredAttendees; + console.log("Cleared the body contents."); + }); - console.log("Required attendees:"); - for (let i = 0; i < apptRequiredAttendees.length; i++) { - console.log( - apptRequiredAttendees[i].displayName + - " (" + - apptRequiredAttendees[i].emailAddress + - ") - response: " + - apptRequiredAttendees[i].appointmentResponse - ); - } -'Office.AppointmentRead#seriesId:member': + // The Silly stories add-in sample shows how the clear method can be used to + clear the contents of a document. + + // https://aka.ms/sillystorywordaddin +Word.Body#getComments:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-series-id.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - const seriesId = Office.context.mailbox.item.seriesId; + // Gets the comments in the document body. - if (seriesId === undefined) { - console.log("This is a message that's not a meeting request."); - } else if (seriesId === null) { - console.log("This is a single appointment, a parent series, or a meeting request for a series or single meeting."); - } else { - console.log("This is an instance belonging to series with ID " + seriesId); - } -'Office.AppointmentRead#start:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-start-read.yaml + await Word.run(async (context) => { + const comments: Word.CommentCollection = context.document.body.getComments(); - console.log(`Appointment starts: ${Office.context.mailbox.item.start}`); -'Office.AppointmentRead#subject:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-subject-read.yaml + // Load objects to log in the console. + comments.load(); + await context.sync(); - console.log(`Subject: ${Office.context.mailbox.item.subject}`); -'Office.Body#appendOnSendAsync:member(1)': + console.log("All comments:", comments); + }); +Word.Body#getHtml:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/append-text-on-send.yaml - - // This snippet appends text to the end of the message or appointment's body - once it's sent. + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - const text = $("#text-field").val(); + // Gets the HTML that represents the content of the body. - // It's recommended to call getTypeAsync and pass its returned value to the - options.coercionType parameter of the appendOnSendAsync call. - - Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Action failed with error: " + asyncResult.error.message); - return; - } + // Run a batch operation against the Word object model. - const bodyFormat = asyncResult.value; - Office.context.mailbox.item.body.appendOnSendAsync(text, { coercionType: bodyFormat }, (asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Action failed with error: " + asyncResult.error.message); - return; - } + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; - console.log(`"${text}" will be appended to the body once the message or appointment is sent. Send the mail item to test this feature.`); - }); + // Queue a command to get the HTML contents of the body. + const bodyHTML = body.getHtml(); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Body contents (HTML): " + bodyHTML.value); }); -'Office.Body#getAsync:member(2)': +Word.Body#getOoxml:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/add-inline-base64-image.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - const mailItem = Office.context.mailbox.item; - 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=="; + // Gets the OOXML that represents the content of the body. - // Get the current body of the message or appointment. + // Run a batch operation against the Word object model. - 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); - } - }); - } else { - console.log(bodyResult.error.message); - } + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to get the OOXML contents of the body. + const bodyOOXML = body.getOoxml(); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Body contents (OOXML): " + bodyOOXML.value); }); -'Office.Body#getTypeAsync:member(1)': +Word.Body#getTrackedChanges:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/get-body-format.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml - // Get the mail item's body format (plain text or HTML) and log it to the - console. - Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Action failed with error: " + asyncResult.error.message); - return; - } + // Gets all tracked changes. - console.log("Body format: " + asyncResult.value); + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + trackedChanges.load(); + await context.sync(); + + console.log(trackedChanges); }); -'Office.Body#prependAsync:member(1)': +Word.Body#insertBreak:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/prepend-text-to-item-body.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - /* This snippet adds text to the beginning of the message or appointment's - body. - - When prepending a link in HTML markup to the body, you can disable the online link preview by setting the anchor tag's id attribute to "LPNoLP". For example, 'Click here!'. - */ - const text = $("#text-field").val(); + // Inserts a page break at the beginning of the document. + // Run a batch operation against the Word object model. - // It's recommended to call getTypeAsync and pass its returned value to the - options.coercionType parameter of the prependAsync call. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; - Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Action failed with error: " + asyncResult.error.message); - return; - } + // Queue a command to insert a page break at the start of the document body. + body.insertBreak(Word.BreakType.page, Word.InsertLocation.start); - const bodyFormat = asyncResult.value; - Office.context.mailbox.item.body.prependAsync(text, { coercionType: bodyFormat }, (asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Action failed with error: " + asyncResult.error.message); - return; - } + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); - console.log(`"${text}" prepended to the body.`); - }); + console.log("Added a page break at the start of the document body."); }); -'Office.Body#prependOnSendAsync:member(1)': +Word.Body#insertContentControl:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/prepend-text-on-send.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - // This snippet prepends text to the beginning of the message or - appointment's body once it's sent. - const text = $("#text-field").val(); + // Creates a content control using the document body. + // Run a batch operation against the Word object model. - // It's recommended to call getTypeAsync and pass its returned value to the - options.coercionType parameter of the prependOnSendAsync call. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; - Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Action failed with error: " + asyncResult.error.message); - return; - } + // Queue a command to wrap the body in a content control. + body.insertContentControl(); - const bodyFormat = asyncResult.value; - Office.context.mailbox.item.body.prependOnSendAsync(text, { coercionType: bodyFormat }, (asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Action failed with error: " + asyncResult.error.message); - return; - } + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); - console.log(`"${text}" will be prepended to the body once the message or appointment is sent. Send the mail item to test this feature.`); - }); + console.log("Wrapped the body in a content control."); }); -'Office.Body#setAsync:member(1)': +Word.Body#insertFileFromBase64:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/add-inline-base64-image.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - const mailItem = Office.context.mailbox.item; - 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=="; + // Inserts the body from the external document at the beginning of this + document. - // Get the current body of the message or appointment. + // Run a batch operation against the Word object model. - 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); - } - }); - } else { - console.log(bodyResult.error.message); - } + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to insert the Base64-encoded string representation of the body of the selected .docx file at the beginning of the current document. + body.insertFileFromBase64(externalDocument, Word.InsertLocation.start); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Added Base64-encoded text to the beginning of the document body."); }); -'Office.Body#setSelectedDataAsync:member(1)': +Word.Body#insertHtml:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/replace-selected-text.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - /* This snippet replaces selected text in a message or appointment's body - with specified text. - - If you want to use a link in HTML markup as a value of the setSelectedDataAsync call's data parameter, you can disable online link preview by setting the anchor tag's id attribute to "LPNoLP". For example, 'Click here!'. - */ - const text = $("#text-field").val(); + // Inserts the HTML at the beginning of this document. + // Run a batch operation against the Word object model. - // It's recommended to call getTypeAsync and pass its returned value to the - options.coercionType parameter of the prependAsync call. + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; - Office.context.mailbox.item.body.getTypeAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Action failed with error: " + asyncResult.error.message); - return; - } + // Queue a command to insert HTML at the beginning of the document. + body.insertHtml("This is text inserted with body.insertHtml()", Word.InsertLocation.start); - const bodyFormat = asyncResult.value; - Office.context.mailbox.item.body.setSelectedDataAsync(text, { coercionType: bodyFormat }, (asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Action failed with error: " + asyncResult.error.message); - return; - } + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); - console.log(`Replaced selected text with "${text}".`); - }); + console.log("HTML added to the beginning of the document body."); }); -'Office.Body#setSignatureAsync:member(1)': +Word.Body#insertInlinePictureFromBase64:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - // Set the signature for the current item with inline image. - const modIcon1Base64 = - "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpDRDMxMDg1MjBCNDZFMTExODE2MkM1RUI2M0M4MDYxRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFMTUxQjgyRjQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFMTUxQjgyRTQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkQxMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkNEMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+uC/WfAAAAehJREFUeNpilCzfwEAEkAbiECA2A2J1IOaHin8E4ptAfBaIVwLxU0IGMRKw0B6IW4DYhoE4cASIK6E0VsCEQ1wUiNcB8QESLGOAqj0MxBuhZhBloS4QnwHiQAbygR/UDF1CFupCXSjHQDmQg5qli8tCUBBsQUoQ1AD8UDNFsVk4n0o+w+bT+egWglKjNymmeGhLkqLcG2oHAwtUoIuQDj5OVgZPLUmwRe5aEmAxqYqNpFgKssOcCeplM0KqdST5GfpDDRm0JfkYrj3/SE7QguyQY4ImYYLgCtAS10kHGMw6dzNsv/qC7OwCClJXYlR++v6b4er3j5QmIFcmaNlIL6AOslCIjhYKMTHQGTBBqxh6gXcgC6/R0cKbIAv30dHCfaAKGJTxHxJSqS3Fz9DkowNmywpyMcgA8fF7b8D8VWcfM6w8+4gYC+VB+RCk8hSh0gaUD4/dewvlvUWRe/z+GzGWgex4BGtiOAHxXhoHpzMoSGHZAhSPW2lo2VZYWkHOh4nEtLrIAE+hZmNUwK+B2BOIv1PRsu9QM1/jatNcBtVZ0IREKXgENesyoVYbzNIdFFi2A5tl+NqlL6BB4QBNzsSCU1A9nlAzMAALAQMOQl0qB23qWwKxIlIrDBQ394H4OBCvISYqAAIMACVibHDqsO7zAAAAAElFTkSuQmCC"; + // Inserts an image inline at the beginning of this document. - Office.context.mailbox.item.addFileAttachmentFromBase64Async( - modIcon1Base64, - "myImage.png", - { isInline: true }, - function(result) { - if (result.status == Office.AsyncResultStatus.Succeeded) { - const signature = $("#signature").val() + ""; - console.log(`Setting signature to "${signature}".`); - Office.context.mailbox.item.body.setSignatureAsync( - signature, - { coercionType: "html" }, - function(asyncResult) { - console.log(`setSignatureAsync: ${asyncResult.status}`); - } - ); - } else { - console.error(`addFileAttachmentFromBase64Async: ${result.error}`); - } - } - ); + // Run a batch operation against the Word object model. + + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Base64-encoded image to insert inline. + const base64EncodedImg = + "iVBORw0KGgoAAAANSUhEUgAAAB4AAAANCAIAAAAxEEnAAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACFSURBVDhPtY1BEoQwDMP6/0+XgIMTBAeYoTqso9Rkx1zG+tNj1H94jgGzeNSjteO5vtQQuG2seO0av8LzGbe3anzRoJ4ybm/VeKEerAEbAUpW4aWQCmrGFWykRzGBCnYy2ha3oAIq2MloW9yCCqhgJ6NtcQsqoIKdjLbFLaiACnYyf2fODbrjZcXfr2F4AAAAAElFTkSuQmCC"; + + // Queue a command to insert a Base64-encoded image at the beginning of the current document. + body.insertInlinePictureFromBase64(base64EncodedImg, Word.InsertLocation.start); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Added a Base64-encoded image to the beginning of the document body."); + }); +Word.Body#insertOoxml:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - // Set the signature for the current item. - const signature = $("#signature").val(); + // Inserts OOXML at the beginning of this document. - console.log(`Setting signature to "${signature}".`); + // Run a batch operation against the Word object model. - Office.context.mailbox.item.body.setSignatureAsync(signature, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("setSignatureAsync succeeded"); - } else { - console.error(asyncResult.error); - } + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to insert OOXML at the beginning of the body. + body.insertOoxml( + "This text has formatting directly applied to achieve its font size, color, line spacing, and paragraph spacing.", + Word.InsertLocation.start + ); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Added OOXML to the beginning of the document body."); }); -'Office.Categories#addAsync:member(1)': + + + // Read "Understand when and how to use Office Open XML in your Word add-in" + for guidance on working with OOXML. + + // + https://learn.microsoft.com/office/dev/add-ins/word/create-better-add-ins-for-word-with-office-open-xml + + + // The Word-Add-in-DocumentAssembly sample shows how you can use this API to + assemble a document. + + // https://github.com/OfficeDev/Word-Add-in-DocumentAssembly +Word.Body#insertParagraph:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml - - // Note: In order for you to successfully add a category, + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-formatted-text.yaml - // it must be in the mailbox categories master list. + await Word.run(async (context) => { + // Second sentence, let's insert it as a paragraph after the previously inserted one. + const secondSentence: Word.Paragraph = context.document.body.insertParagraph( + "This is the first text with a custom style.", + "End" + ); + secondSentence.font.set({ + bold: false, + italic: true, + name: "Berlin Sans FB", + color: "blue", + size: 30 + }); - Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const masterCategories = asyncResult.value; - if (masterCategories && masterCategories.length > 0) { - // Grab the first category from the master list. - const categoryToAdd = [masterCategories[0].displayName]; - Office.context.mailbox.item.categories.addAsync(categoryToAdd, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully assigned category '${categoryToAdd}' to item.`); - } else { - console.log("categories.addAsync call failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("There are no categories in the master list on this mailbox. You can add categories using Office.context.mailbox.masterCategories.addAsync."); - } - } else { - console.error(asyncResult.error); - } + await context.sync(); }); -'Office.Categories#getAsync:member(2)': +Word.Body#insertTable:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/table-cell-access.yaml - Office.context.mailbox.item.categories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - console.log("Categories assigned to this item:"); - console.log(JSON.stringify(categories)); - } else { - console.log("There are no categories assigned to this item."); - } - } else { - console.error(asyncResult.error); - } + + await Word.run(async (context) => { + // Use a two-dimensional array to hold the initial table values. + const data = [ + ["Tokyo", "Beijing", "Seattle"], + ["Apple", "Orange", "Pineapple"] + ]; + const table: Word.Table = context.document.body.insertTable(2, 3, "Start", data); + table.styleBuiltIn = Word.BuiltInStyleName.gridTable5Dark_Accent2; + table.styleFirstColumn = false; + + await context.sync(); }); -'Office.Categories#removeAsync:member(1)': +Word.Body#insertText:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - Office.context.mailbox.item.categories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - // Grab the first category assigned to this item. - const categoryToRemove = [categories[0].displayName]; - Office.context.mailbox.item.categories.removeAsync(categoryToRemove, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully unassigned category '${categoryToRemove}' from this item.`); - } else { - console.log("categories.removeAsync call failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("There are no categories assigned to this item."); - } - } else { - console.error(asyncResult.error); - } + + // Inserts text at the beginning of this document. + + // Run a batch operation against the Word object model. + + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to insert text at the beginning of the current document. + body.insertText('This is text inserted with body.insertText()', Word.InsertLocation.start); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Text added to the beginning of the document body."); }); -'Office.CustomProperties#get:member(1)': +Word.Body#search:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/search.yaml - const propertyName = $("#propertyName").val(); - const propertyValue = customProps.get(propertyName); + // Does a basic text search and highlights matches in the document. - $("#propertyValue").val(propertyValue); + await Word.run(async (context) => { + const results : Word.RangeCollection = context.document.body.search("extend"); + results.load("length"); - console.log(`The value of custom property "${propertyName}" is - "${propertyValue}".`); -'Office.CustomProperties#remove:member(1)': + await context.sync(); + + // Let's traverse the search results and highlight matches. + for (let i = 0; i < results.items.length; i++) { + results.items[i].font.highlightColor = "yellow"; + } + + await context.sync(); + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/search.yaml - const propertyName = $("#propertyName").val(); - customProps.remove(propertyName); + // Does a wildcard search and highlights matches in the document. - console.log(`Custom property "${propertyName}" removed.`); -'Office.CustomProperties#set:member(1)': + await Word.run(async (context) => { + // Construct a wildcard expression and set matchWildcards to true in order to use wildcards. + const results : Word.RangeCollection = context.document.body.search("$*.[0-9][0-9]", { matchWildcards: true }); + results.load("length"); + + await context.sync(); + + // Let's traverse the search results and highlight matches. + for (let i = 0; i < results.items.length; i++) { + results.items[i].font.highlightColor = "red"; + results.items[i].font.color = "white"; + } + + await context.sync(); + }); +Word.Body#select:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - const propertyName = $("#propertyName").val(); - const propertyValue = $("#propertyValue").val(); + // Selects the entire body. - customProps.set(propertyName, propertyValue); + // Run a batch operation against the Word object model. - console.log(`Custom property "${propertyName}" set to value - "${propertyValue}".`); -'Office.DelayDeliveryTime#getAsync:member(2)': + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to select the document body. + // The Word UI will move to the selected document body. + body.select(); + + console.log("Selected the document body."); + }); +Word.Body#fields:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/delay-message-delivery.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - // This snippet gets the delivery date and time of a message. - Office.context.mailbox.item.delayDeliveryTime.getAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log(asyncResult.error.message); - return; - } + // Gets all fields in the document body. - const deliveryDate = asyncResult.value; - if (deliveryDate === 0) { - console.log("Your message will be delivered immediately when you select Send."); + await Word.run(async (context) => { + const fields: Word.FieldCollection = context.document.body.fields.load("items"); + + await context.sync(); + + if (fields.items.length === 0) { + console.log("No fields in this document."); } else { - const date = new Date(deliveryDate); - console.log(`Message delivery date and time: ${date.toString()}`); + fields.load(["code", "result"]); + await context.sync(); + + for (let i = 0; i < fields.items.length; i++) { + console.log(`Field ${i + 1}'s code: ${fields.items[i].code}`, `Field ${i + 1}'s result: ${JSON.stringify(fields.items[i].result)}`); + } } }); -'Office.DelayDeliveryTime#setAsync:member(2)': +Word.Body#font:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/delay-message-delivery.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - function setDeliveryDate(minutes) { - // This snippet sets the delivery date and time of a message. - const currentTime = new Date().getTime(); - const milliseconds = totalDelay * 60000; - const timeDelay = new Date(currentTime + milliseconds); - Office.context.mailbox.item.delayDeliveryTime.setAsync(timeDelay, (asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log(asyncResult.error.message); - return; - } - if (minutes === 1440) { - console.log(`Delayed delivery by an additional one day.`); - } else { - console.log(`Delayed delivery by an additional ${minutes} minutes.`); - } - }); - } -'Office.Display#body:member': + // Gets the style and the font size, font name, and font color properties on + the body object. + + // Run a batch operation against the Word object model. + + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to load font and style information for the document body. + body.load("font/size, font/name, font/color, style"); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + // Show font-related property values on the body object. + const results = + "Font size: " + + body.font.size + + "; Font name: " + + body.font.name + + "; Font color: " + + body.font.color + + "; Body style: " + + body.style; + + console.log(results); + }); +Word.Body#footnotes:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml - // This snippet temporarily sets the content displayed in the body of a - message in read mode. - // The set content will remain visible until the user switches to a - different message in the Reading Pane or closes the window of the current - message. + // Gets the footnotes in the document body. - const bodyText = $("#body-text-field") - .val() - .toString(); - Office.context.mailbox.item.display.body.setAsync(bodyText, (asyncResult) => - { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log(`Action failed with error: ${asyncResult.error.message}`); - return; - } + await Word.run(async (context) => { + const footnotes: Word.NoteItemCollection = context.document.body.footnotes; + footnotes.load("length"); + await context.sync(); - console.log("Temporarily set the content displayed in the body."); + console.log("Number of footnotes in the document body: " + footnotes.items.length); }); -'Office.Display#subject:member': +Word.Body#inlinePictures:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml - // This snippet temporarily sets the content displayed in the subject field - of a message in read mode. - // The set content will remain visible until the user switches to a - different message in the Reading Pane or closes the window of the current - message. + // Gets the first image in the document. - const subjectText = $("#subject-text-field") - .val() - .toString(); - Office.context.mailbox.item.display.subject.setAsync(subjectText, - (asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log(`Action failed with error: ${asyncResult.error.message}`); - return; - } + await Word.run(async (context) => { + const firstPicture: Word.InlinePicture = context.document.body.inlinePictures.getFirst(); + firstPicture.load("width, height, imageFormat"); - console.log("Temporarily set the content displayed in the subject field."); + await context.sync(); + console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`, `Image format: ${firstPicture.imageFormat}`); + // Get the image encoded as Base64. + const base64 = firstPicture.getBase64ImageSrc(); + + await context.sync(); + console.log(base64.value); }); -'Office.DisplayedBody#setAsync:member(2)': +Word.Body#lists:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml - // This snippet temporarily sets the content displayed in the body of a - message in read mode. - // The set content will remain visible until the user switches to a - different message in the Reading Pane or closes the window of the current - message. + // Gets information about the first list in the document. - const bodyText = $("#body-text-field") - .val() - .toString(); - Office.context.mailbox.item.display.body.setAsync(bodyText, (asyncResult) => - { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log(`Action failed with error: ${asyncResult.error.message}`); + await Word.run(async (context) => { + const lists: Word.ListCollection = context.document.body.lists; + lists.load("items"); + + await context.sync(); + + if (lists.items.length === 0) { + console.warn("There are no lists in this document."); return; } + + // Get the first list. + const list: Word.List = lists.getFirst(); + list.load("levelTypes,levelExistences"); - console.log("Temporarily set the content displayed in the body."); + await context.sync(); + + const levelTypes = list.levelTypes; + console.log("Level types of the first list:"); + for (let i = 0; i < levelTypes.length; i++) { + console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); + } + + const levelExistences = list.levelExistences; + console.log("Level existences of the first list:"); + for (let i = 0; i < levelExistences.length; i++) { + console.log(`- Level ${i + 1} (index ${i}): ${levelExistences[i]}`); + } }); -'Office.DisplayedSubject#setAsync:member(2)': +Word.Body#onCommentAdded:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - // This snippet temporarily sets the content displayed in the subject field - of a message in read mode. - // The set content will remain visible until the user switches to a - different message in the Reading Pane or closes the window of the current - message. + // Registers event handlers. - const subjectText = $("#subject-text-field") - .val() - .toString(); - Office.context.mailbox.item.display.subject.setAsync(subjectText, - (asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log(`Action failed with error: ${asyncResult.error.message}`); - return; - } + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.track(); + await context.sync(); - console.log("Temporarily set the content displayed in the subject field."); + eventContexts[0] = body.onCommentAdded.add(onEventHandler); + eventContexts[1] = body.onCommentChanged.add(onChangedHandler); + eventContexts[2] = body.onCommentDeleted.add(onEventHandler); + eventContexts[3] = body.onCommentDeselected.add(onEventHandler); + eventContexts[4] = body.onCommentSelected.add(onEventHandler); + await context.sync(); + + console.log("Event handlers registered."); }); -'Office.EnhancedLocation#addAsync:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - const locations = [ - { - id: "Contoso", - type: Office.MailboxEnums.LocationType.Custom - }, - { - id: "room500@test.com", - type: Office.MailboxEnums.LocationType.Room - } - ]; - Office.context.mailbox.item.enhancedLocation.addAsync(locations, (result) => - { - if (result.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully added locations ${JSON.stringify(locations)}`); - } else { - console.error(`Failed to add locations. Error message: ${result.error.message}`); - } - }); -'Office.EnhancedLocation#getAsync:member(1)': + async function onEventHandler(event: Word.CommentEventArgs) { + // Handler for all events except onCommentChanged. + await Word.run(async (context) => { + console.log(`${event.type} event detected. Event source: ${event.source}. Comment info:`, event.commentDetails); + }); + } +Word.Body#onCommentChanged:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - Office.context.mailbox.item.enhancedLocation.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Failed to get locations. Error message: ${result.error.message}`); - return; - } - const places = result.value; - if (places && places.length > 0) { - result.value.forEach(function(place) { - console.log(`Location: ${place.displayName} (type: ${place.locationIdentifier.type})`); - if (place.locationIdentifier.type === Office.MailboxEnums.LocationType.Room) { - console.log("Email address: " + place.emailAddress); - } - }); - } else { - console.log("There are no locations."); - } + + // Registers event handlers. + + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.track(); + await context.sync(); + + eventContexts[0] = body.onCommentAdded.add(onEventHandler); + eventContexts[1] = body.onCommentChanged.add(onChangedHandler); + eventContexts[2] = body.onCommentDeleted.add(onEventHandler); + eventContexts[3] = body.onCommentDeselected.add(onEventHandler); + eventContexts[4] = body.onCommentSelected.add(onEventHandler); + await context.sync(); + + console.log("Event handlers registered."); }); -'Office.EnhancedLocation#removeAsync:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - const locations = [ - { - id: "Contoso", - type: Office.MailboxEnums.LocationType.Custom - }, - { - id: "room500@test.com", - type: Office.MailboxEnums.LocationType.Room - } - ]; - Office.context.mailbox.item.enhancedLocation.removeAsync(locations, (result) - => { - if (result.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully removed locations ${JSON.stringify(locations)}`); - } else { - console.error(`Failed to remove locations. Error message: ${result.error.message}`); - } + async function onChangedHandler(event: Word.CommentEventArgs) { + await Word.run(async (context) => { + console.log( + `${event.type} event detected. ${event.changeType} change made. Event source: ${event.source}. Comment info:`, event.commentDetails + ); + }); + } +Word.Body#onCommentDeleted:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml + + + // Registers event handlers. + + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.track(); + await context.sync(); + + eventContexts[0] = body.onCommentAdded.add(onEventHandler); + eventContexts[1] = body.onCommentChanged.add(onChangedHandler); + eventContexts[2] = body.onCommentDeleted.add(onEventHandler); + eventContexts[3] = body.onCommentDeselected.add(onEventHandler); + eventContexts[4] = body.onCommentSelected.add(onEventHandler); + await context.sync(); + + console.log("Event handlers registered."); }); -'Office.From#getAsync:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-from-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - Office.context.mailbox.item.from.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const msgFrom = asyncResult.value; - console.log("Message from: " + msgFrom.displayName + " (" + msgFrom.emailAddress + ")"); - } else { - console.error(asyncResult.error); - } + + async function onEventHandler(event: Word.CommentEventArgs) { + // Handler for all events except onCommentChanged. + await Word.run(async (context) => { + console.log(`${event.type} event detected. Event source: ${event.source}. Comment info:`, event.commentDetails); + }); + } +Word.Body#onCommentDeselected:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml + + + // Registers event handlers. + + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.track(); + await context.sync(); + + eventContexts[0] = body.onCommentAdded.add(onEventHandler); + eventContexts[1] = body.onCommentChanged.add(onChangedHandler); + eventContexts[2] = body.onCommentDeleted.add(onEventHandler); + eventContexts[3] = body.onCommentDeselected.add(onEventHandler); + eventContexts[4] = body.onCommentSelected.add(onEventHandler); + await context.sync(); + + console.log("Event handlers registered."); }); -'Office.InternetHeaders#getAsync:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - Office.context.mailbox.item.internetHeaders.getAsync( - ["x-preferred-fruit", "x-preferred-vegetable", "x-best-vegetable", "x-nonexistent-header"], - function (asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Selected headers: " + JSON.stringify(asyncResult.value)); - } else { - console.log("Error getting selected headers: " + JSON.stringify(asyncResult.error)); - } - } - ); -'Office.InternetHeaders#removeAsync:member(1)': + + async function onEventHandler(event: Word.CommentEventArgs) { + // Handler for all events except onCommentChanged. + await Word.run(async (context) => { + console.log(`${event.type} event detected. Event source: ${event.source}. Comment info:`, event.commentDetails); + }); + } +Word.Body#onCommentSelected:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - Office.context.mailbox.item.internetHeaders.removeAsync( - ["x-best-vegetable", "x-nonexistent-header"], - function (asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Successfully removed selected headers"); - } else { - console.log("Error removing selected headers: " + JSON.stringify(asyncResult.error)); - } - } - ); -'Office.InternetHeaders#setAsync:member(1)': + + // Registers event handlers. + + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.track(); + await context.sync(); + + eventContexts[0] = body.onCommentAdded.add(onEventHandler); + eventContexts[1] = body.onCommentChanged.add(onChangedHandler); + eventContexts[2] = body.onCommentDeleted.add(onEventHandler); + eventContexts[3] = body.onCommentDeselected.add(onEventHandler); + eventContexts[4] = body.onCommentSelected.add(onEventHandler); + await context.sync(); + + console.log("Event handlers registered."); + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - Office.context.mailbox.item.internetHeaders.setAsync( - { "x-preferred-fruit": "orange", "x-preferred-vegetable": "broccoli", "x-best-vegetable": "spinach" }, - function (asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Successfully set headers"); - } else { - console.log("Error setting headers: " + JSON.stringify(asyncResult.error)); - } - } - ); -'Office.IsAllDayEvent#getAsync:member(2)': + async function onEventHandler(event: Word.CommentEventArgs) { + // Handler for all events except onCommentChanged. + await Word.run(async (context) => { + console.log(`${event.type} event detected. Event source: ${event.source}. Comment info:`, event.commentDetails); + }); + } +Word.Body#paragraphs:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/calendar-properties-apis.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-word-count.yaml - Office.context.mailbox.item.isAllDayEvent.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Is this an all-day event? " + asyncResult.value); - } else { - console.log("Failed to get if this is an all-day event. Error: " + JSON.stringify(asyncResult.error)); + + // Counts how many times each term appears in the document. + + await Word.run(async (context) => { + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("text"); + await context.sync(); + + // Split up the document text using existing spaces as the delimiter. + let text = []; + paragraphs.items.forEach((item) => { + let paragraph = item.text.trim(); + if (paragraph) { + paragraph.split(" ").forEach((term) => { + let currentTerm = term.trim(); + if (currentTerm) { + text.push(currentTerm); + } + }); + } + }); + + // Determine the list of unique terms. + let makeTextDistinct = new Set(text); + let distinctText = Array.from(makeTextDistinct); + let allSearchResults = []; + + for (let i = 0; i < distinctText.length; i++) { + let results = context.document.body.search(distinctText[i], { matchCase: true, matchWholeWord: true }); + results.load("text"); + + // Map each search term with its results. + let correlatedResults = { + searchTerm: distinctText[i], + hits: results + }; + + allSearchResults.push(correlatedResults); } + + await context.sync(); + + // Display the count for each search term. + allSearchResults.forEach((result) => { + let length = result.hits.items.length; + + console.log("Search term: " + result.searchTerm + " => Count: " + length); + }); }); -'Office.IsAllDayEvent#setAsync:member(1)': +Word.Body#shapes:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/calendar-properties-apis.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml - Office.context.mailbox.item.isAllDayEvent.setAsync(true, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Failed to set all-day event: " + JSON.stringify(asyncResult.error)); + + await Word.run(async (context) => { + // Gets text boxes in main document. + const shapes: Word.ShapeCollection = context.document.body.shapes; + shapes.load(); + await context.sync(); + + if (shapes.items.length > 0) { + shapes.items.forEach(function (shape, index) { + if (shape.type === Word.ShapeType.textBox) { + console.log(`Shape ${index} in the main document has a text box. Properties:`, shape); + } + }); } else { - console.log("Appointment set to all-day event."); + console.log("No shapes found in main document."); } }); -'Office.Location#getAsync:member(2)': +Word.Body#tables:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-location-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/table-cell-access.yaml - Office.context.mailbox.item.location.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; - } - console.log(`Appointment location: ${result.value}`); + + // Gets the content of the first cell in the first table. + + await Word.run(async (context) => { + const firstCell: Word.Body = context.document.body.tables.getFirst().getCell(0, 0).body; + firstCell.load("text"); + + await context.sync(); + console.log("First cell's text is: " + firstCell.text); }); -'Office.Location#setAsync:member(1)': +Word.Body#text:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-location-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml - const location = "my office"; - Office.context.mailbox.item.location.setAsync(location, (result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; - } - console.log(`Successfully set location to ${location}`); + // Gets the text content of the body. + + // Run a batch operation against the Word object model. + + await Word.run(async (context) => { + // Create a proxy object for the document body. + const body: Word.Body = context.document.body; + + // Queue a command to load the text in document body. + body.load("text"); + + // Synchronize the document state by executing the queued commands, and return a promise to indicate task completion. + await context.sync(); + + console.log("Body contents (text): " + body.text); }); -'Office.Mailbox#convertToEwsId:member(1)': +Word.Body#type:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/ids-and-urls.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml - console.log("EWS URL: " + Office.context.mailbox.ewsUrl); - const ewsId = Office.context.mailbox.item.itemId; + // Gets the referenced note's item type and body type, which are both + "Footnote". - console.log("EWS item ID: " + Office.context.mailbox.item.itemId); + await Word.run(async (context) => { + const footnotes: Word.NoteItemCollection = context.document.body.footnotes; + footnotes.load("items"); + await context.sync(); + const referenceNumber = (document.getElementById("input-reference") as HTMLInputElement).value; + const mark = (referenceNumber as number) - 1; + const item: Word.NoteItem = footnotes.items[mark]; + console.log(`Note type of footnote ${referenceNumber}: ${item.type}`); - console.log("REST URL: " + Office.context.mailbox.restUrl); + item.body.load("type"); + await context.sync(); - const restId = Office.context.mailbox.convertToRestId(ewsId, - Office.MailboxEnums.RestVersion.v2_0); + console.log(`Body type of note: ${item.body.type}`); + }); +Word.BodyType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml - console.log("REST item ID: " + restId); + // Gets the referenced note's item type and body type, which are both + "Footnote". - const ewsId2 = Office.context.mailbox.convertToEwsId(restId, - Office.MailboxEnums.RestVersion.v2_0); + await Word.run(async (context) => { + const footnotes: Word.NoteItemCollection = context.document.body.footnotes; + footnotes.load("items"); + await context.sync(); - console.log("EWS ID (from REST ID): " + ewsId2); -'Office.Mailbox#convertToRestId:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/basic-rest-cors.yaml - - Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, function - (result) { - const ewsId = Office.context.mailbox.item.itemId; - const token = result.value; - const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); - const getMessageUrl = Office.context.mailbox.restUrl + '/v2.0/me/messages/' + restId; - - const xhr = new XMLHttpRequest(); - xhr.open('GET', getMessageUrl); - xhr.setRequestHeader("Authorization", "Bearer " + token); - xhr.onload = function (e) { - console.log(this.response); - } - xhr.send(); + const referenceNumber = (document.getElementById("input-reference") as HTMLInputElement).value; + const mark = (referenceNumber as number) - 1; + const item: Word.NoteItem = footnotes.items[mark]; + console.log(`Note type of footnote ${referenceNumber}: ${item.type}`); + + item.body.load("type"); + await context.sync(); + + console.log(`Body type of note: ${item.body.type}`); }); +Word.Border:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/ids-and-urls.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - console.log("EWS URL: " + Office.context.mailbox.ewsUrl); - const ewsId = Office.context.mailbox.item.itemId; + // Updates border properties (e.g., type, width, color) of the specified + style. - console.log("EWS item ID: " + Office.context.mailbox.item.itemId); + await Word.run(async (context) => { + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update border properties."); + return; + } + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); + await context.sync(); - console.log("REST URL: " + Office.context.mailbox.restUrl); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + const borders: Word.BorderCollection = style.borders; + borders.load("items"); + await context.sync(); - const restId = Office.context.mailbox.convertToRestId(ewsId, - Office.MailboxEnums.RestVersion.v2_0); + borders.outsideBorderType = Word.BorderType.dashed; + borders.outsideBorderWidth = Word.BorderWidth.pt025; + borders.outsideBorderColor = "green"; + console.log("Updated outside borders."); + } + }); +Word.BorderCollection:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - console.log("REST item ID: " + restId); + // Updates border properties (e.g., type, width, color) of the specified + style. - const ewsId2 = Office.context.mailbox.convertToEwsId(restId, - Office.MailboxEnums.RestVersion.v2_0); + await Word.run(async (context) => { + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update border properties."); + return; + } - console.log("EWS ID (from REST ID): " + ewsId2); -'Office.Mailbox#displayAppointmentForm:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-existing-appointment.yaml + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); + await context.sync(); - const itemId = $("#itemId").val(); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + const borders: Word.BorderCollection = style.borders; + borders.load("items"); + await context.sync(); - Office.context.mailbox.displayAppointmentForm(itemId); -'Office.Mailbox#displayAppointmentFormAsync:member(1)': + borders.outsideBorderType = Word.BorderType.dashed; + borders.outsideBorderWidth = Word.BorderWidth.pt025; + borders.outsideBorderColor = "green"; + console.log("Updated outside borders."); + } + }); +Word.BorderCollection#outsideBorderColor:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-existing-appointment.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - const itemId = $("#itemId").val(); + // Updates border properties (e.g., type, width, color) of the specified + style. - // The async version will return error 9049 if the item is not found. + await Word.run(async (context) => { + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update border properties."); + return; + } - // The async version is only available starting with requirement set 1.9. + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); + await context.sync(); + + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + const borders: Word.BorderCollection = style.borders; + borders.load("items"); + await context.sync(); - Office.context.mailbox.displayAppointmentFormAsync(itemId, - function(asyncResult) { - console.log("Result: " + JSON.stringify(asyncResult)); + borders.outsideBorderType = Word.BorderType.dashed; + borders.outsideBorderWidth = Word.BorderWidth.pt025; + borders.outsideBorderColor = "green"; + console.log("Updated outside borders."); + } }); -'Office.Mailbox#displayMessageForm:member(1)': +Word.BorderCollection#outsideBorderType:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-existing-message.yaml - - const itemId = $("#itemId").val(); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - Office.context.mailbox.displayMessageForm(itemId); -'Office.Mailbox#displayMessageFormAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-existing-message.yaml - const itemId = $("#itemId").val(); + // Updates border properties (e.g., type, width, color) of the specified + style. + await Word.run(async (context) => { + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update border properties."); + return; + } - // The async version will return error 9049 if the item is not found. + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); + await context.sync(); - // The async version is only available starting with requirement set 1.9. + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + const borders: Word.BorderCollection = style.borders; + borders.load("items"); + await context.sync(); - Office.context.mailbox.displayMessageFormAsync(itemId, function - (asyncResult) { - console.log("Result: " + JSON.stringify(asyncResult)); + borders.outsideBorderType = Word.BorderType.dashed; + borders.outsideBorderWidth = Word.BorderWidth.pt025; + borders.outsideBorderColor = "green"; + console.log("Updated outside borders."); + } }); -'Office.Mailbox#displayNewAppointmentForm:member(1)': +Word.BorderCollection#outsideBorderWidth:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-new-appointment.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - const start = new Date(); - const end = new Date(); + // Updates border properties (e.g., type, width, color) of the specified + style. - end.setHours(start.getHours() + 1); + await Word.run(async (context) => { + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update border properties."); + return; + } + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); + await context.sync(); - Office.context.mailbox.displayNewAppointmentForm({ - requiredAttendees: ["bob@contoso.com"], - optionalAttendees: ["sam@contoso.com"], - start: start, - end: end, - location: "Home", - subject: "meeting", - resources: ["projector@contoso.com"], - body: "Hello World!" + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + const borders: Word.BorderCollection = style.borders; + borders.load("items"); + await context.sync(); + + borders.outsideBorderType = Word.BorderType.dashed; + borders.outsideBorderWidth = Word.BorderWidth.pt025; + borders.outsideBorderColor = "green"; + console.log("Updated outside borders."); + } }); -'Office.Mailbox#displayNewAppointmentFormAsync:member(1)': +Word.BorderLocation:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-new-appointment.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - const start = new Date(); - const end = new Date(); + // Gets border details about the first table in the document. - end.setHours(start.getHours() + 1); + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const borderLocation = Word.BorderLocation.top; + const border: Word.TableBorder = firstTable.getBorder(borderLocation); + border.load(["type", "color", "width"]); + await context.sync(); + console.log(`Details about the ${borderLocation} border of the first table:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); + }); +Word.BorderType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // The async version is only available starting with requirement set 1.9, - // and provides a callback when the new appointment form has been created. + // Gets border details about the first of the first table in the document. - Office.context.mailbox.displayNewAppointmentFormAsync( - { - requiredAttendees: ["bob@contoso.com"], - optionalAttendees: ["sam@contoso.com"], - start: start, - end: end, - location: "Home", - subject: "meeting", - resources: ["projector@contoso.com"], - body: "Hello World!" - }, - function(asyncResult) { - console.log(JSON.stringify(asyncResult)); - } - ); -'Office.Mailbox#displayNewMessageForm:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-new-message.yaml + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstCell: Word.TableCell = firstTable.getCell(0, 0); + const borderLocation = "Left"; + const border: Word.TableBorder = firstCell.getBorder(borderLocation); + border.load(["type", "color", "width"]); + await context.sync(); - Office.context.mailbox.displayNewMessageForm({ - toRecipients: Office.context.mailbox.item.to, // Copies the To line from current item - ccRecipients: ["sam@contoso.com"], - subject: "Outlook add-ins are cool!", - htmlBody: 'Hello World!
', - attachments: [ - { - type: "file", - name: "image.png", - url: "http://www.cutestpaw.com/wp-content/uploads/2011/11/Cute-Black-Dogs-s.jpg", - isInline: true - } - ] + console.log(`Details about the ${borderLocation} border of the first table's first cell:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); -'Office.Mailbox#displayNewMessageFormAsync:member(1)': +Word.BorderWidth:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-new-message.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // The async version is only available starting with requirement set 1.9, - // and provides a callback when the new message form has been created. + // Updates border properties (e.g., type, width, color) of the specified + style. - Office.context.mailbox.displayNewMessageFormAsync( - { - toRecipients: Office.context.mailbox.item.to, // Copies the To line from current item - ccRecipients: ["sam@contoso.com"], - subject: "Outlook add-ins are cool!", - htmlBody: 'Hello World!
', - attachments: [ - { - type: "file", - name: "image.png", - url: "http://www.cutestpaw.com/wp-content/uploads/2011/11/Cute-Black-Dogs-s.jpg", - isInline: true - } - ] - }, - function(asyncResult) { - console.log(JSON.stringify(asyncResult)); + await Word.run(async (context) => { + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update border properties."); + return; } - ); -'Office.Mailbox#ewsUrl:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/ids-and-urls.yaml - console.log("EWS URL: " + Office.context.mailbox.ewsUrl); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); + await context.sync(); - const ewsId = Office.context.mailbox.item.itemId; + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + const borders: Word.BorderCollection = style.borders; + borders.load("items"); + await context.sync(); - console.log("EWS item ID: " + Office.context.mailbox.item.itemId); + borders.outsideBorderType = Word.BorderType.dashed; + borders.outsideBorderWidth = Word.BorderWidth.pt025; + borders.outsideBorderColor = "green"; + console.log("Updated outside borders."); + } + }); +Word.BreakType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-line-and-page-breaks.yaml - console.log("REST URL: " + Office.context.mailbox.restUrl); + await Word.run(async (context) => { + context.document.body.paragraphs.getFirst().insertBreak(Word.BreakType.page, "After"); - const restId = Office.context.mailbox.convertToRestId(ewsId, - Office.MailboxEnums.RestVersion.v2_0); + await context.sync(); + console.log("success"); + }); +Word.BuiltInStyleName:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-formatted-text.yaml - console.log("REST item ID: " + restId); + await Word.run(async (context) => { + const sentence: Word.Paragraph = context.document.body.insertParagraph( + "To be or not to be", + "End" + ); - const ewsId2 = Office.context.mailbox.convertToEwsId(restId, - Office.MailboxEnums.RestVersion.v2_0); + // Use styleBuiltIn to use an enumeration of existing styles. If your style is custom make sure to use: range.style = "name of your style"; + sentence.styleBuiltIn = Word.BuiltInStyleName.intenseReference; - console.log("EWS ID (from REST ID): " + ewsId2); -'Office.Mailbox#getCallbackTokenAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/basic-rest-cors.yaml - - Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, function - (result) { - const ewsId = Office.context.mailbox.item.itemId; - const token = result.value; - const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); - const getMessageUrl = Office.context.mailbox.restUrl + '/v2.0/me/messages/' + restId; - - const xhr = new XMLHttpRequest(); - xhr.open('GET', getMessageUrl); - xhr.setRequestHeader("Authorization", "Bearer " + token); - xhr.onload = function (e) { - console.log(this.response); - } - xhr.send(); + await context.sync(); }); -'Office.Mailbox#getCallbackTokenAsync:member(2)': +Word.CellPaddingLocation:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/user-callback-token.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - Office.context.mailbox.getCallbackTokenAsync(function (result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Token retrieval failed with message: ${result.error.message}`); - } else { - console.log(result.value); - } + + // Gets cell padding details about the first table in the document. + + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const cellPaddingLocation = Word.CellPaddingLocation.right; + const cellPadding = firstTable.getCellPadding(cellPaddingLocation); + await context.sync(); + + console.log( + `Cell padding details about the ${cellPaddingLocation} border of the first table: ${cellPadding.value} points` + ); }); -'Office.Mailbox#getUserIdentityTokenAsync:member(1)': +Word.ChangeTrackingMode:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/user-identity-token.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-change-tracking.yaml - Office.context.mailbox.getUserIdentityTokenAsync(function (result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Token retrieval failed with message: ${result.error.message}`); - } else { - console.log(result.value); - } + + // Gets the current change tracking mode. + + await Word.run(async (context) => { + const document: Word.Document = context.document; + document.load("changeTrackingMode"); + await context.sync(); + + if (document.changeTrackingMode === Word.ChangeTrackingMode.trackMineOnly) { + console.log("Only my changes are being tracked."); + } else if (document.changeTrackingMode === Word.ChangeTrackingMode.trackAll) { + console.log("Everyone's changes are being tracked."); + } else { + console.log("No changes are being tracked."); + } }); -'Office.Mailbox#makeEwsRequestAsync:member(1)': +Word.ChangeTrackingState:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-attendee.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/get-change-tracking-states.yaml - const ewsId = Office.context.mailbox.item.itemId; - const request = ` - - - - - AllProperties - - - - - - - `; + // Logs the current change tracking states of the content controls. - Office.context.mailbox.makeEwsRequestAsync(request, (result) => { - if (result.status === Office.AsyncResultStatus.Failed) { - console.error(result.error.message); - return; - } + await Word.run(async (context) => { + let trackAddedArray: Word.ChangeTrackingState[] = [Word.ChangeTrackingState.added]; + let trackDeletedArray: Word.ChangeTrackingState[] = [Word.ChangeTrackingState.deleted]; + let trackNormalArray: Word.ChangeTrackingState[] = [Word.ChangeTrackingState.normal]; - console.log(getUID(result.value)); + let addedContentControls = context.document.body.getContentControls().getByChangeTrackingStates(trackAddedArray); + let deletedContentControls = context.document.body + .getContentControls() + .getByChangeTrackingStates(trackDeletedArray); + let normalContentControls = context.document.body.getContentControls().getByChangeTrackingStates(trackNormalArray); + + addedContentControls.load(); + deletedContentControls.load(); + normalContentControls.load(); + await context.sync(); + + console.log(`Number of content controls in Added state: ${addedContentControls.items.length}`); + console.log(`Number of content controls in Deleted state: ${deletedContentControls.items.length}`); + console.log(`Number of content controls in Normal state: ${normalContentControls.items.length}`); }); +Word.ChangeTrackingVersion:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/send-message-using-make-ews-request-async.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-change-tracking.yaml - const request = ''+ - ' '+ - ' '+ - ' '+ - ' '+ - ' '+ - ' '+ - ' Hello, Outlook!'+ - ' This message was sent from a ScriptLab code sample, used from ' + Office.context.mailbox.diagnostics.hostName + ', version ' + Office.context.mailbox.diagnostics.hostVersion + '!'+ - ' '+ - ' ' + Office.context.mailbox.userProfile.emailAddress + ''+ - ' '+ - ' '+ - ' '+ - ' '+ - ' '+ - ''; - Office.context.mailbox.makeEwsRequestAsync(request, function (result) { - console.log(result); + // Gets the reviewed text. + + await Word.run(async (context) => { + const range: Word.Range = context.document.getSelection(); + const before = range.getReviewedText(Word.ChangeTrackingVersion.original); + const after = range.getReviewedText(Word.ChangeTrackingVersion.current); + + await context.sync(); + + console.log("Reviewed text (before):", before.value, "Reviewed text (after):", after.value); }); -'Office.Mailbox#masterCategories:member': +Word.CheckboxContentControl:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml - Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - console.log("Master categories:"); - console.log(JSON.stringify(categories)); - } else { - console.log("There are no categories in the master list."); - } - } else { - console.error(asyncResult.error); + + // Toggles the isChecked property on all checkbox content controls. + + await Word.run(async (context) => { + let contentControls = context.document.getContentControls({ + types: [Word.ContentControlType.checkBox] + }); + contentControls.load("items"); + + await context.sync(); + + const length = contentControls.items.length; + console.log(`Number of checkbox content controls: ${length}`); + + if (length <= 0) { + return; } - }); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml - const masterCategoriesToAdd = [ - { - displayName: "TestCategory", - color: Office.MailboxEnums.CategoryColor.Preset0 + const checkboxContentControls = []; + for (let i = 0; i < length; i++) { + let contentControl = contentControls.items[i]; + contentControl.load("id,checkboxContentControl/isChecked"); + checkboxContentControls.push(contentControl); } - ]; + await context.sync(); - Office.context.mailbox.masterCategories.addAsync(masterCategoriesToAdd, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Successfully added categories to master list"); - } else { - console.log("masterCategories.addAsync call failed with error: " + asyncResult.error.message); + console.log("isChecked state before:"); + const updatedCheckboxContentControls = []; + for (let i = 0; i < checkboxContentControls.length; i++) { + const currentCheckboxContentControl = checkboxContentControls[i]; + const isCheckedBefore = currentCheckboxContentControl.checkboxContentControl.isChecked; + console.log(`id: ${currentCheckboxContentControl.id} ... isChecked: ${isCheckedBefore}`); + + currentCheckboxContentControl.checkboxContentControl.isChecked = !isCheckedBefore; + currentCheckboxContentControl.load("id,checkboxContentControl/isChecked"); + updatedCheckboxContentControls.push(currentCheckboxContentControl); + } + + await context.sync(); + + console.log("isChecked state after:"); + for (let i = 0; i < updatedCheckboxContentControls.length; i++) { + const currentCheckboxContentControl = updatedCheckboxContentControls[i]; + console.log( + `id: ${currentCheckboxContentControl.id} ... isChecked: ${currentCheckboxContentControl.checkboxContentControl.isChecked}` + ); } }); +Word.CloseBehavior:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/save-close.yaml - const masterCategoriesToRemove = ["TestCategory"]; + // Closes the document after saving. - Office.context.mailbox.masterCategories.removeAsync(masterCategoriesToRemove, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Successfully removed categories from master list"); - } else { - console.log("masterCategories.removeAsync call failed with error: " + asyncResult.error.message); - } + await Word.run(async (context) => { + context.document.close(Word.CloseBehavior.save); }); -'Office.Mailbox#restUrl:member': +Word.ComboBoxContentControl:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/basic-rest-cors.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml - Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, function - (result) { - const ewsId = Office.context.mailbox.item.itemId; - const token = result.value; - const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); - const getMessageUrl = Office.context.mailbox.restUrl + '/v2.0/me/messages/' + restId; - - const xhr = new XMLHttpRequest(); - xhr.open('GET', getMessageUrl); - xhr.setRequestHeader("Authorization", "Bearer " + token); - xhr.onload = function (e) { - console.log(this.response); - } - xhr.send(); + + // Places a combo box content control at the end of the selection. + + await Word.run(async (context) => { + let selection = context.document.getSelection(); + selection.getRange(Word.RangeLocation.end).insertContentControl(Word.ContentControlType.comboBox); + await context.sync(); + + console.log("Combo box content control inserted at the end of the selection."); }); +Word.ComboBoxContentControl#addListItem:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/ids-and-urls.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml - console.log("EWS URL: " + Office.context.mailbox.ewsUrl); - const ewsId = Office.context.mailbox.item.itemId; + // Adds the provided list item to the first combo box content control in the + selection. - console.log("EWS item ID: " + Office.context.mailbox.item.itemId); + await Word.run(async (context) => { + const listItemText = (document.getElementById("item-to-add") as HTMLInputElement).value.trim(); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.comboBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,comboBoxContentControl"); + await context.sync(); + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,comboBoxContentControl"); + await context.sync(); - console.log("REST URL: " + Office.context.mailbox.restUrl); + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.comboBox) { + console.warn("No combo box content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } - const restId = Office.context.mailbox.convertToRestId(ewsId, - Office.MailboxEnums.RestVersion.v2_0); + selectedContentControl.comboBoxContentControl.addListItem(listItemText); + await context.sync(); - console.log("REST item ID: " + restId); + console.log(`List item added to control with ID ${selectedContentControl.id}: ${listItemText}`); + }); +Word.ComboBoxContentControl#deleteAllListItems:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml - const ewsId2 = Office.context.mailbox.convertToEwsId(restId, - Office.MailboxEnums.RestVersion.v2_0); + // Deletes the list items from first combo box content control found in the + selection. - console.log("EWS ID (from REST ID): " + ewsId2); -'Office.MailboxEnums.AppointmentSensitivityType:enum': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/calendar-properties-apis.yaml + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.comboBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,comboBoxContentControl"); + await context.sync(); - Office.context.mailbox.item.sensitivity.setAsync( - Office.MailboxEnums.AppointmentSensitivityType.Confidential, - function callback(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Failed to set appointment sensitivity: " + JSON.stringify(asyncResult.error)); + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,comboBoxContentControl"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.comboBox) { + console.warn("No combo box content control is currently selected."); + return; } else { - console.log("Successfully set appointment sensitivity."); + selectedContentControl = parentContentControl; } } - ); -'Office.MailboxEnums.AttachmentContentFormat:enum': + + console.log(`About to delete the list from the combo box content control with ID ${selectedContentControl.id}`); + selectedContentControl.comboBoxContentControl.deleteAllListItems(); + await context.sync(); + + console.log("Deleted the list from the combo box content control."); + }); +Word.ComboBoxContentControl#listItems:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachment-content.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml - function handleAttachmentsCallback(result) { - // Identifies whether the attachment is a Base64-encoded string, .eml file, .icalendar file, or a URL. - switch (result.value.format) { - case Office.MailboxEnums.AttachmentContentFormat.Base64: - // Handle file attachment. - console.log("Attachment is a Base64-encoded string."); - break; - case Office.MailboxEnums.AttachmentContentFormat.Eml: - // Handle email item attachment. - console.log("Attachment is a message."); - break; - case Office.MailboxEnums.AttachmentContentFormat.ICalendar: - // Handle .icalender attachment. - console.log("Attachment is a calendar item."); - break; - case Office.MailboxEnums.AttachmentContentFormat.Url: - // Handle cloud attachment. - console.log("Attachment is a cloud attachment."); - break; - default: - // Handle attachment formats that aren't supported. + + // Deletes the provided list item from the first combo box content control + in the selection. + + await Word.run(async (context) => { + const listItemText = (document.getElementById("item-to-delete") as HTMLInputElement).value.trim(); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.comboBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,comboBoxContentControl"); + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,comboBoxContentControl"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.comboBox) { + console.warn("No combo box content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } } - console.log(result.value.content); - } -'Office.MailboxEnums.AttachmentType:enum': + let selectedComboBox: Word.ComboBoxContentControl = selectedContentControl.comboBoxContentControl; + selectedComboBox.listItems.load("items/*"); + await context.sync(); + + let listItems: Word.ContentControlListItemCollection = selectedContentControl.comboBoxContentControl.listItems; + let itemToDelete: Word.ContentControlListItem = listItems.items.find((item) => item.displayText === listItemText); + if (!itemToDelete) { + console.warn(`List item doesn't exist in control with ID ${selectedContentControl.id}: ${listItemText}`); + return; + } + + itemToDelete.delete(); + await context.sync(); + + console.log(`List item deleted from control with ID ${selectedContentControl.id}: ${listItemText}`); + }); +Word.Comment:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - Office.context.mailbox.item.getAttachmentsAsync(function (result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(result.error.message); - } else { - if (result.value.length > 0) { - for (let i = 0; i < result.value.length; i++) { - const attachment = result.value[i]; - console.log("ID: " + attachment.id + "\n" + - "Name: " + attachment.name + "\n" + - "Size: " + attachment.size + "\n" + - "isInline: " + attachment.isInline); - switch (attachment.attachmentType) { - case Office.MailboxEnums.AttachmentType.Cloud: - console.log("Attachment type: Attachment is stored in a cloud location."); - break; - case Office.MailboxEnums.AttachmentType.File: - console.log("Attachment type: Attachment is a file."); - break; - case Office.MailboxEnums.AttachmentType.Item: - console.log("Attachment type: Attachment is an Exchange item."); - break; - } - } - } - else { - console.log("No attachments on this message."); - } - } + + // Sets a comment on the selected content. + + await Word.run(async (context) => { + const text = (document.getElementById("comment-text") as HTMLInputElement).value; + const comment: Word.Comment = context.document.getSelection().insertComment(text); + + // Load object to log in the console. + comment.load(); + await context.sync(); + + console.log("Comment inserted:", comment); }); -'Office.MailboxEnums.CategoryColor:enum': +Word.Comment#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - const masterCategoriesToAdd = [ - { - displayName: "TestCategory", - color: Office.MailboxEnums.CategoryColor.Preset0 - } - ]; + // Deletes the first comment in the selected content. - Office.context.mailbox.masterCategories.addAsync(masterCategoriesToAdd, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Successfully added categories to master list"); - } else { - console.log("masterCategories.addAsync call failed with error: " + asyncResult.error.message); + await Word.run(async (context) => { + const comment: Word.Comment = context.document.getSelection().getComments().getFirstOrNullObject(); + comment.delete(); + await context.sync(); + + if (comment.isNullObject) { + console.warn("No comments in the selection, so nothing to delete."); + return; } + + console.log("Comment deleted."); }); -'Office.MailboxEnums.ComposeType:enum': +Word.Comment#getRange:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - // Get the compose type of the current message. - Office.context.mailbox.item.getComposeTypeAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log( - "getComposeTypeAsync succeeded with composeType: " + - asyncResult.value.composeType + - " and coercionType: " + - asyncResult.value.coercionType - ); - } else { - console.error(asyncResult.error); + // Gets the range of the first comment in the selected content. + + await Word.run(async (context) => { + const comment: Word.Comment = context.document.getSelection().getComments().getFirstOrNullObject(); + comment.load("contentRange"); + const range: Word.Range = comment.getRange(); + range.load("text"); + await context.sync(); + + if (comment.isNullObject) { + console.warn("No comments in the selection, so no range to get."); + return; } + + console.log(`Comment location: ${range.text}`); + const contentRange: Word.CommentContentRange = comment.contentRange; + console.log("Comment content range:", contentRange); }); -'Office.MailboxEnums.Days:enum': +Word.Comment#reply:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml - - // Important: Can only set the recurrence pattern of an appointment series. + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - const currentDate = new Date(); + // Replies to the first active comment in the selected content. - let seriesTimeObject: Office.SeriesTime; + await Word.run(async (context) => { + const text = (document.getElementById("reply-text") as HTMLInputElement).value; + const comments: Word.CommentCollection = context.document.getSelection().getComments(); + comments.load("items"); + await context.sync(); - // Set series start date to tomorrow. + const firstActiveComment: Word.Comment = comments.items.find((item) => item.resolved !== true); + if (firstActiveComment) { + const reply: Word.CommentReply = firstActiveComment.reply(text); + console.log("Reply added."); + } else { + console.warn("No active comment was found in the selection, so couldn't reply."); + } + }); +Word.Comment#content:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - seriesTimeObject.setStartDate(currentDate.getFullYear(), - currentDate.getMonth(), currentDate.getDay() + 1); - // Set series end date to one year from now. + // Edits the first active comment in the selected content. - seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, - currentDate.getMonth() + 1, currentDate.getDay()); + await Word.run(async (context) => { + const text = (document.getElementById("edit-comment-text") as HTMLInputElement).value; + const comments: Word.CommentCollection = context.document.getSelection().getComments(); + comments.load("items"); + await context.sync(); - // Set start time to 1:30 PM. + const firstActiveComment: Word.Comment = comments.items.find((item) => item.resolved !== true); + if (!firstActiveComment) { + console.warn("No active comment was found in the selection, so couldn't edit."); + return; + } - seriesTimeObject.setStartTime(13, 30); + firstActiveComment.content = text; - // Set duration to 30 minutes. + // Load object to log in the console. + firstActiveComment.load(); + await context.sync(); - seriesTimeObject.setDuration(30); + console.log("Comment content changed:", firstActiveComment); + }); +Word.Comment#contentRange:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - const pattern: Office.Recurrence = { - seriesTime: seriesTimeObject, - recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, - recurrenceProperties: { - interval: 1, - dayOfWeek: Office.MailboxEnums.Days.Tue, - weekNumber: Office.MailboxEnums.WeekNumber.Second, - month: Office.MailboxEnums.Month.Sep - }, - recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } - }; + // Gets the range of the first comment in the selected content. + await Word.run(async (context) => { + const comment: Word.Comment = context.document.getSelection().getComments().getFirstOrNullObject(); + comment.load("contentRange"); + const range: Word.Range = comment.getRange(); + range.load("text"); + await context.sync(); - Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { - if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); + if (comment.isNullObject) { + console.warn("No comments in the selection, so no range to get."); return; } - console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); + + console.log(`Comment location: ${range.text}`); + const contentRange: Word.CommentContentRange = comment.contentRange; + console.log("Comment content range:", contentRange); }); -'Office.MailboxEnums.DelegatePermissions:enum': +Word.Comment#replies:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - if (!Office.context.mailbox.item.getSharedPropertiesAsync) { - console.error("Try this sample on an appointment from a shared folder."); - return; - } + // Gets the replies to the first comment in the selected content. - Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, - function(result) { - if (result.status === Office.AsyncResultStatus.Succeeded && result.value !== "") { - Office.context.mailbox.item.getSharedPropertiesAsync( - { - // Pass auth token along. - asyncContext: result.value - }, - function(result2) { - let sharedProperties = result2.value; - let delegatePermissions = sharedProperties.delegatePermissions; - - // Determine if user has the appropriate permission to do the operation. - if ((delegatePermissions & Office.MailboxEnums.DelegatePermissions.Read) != 0) { - const ewsId = Office.context.mailbox.item.itemId; - const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); - let rest_url = - sharedProperties.targetRestUrl + "/v2.0/users/" + sharedProperties.targetMailbox + "/events/" + restId; - - $.ajax({ - url: rest_url, - dataType: "json", - headers: { Authorization: "Bearer " + result2.asyncContext } - }) - .done(function(response) { - console.log(response); - }) - .fail(function(error) { - console.error(error); - }); - } - } - ); + await Word.run(async (context) => { + const comment: Word.Comment = context.document.getSelection().getComments().getFirstOrNullObject(); + comment.load("replies"); + await context.sync(); + + if (comment.isNullObject) { + console.warn("No comments in the selection, so no replies to get."); + return; } + + const replies: Word.CommentReplyCollection = comment.replies; + console.log("Replies to the first comment:", replies); }); -'Office.MailboxEnums.EntityType:enum': +Word.Comment#resolved:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/basic-entities.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml + + + // Toggles Resolved status of the first comment in the selected content. + + await Word.run(async (context) => { + const comment: Word.Comment = context.document + .getSelection() + .getComments() + .getFirstOrNullObject(); + comment.load("resolved"); + await context.sync(); + + if (comment.isNullObject) { + console.warn("No comments in the selection, so nothing to toggle."); + return; + } + + // Toggle resolved status. + // If the comment is active, set as resolved. + // If it's resolved, set resolved to false. + const resolvedBefore = comment.resolved; + console.log(`Comment Resolved status (before): ${resolvedBefore}`); + comment.resolved = !resolvedBefore; + comment.load("resolved"); + await context.sync(); - console.log(Office.context.mailbox.item.getEntitiesByType(Office.MailboxEnums.EntityType.Address)); -'Office.MailboxEnums.ItemNotificationMessageType:enum': + console.log(`Comment Resolved status (after): ${comment.resolved}`); + }); +Word.CommentChangeType:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - const id = $("#notificationId").val(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.ErrorMessage, - message: "Error notification message with id = " + id - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); -'Office.MailboxEnums.ItemType:enum': + // Registers event handlers. + + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.track(); + await context.sync(); + + eventContexts[0] = body.onCommentAdded.add(onEventHandler); + eventContexts[1] = body.onCommentChanged.add(onChangedHandler); + eventContexts[2] = body.onCommentDeleted.add(onEventHandler); + eventContexts[3] = body.onCommentDeselected.add(onEventHandler); + eventContexts[4] = body.onCommentSelected.add(onEventHandler); + await context.sync(); + + console.log("Event handlers registered."); + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-type.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - const itemType = Office.context.mailbox.item.itemType; - switch (itemType) { - case Office.MailboxEnums.ItemType.Appointment: - console.log(`Current item is an ${itemType}.`); - break; - case Office.MailboxEnums.ItemType.Message: - console.log(`Current item is a ${itemType}. A message could be an email, meeting request, meeting response, or meeting cancellation.`); - break; + async function onChangedHandler(event: Word.CommentEventArgs) { + await Word.run(async (context) => { + console.log( + `${event.type} event detected. ${event.changeType} change made. Event source: ${event.source}. Comment info:`, event.commentDetails + ); + }); } -'Office.MailboxEnums.LocationType:enum': +Word.CommentCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-add-remove-enhancedlocation-appointment.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - const locations = [ - { - id: "Contoso", - type: Office.MailboxEnums.LocationType.Custom - }, - { - id: "room500@test.com", - type: Office.MailboxEnums.LocationType.Room - } - ]; - Office.context.mailbox.item.enhancedLocation.addAsync(locations, (result) => - { - if (result.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully added locations ${JSON.stringify(locations)}`); + // Replies to the first active comment in the selected content. + + await Word.run(async (context) => { + const text = (document.getElementById("reply-text") as HTMLInputElement).value; + const comments: Word.CommentCollection = context.document.getSelection().getComments(); + comments.load("items"); + await context.sync(); + + const firstActiveComment: Word.Comment = comments.items.find((item) => item.resolved !== true); + if (firstActiveComment) { + const reply: Word.CommentReply = firstActiveComment.reply(text); + console.log("Reply added."); } else { - console.error(`Failed to add locations. Error message: ${result.error.message}`); + console.warn("No active comment was found in the selection, so couldn't reply."); } }); -'Office.MailboxEnums.Month:enum': +Word.CommentCollection#getFirstOrNullObject:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml - - // Important: Can only set the recurrence pattern of an appointment series. - - - const currentDate = new Date(); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - let seriesTimeObject: Office.SeriesTime; - // Set series start date to tomorrow. + // Gets the range of the first comment in the selected content. - seriesTimeObject.setStartDate(currentDate.getFullYear(), - currentDate.getMonth(), currentDate.getDay() + 1); + await Word.run(async (context) => { + const comment: Word.Comment = context.document.getSelection().getComments().getFirstOrNullObject(); + comment.load("contentRange"); + const range: Word.Range = comment.getRange(); + range.load("text"); + await context.sync(); - // Set series end date to one year from now. + if (comment.isNullObject) { + console.warn("No comments in the selection, so no range to get."); + return; + } - seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, - currentDate.getMonth() + 1, currentDate.getDay()); + console.log(`Comment location: ${range.text}`); + const contentRange: Word.CommentContentRange = comment.contentRange; + console.log("Comment content range:", contentRange); + }); +Word.CommentCollection#items:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - // Set start time to 1:30 PM. - seriesTimeObject.setStartTime(13, 30); + // Replies to the first active comment in the selected content. - // Set duration to 30 minutes. + await Word.run(async (context) => { + const text = (document.getElementById("reply-text") as HTMLInputElement).value; + const comments: Word.CommentCollection = context.document.getSelection().getComments(); + comments.load("items"); + await context.sync(); - seriesTimeObject.setDuration(30); + const firstActiveComment: Word.Comment = comments.items.find((item) => item.resolved !== true); + if (firstActiveComment) { + const reply: Word.CommentReply = firstActiveComment.reply(text); + console.log("Reply added."); + } else { + console.warn("No active comment was found in the selection, so couldn't reply."); + } + }); +Word.CommentContentRange:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - const pattern: Office.Recurrence = { - seriesTime: seriesTimeObject, - recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, - recurrenceProperties: { - interval: 1, - dayOfWeek: Office.MailboxEnums.Days.Tue, - weekNumber: Office.MailboxEnums.WeekNumber.Second, - month: Office.MailboxEnums.Month.Sep - }, - recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } - }; + // Gets the range of the first comment in the selected content. + await Word.run(async (context) => { + const comment: Word.Comment = context.document.getSelection().getComments().getFirstOrNullObject(); + comment.load("contentRange"); + const range: Word.Range = comment.getRange(); + range.load("text"); + await context.sync(); - Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { - if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); + if (comment.isNullObject) { + console.warn("No comments in the selection, so no range to get."); return; } - console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); + + console.log(`Comment location: ${range.text}`); + const contentRange: Word.CommentContentRange = comment.contentRange; + console.log("Comment content range:", contentRange); }); -'Office.MailboxEnums.OWAView:enum': +Word.CommentDetail:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-diagnostic-information.yaml - - // This function gets a mailbox's diagnostic information, such as Outlook - client and version, and logs it to the console. + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - const diagnostics = Office.context.mailbox.diagnostics; - console.log(`Client application: ${diagnostics.hostName}`); + // Registers event handlers. - console.log(`Client version: ${diagnostics.hostVersion}`); + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.track(); + await context.sync(); + eventContexts[0] = body.onCommentAdded.add(onEventHandler); + eventContexts[1] = body.onCommentChanged.add(onChangedHandler); + eventContexts[2] = body.onCommentDeleted.add(onEventHandler); + eventContexts[3] = body.onCommentDeselected.add(onEventHandler); + eventContexts[4] = body.onCommentSelected.add(onEventHandler); + await context.sync(); - switch (diagnostics.OWAView) { - case undefined: - console.log("Current view (Outlook on the web only): Not applicable. An Outlook desktop client is in use."); - break; - case Office.MailboxEnums.OWAView.OneColumnNarrow: - console.log("Current view (Outlook on the web only): Viewed from an older generation mobile phone"); - break; - case Office.MailboxEnums.OWAView.OneColumn: - console.log("Current view (Outlook on the web only): Viewed from a newer generation mobile phone"); - break; - case Office.MailboxEnums.OWAView.TwoColumns: - console.log("Current view (Outlook on the web only): Viewed from a tablet"); - break; - case Office.MailboxEnums.OWAView.ThreeColumns: - console.log("Current view (Outlook on the web only): Viewed from a desktop computer"); - break; - } -'Office.MailboxEnums.RecipientType:enum': + console.log("Event handlers registered."); + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-to-message-read.yaml - - const msgTo = Office.context.mailbox.item.to; + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - const distributionLists = []; - - const externalRecipients = []; - - const internalRecipients = []; - - const otherRecipients = []; - for (let i = 0; i < msgTo.length; i++) { - switch (msgTo[i].recipientType) { - case Office.MailboxEnums.RecipientType.DistributionList: - distributionLists.push(msgTo[i]); - break; - case Office.MailboxEnums.RecipientType.ExternalUser: - externalRecipients.push(msgTo[i]); - break; - case Office.MailboxEnums.RecipientType.User: - internalRecipients.push(msgTo[i]); - break; - case Office.MailboxEnums.RecipientType.Other: - otherRecipients.push(msgTo[i]); - } + async function onEventHandler(event: Word.CommentEventArgs) { + // Handler for all events except onCommentChanged. + await Word.run(async (context) => { + console.log(`${event.type} event detected. Event source: ${event.source}. Comment info:`, event.commentDetails); + }); } +Word.CommentEventArgs:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - if (distributionLists.length > 0) { - console.log("Distribution Lists:"); - distributionLists.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); - } - + // Registers event handlers. - if (externalRecipients.length > 0) { - console.log("External Recipients:"); - externalRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); - } + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.track(); + await context.sync(); + eventContexts[0] = body.onCommentAdded.add(onEventHandler); + eventContexts[1] = body.onCommentChanged.add(onChangedHandler); + eventContexts[2] = body.onCommentDeleted.add(onEventHandler); + eventContexts[3] = body.onCommentDeselected.add(onEventHandler); + eventContexts[4] = body.onCommentSelected.add(onEventHandler); + await context.sync(); - if (internalRecipients.length > 0) { - console.log("Internal Recipients:"); - internalRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); - } + console.log("Event handlers registered."); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - if (otherRecipients.length > 0) { - console.log("Other Recipients:"); - otherRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); + async function onChangedHandler(event: Word.CommentEventArgs) { + await Word.run(async (context) => { + console.log( + `${event.type} event detected. ${event.changeType} change made. Event source: ${event.source}. Comment info:`, event.commentDetails + ); + }); } -'Office.MailboxEnums.RecurrenceTimeZone:enum': +Word.CommentReply:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - // Important: Can only set the recurrence pattern of an appointment series. + // Replies to the first active comment in the selected content. - const currentDate = new Date(); + await Word.run(async (context) => { + const text = (document.getElementById("reply-text") as HTMLInputElement).value; + const comments: Word.CommentCollection = context.document.getSelection().getComments(); + comments.load("items"); + await context.sync(); - let seriesTimeObject: Office.SeriesTime; + const firstActiveComment: Word.Comment = comments.items.find((item) => item.resolved !== true); + if (firstActiveComment) { + const reply: Word.CommentReply = firstActiveComment.reply(text); + console.log("Reply added."); + } else { + console.warn("No active comment was found in the selection, so couldn't reply."); + } + }); +Word.CommentReplyCollection:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - // Set series start date to tomorrow. - seriesTimeObject.setStartDate(currentDate.getFullYear(), - currentDate.getMonth(), currentDate.getDay() + 1); + // Gets the replies to the first comment in the selected content. + + await Word.run(async (context) => { + const comment: Word.Comment = context.document.getSelection().getComments().getFirstOrNullObject(); + comment.load("replies"); + await context.sync(); - // Set series end date to one year from now. + if (comment.isNullObject) { + console.warn("No comments in the selection, so no replies to get."); + return; + } - seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, - currentDate.getMonth() + 1, currentDate.getDay()); + const replies: Word.CommentReplyCollection = comment.replies; + console.log("Replies to the first comment:", replies); + }); +Word.CompareTarget:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/compare-documents.yaml - // Set start time to 1:30 PM. - seriesTimeObject.setStartTime(13, 30); + // Compares the current document with a specified external document. - // Set duration to 30 minutes. + await Word.run(async (context) => { + // Absolute path of an online or local document. + const filePath = (document.getElementById("filePath") as HTMLInputElement).value; + // Options that configure the compare operation. + const options: Word.DocumentCompareOptions = { + compareTarget: Word.CompareTarget.compareTargetCurrent, + detectFormatChanges: false + // Other options you choose... + }; + context.document.compare(filePath, options); - seriesTimeObject.setDuration(30); + await context.sync(); + console.log("Differences shown in the current document."); + }); +Word.ContentControl#delete:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml - const pattern: Office.Recurrence = { - seriesTime: seriesTimeObject, - recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, - recurrenceProperties: { - interval: 1, - dayOfWeek: Office.MailboxEnums.Days.Tue, - weekNumber: Office.MailboxEnums.WeekNumber.Second, - month: Office.MailboxEnums.Month.Sep - }, - recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } - }; + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls.getByTag("forTesting"); + contentControls.load("items"); + await context.sync(); - Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { - if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); - return; + if (contentControls.items.length === 0) { + console.log("There are no content controls in this document."); + } else { + console.log("Control to be deleted:", contentControls.items[0]); + contentControls.items[0].delete(false); + await context.sync(); } - console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); }); -'Office.MailboxEnums.RecurrenceType:enum': +Word.ContentControl#resetState:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/insert-and-change-content-controls.yaml - // Important: Can only set the recurrence pattern of an appointment series. + // Resets the state of the first content control. - const currentDate = new Date(); + await Word.run(async (context) => { + let firstContentControl = context.document.contentControls.getFirstOrNullObject(); + await context.sync(); - let seriesTimeObject: Office.SeriesTime; + if (firstContentControl.isNullObject) { + console.warn("There are no content controls in this document."); + return; + } - // Set series start date to tomorrow. + firstContentControl.resetState(); + firstContentControl.load("id"); + await context.sync(); - seriesTimeObject.setStartDate(currentDate.getFullYear(), - currentDate.getMonth(), currentDate.getDay() + 1); + console.log(`Reset state of first content control with ID: ${firstContentControl.id}`); + }); +Word.ContentControl#set:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-content-controls.yaml - // Set series end date to one year from now. - seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, - currentDate.getMonth() + 1, currentDate.getDay()); + // Adds title and colors to odd and even content controls and changes their + appearance. - // Set start time to 1:30 PM. + await Word.run(async (context) => { + // Get the complete sentence (as range) associated with the insertion point. + let evenContentControls = context.document.contentControls.getByTag("even"); + let oddContentControls = context.document.contentControls.getByTag("odd"); + evenContentControls.load("length"); + oddContentControls.load("length"); - seriesTimeObject.setStartTime(13, 30); + await context.sync(); - // Set duration to 30 minutes. + for (let i = 0; i < evenContentControls.items.length; i++) { + // Change a few properties and append a paragraph. + evenContentControls.items[i].set({ + color: "red", + title: "Odd ContentControl #" + (i + 1), + appearance: Word.ContentControlAppearance.tags + }); + evenContentControls.items[i].insertParagraph("This is an odd content control", "End"); + } - seriesTimeObject.setDuration(30); + for (let j = 0; j < oddContentControls.items.length; j++) { + // Change a few properties and append a paragraph. + oddContentControls.items[j].set({ + color: "green", + title: "Even ContentControl #" + (j + 1), + appearance: "Tags" + }); + oddContentControls.items[j].insertHtml("This is an even content control", "End"); + } + + await context.sync(); + }); +Word.ContentControl#setState:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/insert-and-change-content-controls.yaml - const pattern: Office.Recurrence = { - seriesTime: seriesTimeObject, - recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, - recurrenceProperties: { - interval: 1, - dayOfWeek: Office.MailboxEnums.Days.Tue, - weekNumber: Office.MailboxEnums.WeekNumber.Second, - month: Office.MailboxEnums.Month.Sep - }, - recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } - }; + // Sets the state of the first content control. + await Word.run(async (context) => { + const state = ((document.getElementById("state-to-set") as HTMLSelectElement) + .value as unknown) as Word.ContentControlState; + let firstContentControl = context.document.contentControls.getFirstOrNullObject(); + await context.sync(); - Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { - if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); + if (firstContentControl.isNullObject) { + console.warn("There are no content controls in this document."); return; } - console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); + + firstContentControl.setState(state); + firstContentControl.load("id"); + await context.sync(); + + console.log(`Set state of first content control with ID ${firstContentControl.id} to ${state}.`); }); -'Office.MailboxEnums.ResponseType:enum': +Word.ContentControl#checkboxContentControl:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-all-attendees.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml - function organizeByResponse(attendees) { - const accepted = []; - const declined = []; - const noResponse = []; - const tentative = []; - attendees.forEach(attendee => { - switch (attendee.appointmentResponse) { - case Office.MailboxEnums.ResponseType.Accepted: - accepted.push(attendee); - break; - case Office.MailboxEnums.ResponseType.Declined: - declined.push(attendee); - break; - case Office.MailboxEnums.ResponseType.None: - noResponse.push(attendee); - break; - case Office.MailboxEnums.ResponseType.Tentative: - tentative.push(attendee); - break; - case Office.MailboxEnums.ResponseType.Organizer: - console.log(`Organizer: ${attendee.displayName}, ${attendee.emailAddress}`); - break; - } - }); - // List attendees by their response. - console.log("Accepted: "); - printAttendees(accepted); - console.log("Declined: "); - printAttendees(declined); - console.log("Tentative: "); - printAttendees(tentative); - console.log("No response: "); - printAttendees(noResponse); - } -'Office.MailboxEnums.RestVersion:enum': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/basic-rest-cors.yaml - - Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, function - (result) { - const ewsId = Office.context.mailbox.item.itemId; - const token = result.value; - const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); - const getMessageUrl = Office.context.mailbox.restUrl + '/v2.0/me/messages/' + restId; - - const xhr = new XMLHttpRequest(); - xhr.open('GET', getMessageUrl); - xhr.setRequestHeader("Authorization", "Bearer " + token); - xhr.onload = function (e) { - console.log(this.response); + // Toggles the isChecked property of the first checkbox content control + found in the selection. + + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.checkBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,checkboxContentControl/isChecked"); + + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,checkboxContentControl/isChecked"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.checkBox) { + console.warn("No checkbox content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; } - xhr.send(); + } + + const isCheckedBefore = selectedContentControl.checkboxContentControl.isChecked; + console.log("isChecked state before:", `id: ${selectedContentControl.id} ... isChecked: ${isCheckedBefore}`); + selectedContentControl.checkboxContentControl.isChecked = !isCheckedBefore; + selectedContentControl.load("id,checkboxContentControl/isChecked"); + await context.sync(); + + console.log( + "isChecked state after:", + `id: ${selectedContentControl.id} ... isChecked: ${selectedContentControl.checkboxContentControl.isChecked}` + ); }); -'Office.MailboxEnums.SourceProperty:enum': +Word.ContentControl#comboBoxContentControl:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/get-selected-data.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml - Office.context.mailbox.item.getSelectedDataAsync(Office.CoercionType.Text, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const text = asyncResult.value.data; - const prop = asyncResult.value.sourceProperty; - console.log("Selected text in " + prop + ": " + text); - } else { - console.error(asyncResult.error); + + // Adds the provided list item to the first combo box content control in the + selection. + + await Word.run(async (context) => { + const listItemText = (document.getElementById("item-to-add") as HTMLInputElement).value.trim(); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.comboBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,comboBoxContentControl"); + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,comboBoxContentControl"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.comboBox) { + console.warn("No combo box content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } } + + selectedContentControl.comboBoxContentControl.addListItem(listItemText); + await context.sync(); + + console.log(`List item added to control with ID ${selectedContentControl.id}: ${listItemText}`); }); -'Office.MailboxEnums.WeekNumber:enum': +Word.ContentControl#dropDownListContentControl:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml - // Important: Can only set the recurrence pattern of an appointment series. + // Adds the provided list item to the first dropdown list content control in + the selection. - const currentDate = new Date(); + await Word.run(async (context) => { + const listItemText = (document.getElementById("item-to-add") as HTMLInputElement).value.trim(); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.dropDownList] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,dropDownListContentControl"); + await context.sync(); - let seriesTimeObject: Office.SeriesTime; + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,dropDownListContentControl"); + await context.sync(); - // Set series start date to tomorrow. + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.dropDownList) { + console.warn("No dropdown list content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } - seriesTimeObject.setStartDate(currentDate.getFullYear(), - currentDate.getMonth(), currentDate.getDay() + 1); + selectedContentControl.dropDownListContentControl.addListItem(listItemText); + await context.sync(); - // Set series end date to one year from now. + console.log(`List item added to control with ID ${selectedContentControl.id}: ${listItemText}`); + }); +Word.ContentControl#onDataChanged:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondatachanged-event.yaml - seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, - currentDate.getMonth() + 1, currentDate.getDay()); - // Set start time to 1:30 PM. + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls; + contentControls.load("items"); + await context.sync(); - seriesTimeObject.setStartTime(13, 30); + // Register the onDataChanged event handler on each content control. + if (contentControls.items.length === 0) { + console.log("There aren't any content controls in this document so can't register event handlers."); + } else { + for (let i = 0; i < contentControls.items.length; i++) { + eventContexts[i] = contentControls.items[i].onDataChanged.add(contentControlDataChanged); + contentControls.items[i].track(); + } - // Set duration to 30 minutes. + await context.sync(); - seriesTimeObject.setDuration(30); + console.log("Added event handlers for when data is changed in content controls."); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondatachanged-event.yaml - const pattern: Office.Recurrence = { - seriesTime: seriesTimeObject, - recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, - recurrenceProperties: { - interval: 1, - dayOfWeek: Office.MailboxEnums.Days.Tue, - weekNumber: Office.MailboxEnums.WeekNumber.Second, - month: Office.MailboxEnums.Month.Sep - }, - recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } - }; + async function contentControlDataChanged(event: + Word.ContentControlDataChangedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. IDs of content controls where data was changed:`, event.ids); + }); + } +Word.ContentControl#onDeleted:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml + + + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls; + contentControls.load("items"); + await context.sync(); + + // Register the onDeleted event handler on each content control. + if (contentControls.items.length === 0) { + console.log("There aren't any content controls in this document so can't register event handlers."); + } else { + for (let i = 0; i < contentControls.items.length; i++) { + eventContexts[i] = contentControls.items[i].onDeleted.add(contentControlDeleted); + contentControls.items[i].track(); + } + await context.sync(); - Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { - if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); - return; + console.log("Added event handlers for when content controls are deleted."); } - console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); }); -'Office.MasterCategories#addAsync:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml - const masterCategoriesToAdd = [ - { - displayName: "TestCategory", - color: Office.MailboxEnums.CategoryColor.Preset0 - } - ]; + + async function contentControlDeleted(event: + Word.ContentControlDeletedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. IDs of content controls that were deleted:`, event.ids); + }); + } +Word.ContentControl#onEntered:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onentered-event.yaml - Office.context.mailbox.masterCategories.addAsync(masterCategoriesToAdd, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Successfully added categories to master list"); + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls; + contentControls.load("items"); + await context.sync(); + + // Register the onEntered event handler on each content control. + if (contentControls.items.length === 0) { + console.log("There aren't any content controls in this document so can't register event handlers."); } else { - console.log("masterCategories.addAsync call failed with error: " + asyncResult.error.message); + for (let i = 0; i < contentControls.items.length; i++) { + eventContexts[i] = contentControls.items[i].onEntered.add(contentControlEntered); + contentControls.items[i].track(); + } + + await context.sync(); + + console.log("Added event handlers for when the cursor is placed in content controls."); } }); -'Office.MasterCategories#getAsync:member(2)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onentered-event.yaml - Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - console.log("Master categories:"); - console.log(JSON.stringify(categories)); - } else { - console.log("There are no categories in the master list."); - } - } else { - console.error(asyncResult.error); - } - }); -'Office.MasterCategories#removeAsync:member(1)': + + async function contentControlEntered(event: + Word.ContentControlEnteredEventArgs) { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. ID of content control that was entered: ${event.ids[0]}`); + }); + } +Word.ContentControl#onExited:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-master-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onexited-event.yaml - const masterCategoriesToRemove = ["TestCategory"]; + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls; + contentControls.load("items"); + await context.sync(); - Office.context.mailbox.masterCategories.removeAsync(masterCategoriesToRemove, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Successfully removed categories from master list"); + // Register the onExited event handler on each content control. + if (contentControls.items.length === 0) { + console.log("There aren't any content controls in this document so can't register event handlers."); } else { - console.log("masterCategories.removeAsync call failed with error: " + asyncResult.error.message); + for (let i = 0; i < contentControls.items.length; i++) { + eventContexts[i] = contentControls.items[i].onExited.add(contentControlExited); + contentControls.items[i].track(); + } + + await context.sync(); + + console.log("Added event handlers for when the cursor is removed from within content controls."); } }); -'Office.MessageCompose#addFileAttachmentAsync:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onexited-event.yaml - const attachmentUrl = $("#attachmentUrl").val(); - Office.context.mailbox.item.addFileAttachmentAsync( - attachmentUrl, - getFileName(attachmentUrl), - { "asyncContext" : { var1: 1, var2: true } }, - function(result) { console.log(result); }); -'Office.MessageCompose#addFileAttachmentFromBase64Async:member(1)': + async function contentControlExited(event: + Word.ContentControlExitedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. ID of content control that was exited: ${event.ids[0]}`); + }); + } +Word.ContentControl#onSelectionChanged:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onselectionchanged-event.yaml - base64String = - "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAACRUlEQVRYw82XzXHbMBCFP2F8tzsQc8Ixyh0zoiuIXIGdCsxUYKqC0B04FdiuwMoM7mGOOIXqQGoAymXhgSX+itJM9kIRFLAP+3YXD5Pdbscx5oxaAIW8Ztr6l2PWmQwF4IyaieP53qdfAqQ8CwBn1JU4vpWhrbxXQA5MZfynANmcDIAzKgcy4FKGXsVJFf3nLgKyBQptfT4KQMRz2N0fcbxqmRMDWXflx0VPnrdArq0vekQ1Dv0UeHZGNebHhwjU8AzwKM43RyZnbAf58Q6ghudeWd0Aus0+5EcMIIRi3beua0D3Nm39BEAx3i7HTK4DEBJn5YxKOnaRA5+ErpMBWMpzDvx1RuXCcxOISlufAjfC7zgAsqsvUvMAD0ApPaEtGi9AIlUzKgJo60tt/SyKRkzLrAXERluf7W1gOICWaMyB386oooOWsIHvXbSoHuUSFovtHqicUVnH3EJoeT0aQEf5/XBGlc6otIOWBXAtPeZkAIJ9Bt6cUU9tZautX2nrk3MACHYr1ZKProKRtDw4o8pzAPjWo+NtpXTTvoteDDg8noDAcwbcRedAkGdFXyk2GEDcegVAFp2gyVDHjRQ4o6q2smoqtR5Hd+qMqtoALCWUUymr1m43QMZfOaMK4C0SrMsDANJ2E5FNcbdbjHC+ENl+H0myJFbLtaq4Rt8dyPBYRQV1E40nMv9rl7xrOw3DGb+Whcqu3i/OM6CUOWvgRlufNmnLYy4m77uJI7AXtdNcTDrU71LEyv7v01/N/ovL6bmu5/8A1tNWZldH0W4AAAAASUVORK5CYII="; - Office.context.mailbox.item.addFileAttachmentFromBase64Async( - base64String, - "logo.png", - { isInline: false }, - function(result) { console.log(result); }); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls; + contentControls.load("items"); + await context.sync(); - // Set the signature for the current item with inline image. + if (contentControls.items.length === 0) { + console.log("There aren't any content controls in this document so can't register event handlers."); + } else { + for (let i = 0; i < contentControls.items.length; i++) { + eventContexts[i] = contentControls.items[i].onSelectionChanged.add(contentControlSelectionChanged); + contentControls.items[i].track(); + } - const modIcon1Base64 = - "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpDRDMxMDg1MjBCNDZFMTExODE2MkM1RUI2M0M4MDYxRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFMTUxQjgyRjQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFMTUxQjgyRTQ2MEQxMUUxODlFMkQwNTYzQ0YwMTUxMiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkQxMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkNEMzEwODUyMEI0NkUxMTE4MTYyQzVFQjYzQzgwNjFEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+uC/WfAAAAehJREFUeNpilCzfwEAEkAbiECA2A2J1IOaHin8E4ptAfBaIVwLxU0IGMRKw0B6IW4DYhoE4cASIK6E0VsCEQ1wUiNcB8QESLGOAqj0MxBuhZhBloS4QnwHiQAbygR/UDF1CFupCXSjHQDmQg5qli8tCUBBsQUoQ1AD8UDNFsVk4n0o+w+bT+egWglKjNymmeGhLkqLcG2oHAwtUoIuQDj5OVgZPLUmwRe5aEmAxqYqNpFgKssOcCeplM0KqdST5GfpDDRm0JfkYrj3/SE7QguyQY4ImYYLgCtAS10kHGMw6dzNsv/qC7OwCClJXYlR++v6b4er3j5QmIFcmaNlIL6AOslCIjhYKMTHQGTBBqxh6gXcgC6/R0cKbIAv30dHCfaAKGJTxHxJSqS3Fz9DkowNmywpyMcgA8fF7b8D8VWcfM6w8+4gYC+VB+RCk8hSh0gaUD4/dewvlvUWRe/z+GzGWgex4BGtiOAHxXhoHpzMoSGHZAhSPW2lo2VZYWkHOh4nEtLrIAE+hZmNUwK+B2BOIv1PRsu9QM1/jatNcBtVZ0IREKXgENesyoVYbzNIdFFi2A5tl+NqlL6BB4QBNzsSCU1A9nlAzMAALAQMOQl0qB23qWwKxIlIrDBQ394H4OBCvISYqAAIMACVibHDqsO7zAAAAAElFTkSuQmCC"; + await context.sync(); - Office.context.mailbox.item.addFileAttachmentFromBase64Async( - modIcon1Base64, - "myImage.png", - { isInline: true }, - function(result) { - if (result.status == Office.AsyncResultStatus.Succeeded) { - const signature = $("#signature").val() + ""; - console.log(`Setting signature to "${signature}".`); - Office.context.mailbox.item.body.setSignatureAsync( - signature, - { coercionType: "html" }, - function(asyncResult) { - console.log(`setSignatureAsync: ${asyncResult.status}`); - } - ); - } else { - console.error(`addFileAttachmentFromBase64Async: ${result.error}`); - } + console.log("Added event handlers for when selections are changed in content controls."); } - ); -'Office.MessageCompose#addItemAttachmentAsync:member(1)': + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onselectionchanged-event.yaml - const attachmentItemId = $("#attachmentItemId").val(); - Office.context.mailbox.item.addItemAttachmentAsync( - attachmentItemId, - "My attachment", - { "asyncContext" : { var3: 3, var4: false } }, - function(result) { console.log(result); }); -'Office.MessageCompose#bcc:member': + async function contentControlSelectionChanged(event: + Word.ContentControlSelectionChangedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. IDs of content controls where selection was changed:`, event.ids); + }); + } +Word.ContentControl#tag:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-bcc-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-content-controls.yaml - Office.context.mailbox.item.bcc.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const msgBcc = asyncResult.value; - console.log("Message being blind-copied to:"); - for (let i = 0; i < msgBcc.length; i++) { - console.log(msgBcc[i].displayName + " (" + msgBcc[i].emailAddress + ")"); + + // Traverses each paragraph of the document and wraps a content control on + each with either a even or odd tags. + + await Word.run(async (context) => { + let paragraphs = context.document.body.paragraphs; + paragraphs.load("$none"); // Don't need any properties; just wrap each paragraph with a content control. + + await context.sync(); + + for (let i = 0; i < paragraphs.items.length; i++) { + let contentControl = paragraphs.items[i].insertContentControl(); + // For even, tag "even". + if (i % 2 === 0) { + contentControl.tag = "even"; + } else { + contentControl.tag = "odd"; } - } else { - console.error(asyncResult.error); } + console.log("Content controls inserted: " + paragraphs.items.length); + + await context.sync(); }); +Word.ContentControlAddedEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-bcc-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onadded-event.yaml - const email = $("#emailBcc") - .val() - .toString(); - const emailArray = [email]; - Office.context.mailbox.item.bcc.setAsync(emailArray, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Succeeded in setting Bcc field."); - } else { - console.error(asyncResult.error); - } + // Registers the onAdded event handler on the document. + + await Word.run(async (context) => { + eventContext = context.document.onContentControlAdded.add(contentControlAdded); + await context.sync(); + + console.log("Added event handler for when content controls are added."); }); -'Office.MessageCompose#categories:member': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onadded-event.yaml - Office.context.mailbox.item.categories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - console.log("Categories assigned to this item:"); - console.log(JSON.stringify(categories)); - } else { - console.log("There are no categories assigned to this item."); - } - } else { - console.error(asyncResult.error); - } - }); + + async function contentControlAdded(event: Word.ContentControlAddedEventArgs) + { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. IDs of content controls that were added:`, event.ids); + }); + } +Word.ContentControlAppearance:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-content-controls.yaml - // Note: In order for you to successfully add a category, - // it must be in the mailbox categories master list. + // Adds title and colors to odd and even content controls and changes their + appearance. + await Word.run(async (context) => { + // Get the complete sentence (as range) associated with the insertion point. + let evenContentControls = context.document.contentControls.getByTag("even"); + let oddContentControls = context.document.contentControls.getByTag("odd"); + evenContentControls.load("length"); + oddContentControls.load("length"); - Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const masterCategories = asyncResult.value; - if (masterCategories && masterCategories.length > 0) { - // Grab the first category from the master list. - const categoryToAdd = [masterCategories[0].displayName]; - Office.context.mailbox.item.categories.addAsync(categoryToAdd, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully assigned category '${categoryToAdd}' to item.`); - } else { - console.log("categories.addAsync call failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("There are no categories in the master list on this mailbox. You can add categories using Office.context.mailbox.masterCategories.addAsync."); - } - } else { - console.error(asyncResult.error); + await context.sync(); + + for (let i = 0; i < evenContentControls.items.length; i++) { + // Change a few properties and append a paragraph. + evenContentControls.items[i].set({ + color: "red", + title: "Odd ContentControl #" + (i + 1), + appearance: Word.ContentControlAppearance.tags + }); + evenContentControls.items[i].insertParagraph("This is an odd content control", "End"); } - }); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml - Office.context.mailbox.item.categories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - // Grab the first category assigned to this item. - const categoryToRemove = [categories[0].displayName]; - Office.context.mailbox.item.categories.removeAsync(categoryToRemove, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully unassigned category '${categoryToRemove}' from this item.`); - } else { - console.log("categories.removeAsync call failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("There are no categories assigned to this item."); - } - } else { - console.error(asyncResult.error); + for (let j = 0; j < oddContentControls.items.length; j++) { + // Change a few properties and append a paragraph. + oddContentControls.items[j].set({ + color: "green", + title: "Even ContentControl #" + (j + 1), + appearance: "Tags" + }); + oddContentControls.items[j].insertHtml("This is an even content control", "End"); } + + await context.sync(); }); -'Office.MessageCompose#cc:member': +Word.ContentControlCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-cc-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/doc-assembly.yaml - Office.context.mailbox.item.cc.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const msgCc = asyncResult.value; - console.log("Message being copied to:"); - for (let i = 0; i < msgCc.length; i++) { - console.log(msgCc[i].displayName + " (" + msgCc[i].emailAddress + ")"); + + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls.getByTag("customer"); + contentControls.load("text"); + + await context.sync(); + + for (let i = 0; i < contentControls.items.length; i++) { + contentControls.items[i].insertText("Fabrikam", "Replace"); } - } else { - console.error(asyncResult.error); - } + + await context.sync(); }); +Word.ContentControlCollection#getByTag:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-cc-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/doc-assembly.yaml - const email = $("#emailCc") - .val() - .toString(); - const emailArray = [email]; - Office.context.mailbox.item.cc.setAsync(emailArray, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Succeeded in setting Cc field."); - } else { - console.error(asyncResult.error); - } + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls.getByTag("customer"); + contentControls.load("text"); + + await context.sync(); + + for (let i = 0; i < contentControls.items.length; i++) { + contentControls.items[i].insertText("Fabrikam", "Replace"); + } + + await context.sync(); }); -'Office.MessageCompose#close:member(1)': +Word.ContentControlCollection#getFirstOrNullObject:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/25-item-save-and-close/close.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml - Office.context.mailbox.item.close(); -'Office.MessageCompose#closeAsync:member(2)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/close-async.yaml - // This snippet closes the current message being composed and discards any - unsaved changes when the optional property, discardItem, is set to true. + // Toggles the isChecked property of the first checkbox content control + found in the selection. - // The API call works on a new message being composed, a reply, or an - existing draft. + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.checkBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,checkboxContentControl/isChecked"); - // When discardItem is set to false or isn't defined on a new message with - unsaved changes, the user is prompted to save a draft, discard the changes, - or cancel the close operation. + await context.sync(); - Office.context.mailbox.item.closeAsync( - { discardItem: true }, - (asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Action failed with error: " + asyncResult.error.message); + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,checkboxContentControl/isChecked"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.checkBox) { + console.warn("No checkbox content control is currently selected."); return; + } else { + selectedContentControl = parentContentControl; } - }); -'Office.MessageCompose#conversationId:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-conversation-id-message.yaml + } - console.log(`Conversation ID: - ${Office.context.mailbox.item.conversationId}`); -'Office.MessageCompose#delayDeliveryTime:member': + const isCheckedBefore = selectedContentControl.checkboxContentControl.isChecked; + console.log("isChecked state before:", `id: ${selectedContentControl.id} ... isChecked: ${isCheckedBefore}`); + selectedContentControl.checkboxContentControl.isChecked = !isCheckedBefore; + selectedContentControl.load("id,checkboxContentControl/isChecked"); + await context.sync(); + + console.log( + "isChecked state after:", + `id: ${selectedContentControl.id} ... isChecked: ${selectedContentControl.checkboxContentControl.isChecked}` + ); + }); +Word.ContentControlDataChangedEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/delay-message-delivery.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondatachanged-event.yaml - function setDeliveryDate(minutes) { - // This snippet sets the delivery date and time of a message. - const currentTime = new Date().getTime(); - const milliseconds = totalDelay * 60000; - const timeDelay = new Date(currentTime + milliseconds); - Office.context.mailbox.item.delayDeliveryTime.setAsync(timeDelay, (asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log(asyncResult.error.message); - return; - } - if (minutes === 1440) { - console.log(`Delayed delivery by an additional one day.`); - } else { - console.log(`Delayed delivery by an additional ${minutes} minutes.`); + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls; + contentControls.load("items"); + await context.sync(); + + // Register the onDataChanged event handler on each content control. + if (contentControls.items.length === 0) { + console.log("There aren't any content controls in this document so can't register event handlers."); + } else { + for (let i = 0; i < contentControls.items.length; i++) { + eventContexts[i] = contentControls.items[i].onDataChanged.add(contentControlDataChanged); + contentControls.items[i].track(); } - }); - } -'Office.MessageCompose#disableClientSignatureAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml - // Disable the client signature. + await context.sync(); - Office.context.mailbox.item.disableClientSignatureAsync(function(asyncResult) - { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("disableClientSignatureAsync succeeded"); - } else { - console.error(asyncResult.error); + console.log("Added event handlers for when data is changed in content controls."); } }); -'Office.MessageCompose#from:member': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-from-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondatachanged-event.yaml - Office.context.mailbox.item.from.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const msgFrom = asyncResult.value; - console.log("Message from: " + msgFrom.displayName + " (" + msgFrom.emailAddress + ")"); - } else { - console.error(asyncResult.error); - } - }); -'Office.MessageCompose#getAttachmentContentAsync:member(1)': + + async function contentControlDataChanged(event: + Word.ContentControlDataChangedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. IDs of content controls where data was changed:`, event.ids); + }); + } +Word.ContentControlDeletedEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachment-content.yaml - - // Gets the attachments of the current message or appointment in compose - mode. + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml - const options = { asyncContext: { currentItem: item } }; - // The getAttachmentsAsync call can only be used in compose mode. + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls; + contentControls.load("items"); + await context.sync(); - item.getAttachmentsAsync(options, callback); + // Register the onDeleted event handler on each content control. + if (contentControls.items.length === 0) { + console.log("There aren't any content controls in this document so can't register event handlers."); + } else { + for (let i = 0; i < contentControls.items.length; i++) { + eventContexts[i] = contentControls.items[i].onDeleted.add(contentControlDeleted); + contentControls.items[i].track(); + } + await context.sync(); - function callback(result) { - if (result.status === Office.AsyncResultStatus.Failed) { - console.log(result.error.message); - return; + console.log("Added event handlers for when content controls are deleted."); } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml - if (result.value.length <= 0) { - console.log("Mail item has no attachments."); - return; - } - for (let i = 0; i < result.value.length; i++) { - // Log the attachment type and its contents to the console. - result.asyncContext.currentItem.getAttachmentContentAsync(result.value[i].id, handleAttachmentsCallback); - } + async function contentControlDeleted(event: + Word.ContentControlDeletedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. IDs of content controls that were deleted:`, event.ids); + }); } -'Office.MessageCompose#getAttachmentsAsync:member(1)': +Word.ContentControlEnteredEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onentered-event.yaml - Office.context.mailbox.item.getAttachmentsAsync(function (result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(result.error.message); - } else { - if (result.value.length > 0) { - for (let i = 0; i < result.value.length; i++) { - const attachment = result.value[i]; - console.log("ID: " + attachment.id + "\n" + - "Name: " + attachment.name + "\n" + - "Size: " + attachment.size + "\n" + - "isInline: " + attachment.isInline); - switch (attachment.attachmentType) { - case Office.MailboxEnums.AttachmentType.Cloud: - console.log("Attachment type: Attachment is stored in a cloud location."); - break; - case Office.MailboxEnums.AttachmentType.File: - console.log("Attachment type: Attachment is a file."); - break; - case Office.MailboxEnums.AttachmentType.Item: - console.log("Attachment type: Attachment is an Exchange item."); - break; - } - } - } - else { - console.log("No attachments on this message."); - } - } - }); -'Office.MessageCompose#getComposeTypeAsync:member(2)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml - // Get the compose type of the current message. + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls; + contentControls.load("items"); + await context.sync(); - Office.context.mailbox.item.getComposeTypeAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log( - "getComposeTypeAsync succeeded with composeType: " + - asyncResult.value.composeType + - " and coercionType: " + - asyncResult.value.coercionType - ); + // Register the onEntered event handler on each content control. + if (contentControls.items.length === 0) { + console.log("There aren't any content controls in this document so can't register event handlers."); } else { - console.error(asyncResult.error); + for (let i = 0; i < contentControls.items.length; i++) { + eventContexts[i] = contentControls.items[i].onEntered.add(contentControlEntered); + contentControls.items[i].track(); + } + + await context.sync(); + + console.log("Added event handlers for when the cursor is placed in content controls."); } }); -'Office.MessageCompose#getItemIdAsync:member(2)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/item-id-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onentered-event.yaml - Office.context.mailbox.item.getItemIdAsync(function (result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`getItemIdAsync failed with message: ${result.error.message}`); - } else { - console.log(result.value); - } - }); -'Office.MessageCompose#getSelectedDataAsync:member(2)': + + async function contentControlEntered(event: + Word.ContentControlEnteredEventArgs) { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. ID of content control that was entered: ${event.ids[0]}`); + }); + } +Word.ContentControlExitedEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/get-selected-data.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onexited-event.yaml + + + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls; + contentControls.load("items"); + await context.sync(); - Office.context.mailbox.item.getSelectedDataAsync(Office.CoercionType.Text, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const text = asyncResult.value.data; - const prop = asyncResult.value.sourceProperty; - console.log("Selected text in " + prop + ": " + text); + // Register the onExited event handler on each content control. + if (contentControls.items.length === 0) { + console.log("There aren't any content controls in this document so can't register event handlers."); } else { - console.error(asyncResult.error); + for (let i = 0; i < contentControls.items.length; i++) { + eventContexts[i] = contentControls.items[i].onExited.add(contentControlExited); + contentControls.items[i].track(); + } + + await context.sync(); + + console.log("Added event handlers for when the cursor is removed from within content controls."); } }); -'Office.MessageCompose#getSharedPropertiesAsync:member(2)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml - - if (!Office.context.mailbox.item.getSharedPropertiesAsync) { - console.error("Try this sample on an item from a shared folder."); - return; - } + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onexited-event.yaml - Office.context.mailbox.item.getSharedPropertiesAsync(function(result) { - console.log(result.value); - }); -'Office.MessageCompose#getSharedPropertiesAsync:member(1)': + async function contentControlExited(event: + Word.ContentControlExitedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. ID of content control that was exited: ${event.ids[0]}`); + }); + } +Word.ContentControlListItem:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml - if (!Office.context.mailbox.item.getSharedPropertiesAsync) { - console.error("Try this sample on a message from a shared folder."); - return; - } + // Deletes the provided list item from the first dropdown list content + control in the selection. - Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, - function(result) { - if (result.status === Office.AsyncResultStatus.Succeeded && result.value !== "") { - Office.context.mailbox.item.getSharedPropertiesAsync( - { - // Pass auth token along. - asyncContext: result.value - }, - function(result2) { - let sharedProperties = result2.value; - let delegatePermissions = sharedProperties.delegatePermissions; - - // Determine if user has the appropriate permission to do the operation. - if ((delegatePermissions & Office.MailboxEnums.DelegatePermissions.Read) != 0) { - const ewsId = Office.context.mailbox.item.itemId; - const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); - let rest_url = - sharedProperties.targetRestUrl + "/v2.0/users/" + sharedProperties.targetMailbox + "/messages/" + restId; - - $.ajax({ - url: rest_url, - dataType: "json", - headers: { Authorization: "Bearer " + result2.asyncContext } - }) - .done(function(response) { - console.log(response); - }) - .fail(function(error) { - console.error(error); - }); - } - } - ); - } - }); -'Office.MessageCompose#internetHeaders:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml + await Word.run(async (context) => { + const listItemText = (document.getElementById("item-to-delete") as HTMLInputElement).value.trim(); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.dropDownList] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,dropDownListContentControl"); + await context.sync(); - Office.context.mailbox.item.internetHeaders.getAsync( - ["x-preferred-fruit", "x-preferred-vegetable", "x-best-vegetable", "x-nonexistent-header"], - function (asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Selected headers: " + JSON.stringify(asyncResult.value)); + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,dropDownListContentControl"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.dropDownList) { + console.warn("No dropdown list content control is currently selected."); + return; } else { - console.log("Error getting selected headers: " + JSON.stringify(asyncResult.error)); + selectedContentControl = parentContentControl; } } - ); -'Office.MessageCompose#isClientSignatureEnabledAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml - // Check if the client signature is currently enabled. + let selectedDropdownList: Word.DropDownListContentControl = selectedContentControl.dropDownListContentControl; + selectedDropdownList.listItems.load("items/*"); + await context.sync(); - Office.context.mailbox.item.isClientSignatureEnabledAsync(function(asyncResult) - { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("isClientSignatureEnabledAsync succeeded with result: " + asyncResult.value); - } else { - console.error(asyncResult.error); + let listItems: Word.ContentControlListItemCollection = selectedContentControl.dropDownListContentControl.listItems; + let itemToDelete: Word.ContentControlListItem = listItems.items.find((item) => item.displayText === listItemText); + if (!itemToDelete) { + console.warn(`List item doesn't exist in control with ID ${selectedContentControl.id}: ${listItemText}`) + return; } + + itemToDelete.delete(); + await context.sync(); + + console.log(`List item deleted from control with ID ${selectedContentControl.id}: ${listItemText}`); }); -'Office.MessageCompose#itemType:member': +Word.ContentControlListItem#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-type.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml - const itemType = Office.context.mailbox.item.itemType; - switch (itemType) { - case Office.MailboxEnums.ItemType.Appointment: - console.log(`Current item is an ${itemType}.`); - break; - case Office.MailboxEnums.ItemType.Message: - console.log(`Current item is a ${itemType}. A message could be an email, meeting request, meeting response, or meeting cancellation.`); - break; - } -'Office.MessageCompose#loadCustomPropertiesAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + // Deletes the provided list item from the first combo box content control + in the selection. - Office.context.mailbox.item.loadCustomPropertiesAsync(function (result) { - if (result.status === Office.AsyncResultStatus.Succeeded) { - console.log("Loaded following custom properties:"); - customProps = result.value; - const dataKey = Object.keys(customProps)[0]; - const data = customProps[dataKey]; - for (let propertyName in data) - { - let propertyValue = data[propertyName]; - console.log(`${propertyName}: ${propertyValue}`); - } + await Word.run(async (context) => { + const listItemText = (document.getElementById("item-to-delete") as HTMLInputElement).value.trim(); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.comboBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,comboBoxContentControl"); + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,comboBoxContentControl"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.comboBox) { + console.warn("No combo box content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } } - else { - console.error(`loadCustomPropertiesAsync failed with message ${result.error.message}`); + + let selectedComboBox: Word.ComboBoxContentControl = selectedContentControl.comboBoxContentControl; + selectedComboBox.listItems.load("items/*"); + await context.sync(); + + let listItems: Word.ContentControlListItemCollection = selectedContentControl.comboBoxContentControl.listItems; + let itemToDelete: Word.ContentControlListItem = listItems.items.find((item) => item.displayText === listItemText); + if (!itemToDelete) { + console.warn(`List item doesn't exist in control with ID ${selectedContentControl.id}: ${listItemText}`); + return; } + + itemToDelete.delete(); + await context.sync(); + + console.log(`List item deleted from control with ID ${selectedContentControl.id}: ${listItemText}`); }); -'Office.MessageCompose#notificationMessages:member': +Word.ContentControlListItem#displayText:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml - const id = $("#notificationId").val(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.ProgressIndicator, - message: "Progress indicator with id = " + id - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Deletes the provided list item from the first dropdown list content + control in the selection. - const id = $("#notificationId").val(); + await Word.run(async (context) => { + const listItemText = (document.getElementById("item-to-delete") as HTMLInputElement).value.trim(); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.dropDownList] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,dropDownListContentControl"); + await context.sync(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Non-persistent informational notification message with id = " + id, - icon: "icon1", - persistent: false - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,dropDownListContentControl"); + await context.sync(); - const id = $("#notificationId").val(); + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.dropDownList) { + console.warn("No dropdown list content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Persistent informational notification message with id = " + id, - icon: "icon1", - persistent: true - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + let selectedDropdownList: Word.DropDownListContentControl = selectedContentControl.dropDownListContentControl; + selectedDropdownList.listItems.load("items/*"); + await context.sync(); - Office.context.mailbox.item.notificationMessages.getAllAsync(handleResult); + let listItems: Word.ContentControlListItemCollection = selectedContentControl.dropDownListContentControl.listItems; + let itemToDelete: Word.ContentControlListItem = listItems.items.find((item) => item.displayText === listItemText); + if (!itemToDelete) { + console.warn(`List item doesn't exist in control with ID ${selectedContentControl.id}: ${listItemText}`) + return; + } + + itemToDelete.delete(); + await context.sync(); + + console.log(`List item deleted from control with ID ${selectedContentControl.id}: ${listItemText}`); + }); +Word.ContentControlListItemCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml - const id = $("#notificationId").val(); - Office.context.mailbox.item.notificationMessages.replaceAsync( - id, - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Notification message with id = " + id + " has been replaced with an informational message.", - icon: "icon2", - persistent: false - }, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Gets the list items from the first combo box content control found in the + selection. - const id = $("#notificationId").val(); + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.comboBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,comboBoxContentControl"); + await context.sync(); - Office.context.mailbox.item.notificationMessages.removeAsync(id, - handleResult); -'Office.MessageCompose#removeAttachmentAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/attachments-compose.yaml + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,comboBoxContentControl"); + await context.sync(); - Office.context.mailbox.item.removeAttachmentAsync( - $("#attachmentId").val(), - { asyncContext : null }, - function(result) - { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`${result.error.message}`); - } else { - console.log(`Attachment removed successfully.`); - } + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.comboBox) { + console.warn("No combo box content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; } - ); -'Office.MessageCompose#seriesId:member': + } + + let selectedComboBox: Word.ComboBoxContentControl = selectedContentControl.comboBoxContentControl; + selectedComboBox.listItems.load("items"); + await context.sync(); + + const currentItems: Word.ContentControlListItemCollection = selectedComboBox.listItems; + console.log(`The list from the combo box content control with ID ${selectedContentControl.id}:`, currentItems); + }); +Word.ContentControlOptions:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-series-id.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml - const seriesId = Office.context.mailbox.item.seriesId; + // Toggles the isChecked property of the first checkbox content control + found in the selection. - if (seriesId === undefined) { - console.log("This is a message that's not a meeting request."); - } else if (seriesId === null) { - console.log("This is a single appointment, a parent series, or a meeting request for a series or single meeting."); - } else { - console.log("This is an instance belonging to series with ID " + seriesId); - } -'Office.MessageCompose#sessionData:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.checkBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,checkboxContentControl/isChecked"); - Office.context.mailbox.item.sessionData.getAllAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("The sessionData is " + JSON.stringify(asyncResult.value)); - } else { - console.log("Failed to get all sessionData. Error: " + JSON.stringify(asyncResult.error)); + await context.sync(); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,checkboxContentControl/isChecked"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.checkBox) { + console.warn("No checkbox content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } } + + const isCheckedBefore = selectedContentControl.checkboxContentControl.isChecked; + console.log("isChecked state before:", `id: ${selectedContentControl.id} ... isChecked: ${isCheckedBefore}`); + selectedContentControl.checkboxContentControl.isChecked = !isCheckedBefore; + selectedContentControl.load("id,checkboxContentControl/isChecked"); + await context.sync(); + + console.log( + "isChecked state after:", + `id: ${selectedContentControl.id} ... isChecked: ${selectedContentControl.checkboxContentControl.isChecked}` + ); }); -'Office.MessageCompose#setSelectedDataAsync:member(1)': +Word.ContentControlSelectionChangedEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/set-selected-data.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onselectionchanged-event.yaml - Office.context.mailbox.item.setSelectedDataAsync("Replaced", - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Selected text has been updated successfully."); + + await Word.run(async (context) => { + const contentControls: Word.ContentControlCollection = context.document.contentControls; + contentControls.load("items"); + await context.sync(); + + if (contentControls.items.length === 0) { + console.log("There aren't any content controls in this document so can't register event handlers."); } else { - console.error(asyncResult.error); + for (let i = 0; i < contentControls.items.length; i++) { + eventContexts[i] = contentControls.items[i].onSelectionChanged.add(contentControlSelectionChanged); + contentControls.items[i].track(); + } + + await context.sync(); + + console.log("Added event handlers for when selections are changed in content controls."); } }); -'Office.MessageCompose#subject:member': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-subject-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onselectionchanged-event.yaml - Office.context.mailbox.item.subject.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; - } - console.log(`Subject: ${result.value}`); - }); + + async function contentControlSelectionChanged(event: + Word.ContentControlSelectionChangedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. IDs of content controls where selection was changed:`, event.ids); + }); + } +Word.ContentControlState:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-subject-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/insert-and-change-content-controls.yaml - let subject = "Hello World!"; - Office.context.mailbox.item.subject.setAsync(subject, (result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); + // Sets the state of the first content control. + + await Word.run(async (context) => { + const state = ((document.getElementById("state-to-set") as HTMLSelectElement) + .value as unknown) as Word.ContentControlState; + let firstContentControl = context.document.contentControls.getFirstOrNullObject(); + await context.sync(); + + if (firstContentControl.isNullObject) { + console.warn("There are no content controls in this document."); return; } - console.log(`Successfully set subject to ${subject}`); + + firstContentControl.setState(state); + firstContentControl.load("id"); + await context.sync(); + + console.log(`Set state of first content control with ID ${firstContentControl.id} to ${state}.`); }); -'Office.MessageCompose#to:member': +Word.ContentControlType:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-to-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml - Office.context.mailbox.item.to.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const msgTo = asyncResult.value; - console.log("Message being sent to:"); - for (let i = 0; i < msgTo.length; i++) { - console.log(msgTo[i].displayName + " (" + msgTo[i].emailAddress + ")"); - } - } else { - console.error(asyncResult.error); + + // Traverses each paragraph of the document and places a checkbox content + control at the beginning of each. + + await Word.run(async (context) => { + let paragraphs = context.document.body.paragraphs; + paragraphs.load("$none"); // Don't need any properties; just start each paragraph with a content control. + + await context.sync(); + + for (let i = 0; i < paragraphs.items.length; i++) { + let contentControl = paragraphs.items[i] + .getRange(Word.RangeLocation.start) + .insertContentControl(Word.ContentControlType.checkBox); } + console.log("Checkbox content controls inserted: " + paragraphs.items.length); + + await context.sync(); }); +Word.Critique:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-to-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - const email = $("#emailTo") - .val() - .toString(); - const emailArray = [email]; - Office.context.mailbox.item.to.setAsync(emailArray, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Succeeded in setting To field."); - } else { - console.error(asyncResult.error); - } + // Adds annotations to the selected paragraph. + + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const options: Word.CritiquePopupOptions = { + brandingTextResourceId: "PG.TabLabel", + subtitleResourceId: "PG.HelpCommand.TipTitle", + titleResourceId: "PG.HelpCommand.Label", + suggestions: ["suggestion 1", "suggestion 2", "suggestion 3"] + }; + const critique1: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.red, + start: 1, + length: 3, + popupOptions: options + }; + const critique2: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.green, + start: 6, + length: 1, + popupOptions: options + }; + const critique3: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.blue, + start: 10, + length: 3, + popupOptions: options + }; + const critique4: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.lavender, + start: 14, + length: 3, + popupOptions: options + }; + const critique5: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.berry, + start: 18, + length: 10, + popupOptions: options + }; + const annotationSet: Word.AnnotationSet = { + critiques: [critique1, critique2, critique3, critique4, critique5] + }; + + const annotationIds = paragraph.insertAnnotations(annotationSet); + + await context.sync(); + + console.log("Annotations inserted:", annotationIds.value); }); -'Office.MessageRead#attachments:member': +Word.CritiqueAnnotation:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachments-read.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - const attachments = Office.context.mailbox.item.attachments; - console.log(attachments); -'Office.MessageRead#categories:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + // Gets annotations found in the selected paragraph. - Office.context.mailbox.item.categories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - console.log("Categories assigned to this item:"); - console.log(JSON.stringify(categories)); - } else { - console.log("There are no categories assigned to this item."); - } - } else { - console.error(asyncResult.error); + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id,state,critiqueAnnotation"); + + await context.sync(); + + console.log("Annotations found:"); + + for (let i = 0; i < annotations.items.length; i++) { + const annotation: Word.Annotation = annotations.items[i]; + + console.log(`ID ${annotation.id} - state '${annotation.state}':`, annotation.critiqueAnnotation.critique); } }); +Word.CritiqueAnnotation#accept:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // Note: In order for you to successfully add a category, - // it must be in the mailbox categories master list. + // Accepts the first annotation found in the selected paragraph. + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id,state,critiqueAnnotation"); - Office.context.mailbox.masterCategories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const masterCategories = asyncResult.value; - if (masterCategories && masterCategories.length > 0) { - // Grab the first category from the master list. - const categoryToAdd = [masterCategories[0].displayName]; - Office.context.mailbox.item.categories.addAsync(categoryToAdd, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully assigned category '${categoryToAdd}' to item.`); - } else { - console.log("categories.addAsync call failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("There are no categories in the master list on this mailbox. You can add categories using Office.context.mailbox.masterCategories.addAsync."); + await context.sync(); + + for (let i = 0; i < annotations.items.length; i++) { + const annotation: Word.Annotation = annotations.items[i]; + + if (annotation.state === Word.AnnotationState.created) { + console.log(`Accepting ID ${annotation.id}...`); + annotation.critiqueAnnotation.accept(); + + await context.sync(); + break; } - } else { - console.error(asyncResult.error); } }); +Word.CritiqueAnnotation#reject:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/45-categories/work-with-categories.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - Office.context.mailbox.item.categories.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const categories = asyncResult.value; - if (categories && categories.length > 0) { - // Grab the first category assigned to this item. - const categoryToRemove = [categories[0].displayName]; - Office.context.mailbox.item.categories.removeAsync(categoryToRemove, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(`Successfully unassigned category '${categoryToRemove}' from this item.`); - } else { - console.log("categories.removeAsync call failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("There are no categories assigned to this item."); + + // Rejects the last annotation found in the selected paragraph. + + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id,state,critiqueAnnotation"); + + await context.sync(); + + for (let i = annotations.items.length - 1; i >= 0; i--) { + const annotation: Word.Annotation = annotations.items[i]; + + if (annotation.state === Word.AnnotationState.created) { + console.log(`Rejecting ID ${annotation.id}...`); + annotation.critiqueAnnotation.reject(); + + await context.sync(); + break; } - } else { - console.error(asyncResult.error); } }); -'Office.MessageRead#cc:member': +Word.CritiqueAnnotation#critique:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-cc-message-read.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - const msgCc = Office.context.mailbox.item.cc; - console.log("Message copied to:"); + // Gets annotations found in the selected paragraph. - for (let i = 0; i < msgCc.length; i++) { - console.log(msgCc[i].displayName + " (" + msgCc[i].emailAddress + ")"); - } -'Office.MessageRead#conversationId:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-conversation-id-message.yaml + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id,state,critiqueAnnotation"); - console.log(`Conversation ID: - ${Office.context.mailbox.item.conversationId}`); -'Office.MessageRead#dateTimeCreated:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-date-time-created-read.yaml + await context.sync(); - console.log(`Creation date and time: - ${Office.context.mailbox.item.dateTimeCreated}`); -'Office.MessageRead#dateTimeModified:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-date-time-modified-read.yaml + console.log("Annotations found:"); - console.log(`Date and time item last modified: - ${Office.context.mailbox.item.dateTimeModified}`); -'Office.MessageRead#display:member': + for (let i = 0; i < annotations.items.length; i++) { + const annotation: Word.Annotation = annotations.items[i]; + + console.log(`ID ${annotation.id} - state '${annotation.state}':`, annotation.critiqueAnnotation.critique); + } + }); +Word.CritiqueColorScheme:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // This snippet temporarily sets the content displayed in the body of a - message in read mode. - // The set content will remain visible until the user switches to a - different message in the Reading Pane or closes the window of the current - message. + // Adds annotations to the selected paragraph. - const bodyText = $("#body-text-field") - .val() - .toString(); - Office.context.mailbox.item.display.body.setAsync(bodyText, (asyncResult) => - { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log(`Action failed with error: ${asyncResult.error.message}`); - return; - } + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const options: Word.CritiquePopupOptions = { + brandingTextResourceId: "PG.TabLabel", + subtitleResourceId: "PG.HelpCommand.TipTitle", + titleResourceId: "PG.HelpCommand.Label", + suggestions: ["suggestion 1", "suggestion 2", "suggestion 3"] + }; + const critique1: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.red, + start: 1, + length: 3, + popupOptions: options + }; + const critique2: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.green, + start: 6, + length: 1, + popupOptions: options + }; + const critique3: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.blue, + start: 10, + length: 3, + popupOptions: options + }; + const critique4: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.lavender, + start: 14, + length: 3, + popupOptions: options + }; + const critique5: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.berry, + start: 18, + length: 10, + popupOptions: options + }; + const annotationSet: Word.AnnotationSet = { + critiques: [critique1, critique2, critique3, critique4, critique5] + }; - console.log("Temporarily set the content displayed in the body."); + const annotationIds = paragraph.insertAnnotations(annotationSet); + + await context.sync(); + + console.log("Annotations inserted:", annotationIds.value); }); -'Office.MessageRead#displayReplyAllForm:member(1)': +Word.CritiquePopupOptions:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - Office.context.mailbox.item.displayReplyAllForm("This is a reply ALL with - some bold text."); -'Office.MessageRead#displayReplyAllFormAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml - Office.context.mailbox.item.displayReplyAllFormAsync("This is a reply ALL - with some bold text.", function( - asyncResult - ) { - console.log(JSON.stringify(asyncResult)); + // Adds annotations to the selected paragraph. + + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const options: Word.CritiquePopupOptions = { + brandingTextResourceId: "PG.TabLabel", + subtitleResourceId: "PG.HelpCommand.TipTitle", + titleResourceId: "PG.HelpCommand.Label", + suggestions: ["suggestion 1", "suggestion 2", "suggestion 3"] + }; + const critique1: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.red, + start: 1, + length: 3, + popupOptions: options + }; + const critique2: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.green, + start: 6, + length: 1, + popupOptions: options + }; + const critique3: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.blue, + start: 10, + length: 3, + popupOptions: options + }; + const critique4: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.lavender, + start: 14, + length: 3, + popupOptions: options + }; + const critique5: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.berry, + start: 18, + length: 10, + popupOptions: options + }; + const annotationSet: Word.AnnotationSet = { + critiques: [critique1, critique2, critique3, critique4, critique5] + }; + + const annotationIds = paragraph.insertAnnotations(annotationSet); + + await context.sync(); + + console.log("Annotations inserted:", annotationIds.value); }); -'Office.MessageRead#displayReplyForm:member(1)': +Word.CustomProperty:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml - Office.context.mailbox.item.displayReplyForm("This is a reply with some - text in italics."); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml - Office.context.mailbox.item.displayReplyForm({ - htmlBody: "This is a reply with a couple of attachments - an inline image and an item
", - attachments: [ - { type: "file", url: "http://i.imgur.com/9S36xvA.jpg", name: "dog.jpg", isInline: true }, - { type: "item", itemId: Office.context.mailbox.item.itemId, name: "test_email.msg" } - ], - options: { asyncContext: null }, - callback: function(result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - } - } + await Word.run(async (context) => { + const properties: Word.CustomPropertyCollection = context.document.properties.customProperties; + properties.load("key,type,value"); + + await context.sync(); + for (let i = 0; i < properties.items.length; i++) + console.log("Property Name:" + properties.items[i].key + "; Type=" + properties.items[i].type + "; Property Value=" + properties.items[i].value); }); -'Office.MessageRead#displayReplyFormAsync:member(1)': +Word.CustomPropertyCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-forms.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml - Office.context.mailbox.item.displayReplyFormAsync("This is a reply with - some text in italics.", function( - asyncResult - ) { - console.log(JSON.stringify(asyncResult)); + + await Word.run(async (context) => { + const properties: Word.CustomPropertyCollection = context.document.properties.customProperties; + properties.load("key,type,value"); + + await context.sync(); + for (let i = 0; i < properties.items.length; i++) + console.log("Property Name:" + properties.items[i].key + "; Type=" + properties.items[i].type + "; Property Value=" + properties.items[i].value); }); +Word.CustomPropertyCollection#add:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/55-display-items/display-reply-with-attachments.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml - // The async version is only available starting with requirement set 1.9, - // and provides a callback when the new appointment form has been created. + await Word.run(async (context) => { + context.document.properties.customProperties.add("Numeric Property", 1234); - Office.context.mailbox.item.displayReplyFormAsync( - { - htmlBody: "This is a reply with a couple of attachments - an inline image and an item
", - attachments: [ - { type: "file", url: "http://i.imgur.com/9S36xvA.jpg", name: "dog.jpg", isInline: true }, - { type: "item", itemId: Office.context.mailbox.item.itemId, name: "test_email.msg" } - ] - }, - function(asyncResult) { - console.log(JSON.stringify(asyncResult)); - } - ); -'Office.MessageRead#end:member': + await context.sync(); + console.log("Property added"); + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-end-read.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml - console.log(`Appointment ends: ${Office.context.mailbox.item.end}`); -'Office.MessageRead#from:member': + + await Word.run(async (context) => { + context.document.properties.customProperties.add("String Property", "Hello World!"); + + await context.sync(); + console.log("Property added"); + }); +Word.CustomPropertyCollection#items:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-from-message-read.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml - const msgFrom = Office.context.mailbox.item.from; - console.log("Message received from: " + msgFrom.displayName + " (" + - msgFrom.emailAddress + ")"); -'Office.MessageRead#getAllInternetHeadersAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/get-internet-headers-message-read.yaml + await Word.run(async (context) => { + const properties: Word.CustomPropertyCollection = context.document.properties.customProperties; + properties.load("key,type,value"); - Office.context.mailbox.item.getAllInternetHeadersAsync(function - (asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Internet headers received successfully"); - if (asyncResult.value.match(/x-preferred-fruit:.*/gim)) { - console.log("Sender's preferred fruit: " + asyncResult.value.match(/x-preferred-fruit:.*/gim)[0].slice(19)); - } else { - console.log("Didn't receive header with sender's preferred fruit"); - } - if (asyncResult.value.match(/x-preferred-vegetable:.*/gim)) { - console.log( - "Sender's preferred vegetable: " + asyncResult.value.match(/x-preferred-vegetable:.*/gim)[0].slice(23) - ); - } else { - console.log("Didn't receive header with sender's preferred vegetable"); - } - } else { - console.log("Error getting internet headers: " + JSON.stringify(asyncResult.error)); - } + await context.sync(); + for (let i = 0; i < properties.items.length; i++) + console.log("Property Name:" + properties.items[i].key + "; Type=" + properties.items[i].type + "; Property Value=" + properties.items[i].value); }); -'Office.MessageRead#getAttachmentContentAsync:member(1)': +Word.CustomXmlPart:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/40-attachments/get-attachment-content.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml - // Gets the attachments of the current message or appointment in read mode. - // The item.attachments call can only be used in read mode. + // Adds a custom XML part. - const attachments = item.attachments; + await Word.run(async (context) => { + const originalXml = + "JuanHongSally"; + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.add(originalXml); + customXmlPart.load("id"); + const xmlBlob = customXmlPart.getXml(); - if (attachments.length <= 0) { - console.log("Mail item has no attachments."); - return; - } + await context.sync(); + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.log("Added custom XML part:", readableXml); - for (let i = 0; i < attachments.length; i++) { - // Log the attachment type and its contents to the console. - item.getAttachmentContentAsync(attachments[i].id, handleAttachmentsCallback); - } -'Office.MessageRead#getEntities:member(1)': + // Store the XML part's ID in a setting so the ID is available to other functions. + const settings: Word.SettingCollection = context.document.settings; + settings.add("ContosoReviewXmlPartId", customXmlPart.id); + + await context.sync(); + }); +Word.CustomXmlPart#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/basic-entities.yaml - - const entities = Office.context.mailbox.item.getEntities(); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml - let entityTypesFound = 0; - if (entities.addresses.length > 0) { - console.warn("physical addresses: "); - console.log(entities.addresses); - entityTypesFound++; - } + // Original XML: + JuanHongSally - if (entities.contacts.length > 0) { - console.warn("contacts: "); - entities.contacts.forEach(function (contact) { console.log(contact.personName); }) - entityTypesFound++; - } - if (entities.emailAddresses.length > 0) { - console.warn("email addresses: "); - console.log(entities.emailAddresses); - entityTypesFound++; - } + // Deletes a custom XML part. - if (entities.meetingSuggestions.length > 0) { - console.warn("meetings suggestions: "); - entities.meetingSuggestions.forEach(function (meetingSuggestion) { console.log(meetingSuggestion.meetingString); }) - entityTypesFound++; - } + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); + await context.sync(); - if (entities.phoneNumbers.length > 0) { - console.warn("phone numbers: "); - entities.phoneNumbers.forEach(function (phoneNumber) { console.log(phoneNumber.originalPhoneString); }) - entityTypesFound++; - } + if (xmlPartIDSetting.value) { + let customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const xmlBlob = customXmlPart.getXml(); + customXmlPart.delete(); + customXmlPart = context.document.customXmlParts.getItemOrNullObject(xmlPartIDSetting.value); - if (entities.taskSuggestions.length > 0) { - console.warn("task suggestions: "); - entities.taskSuggestions.forEach(function (taskSuggestion) { console.log(taskSuggestion.taskString); }) - entityTypesFound++; - } + await context.sync(); - if (entities.urls.length > 0) { - console.warn("URLs: "); - console.log(entities.urls); - entityTypesFound++; - } + if (customXmlPart.isNullObject) { + console.log(`The XML part with the ID ${xmlPartIDSetting.value} has been deleted.`); - if (entityTypesFound == 0) + // Delete the associated setting too. + xmlPartIDSetting.delete(); - { - console.log("No entities found on this item."); - } -'Office.MessageRead#getEntitiesByType:member(1)': + await context.sync(); + } else { + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.error(`This is strange. The XML part with the id ${xmlPartIDSetting.value} wasn't deleted:`, readableXml); + } + } else { + console.warn("Didn't find custom XML part to delete."); + } + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/basic-entities.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml - console.log(Office.context.mailbox.item.getEntitiesByType(Office.MailboxEnums.EntityType.Address)); -'Office.MessageRead#getFilteredEntitiesByName:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/contextual.yaml - // This API would only work when you click on highlighted physical address - that has the word "Way" in it. + // Original XML: JuanHongSally - console.log(Office.context.mailbox.item.getFilteredEntitiesByName("sampleFilterName")); -'Office.MessageRead#getRegExMatches:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/contextual.yaml - // This API would only work when you click on highlighted word "ScriptLab". + // Deletes a custom XML part. - console.log(Office.context.mailbox.item.getRegExMatches()); -'Office.MessageRead#getRegExMatchesByName:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/contextual.yaml + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + await context.sync(); - // This API would only work when you click on highlighted word "ScriptLab". + if (xmlPartIDSetting.value) { + let customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const xmlBlob = customXmlPart.getXml(); + customXmlPart.delete(); + customXmlPart = context.document.customXmlParts.getItemOrNullObject(xmlPartIDSetting.value); - console.log(Office.context.mailbox.item.getRegExMatchesByName("sampleRegexName")); -'Office.MessageRead#getSelectedEntities:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/selected.yaml + await context.sync(); - const entities = Office.context.mailbox.item.getSelectedEntities(); + if (customXmlPart.isNullObject) { + console.log(`The XML part with the ID ${xmlPartIDSetting.value} has been deleted.`); - let entityTypesFound = 0; + // Delete the associated setting too. + xmlPartIDSetting.delete(); - if (entities.addresses.length > 0) { - console.warn("physical addresses: "); - console.log(entities.addresses); - entityTypesFound++; - } + await context.sync(); + } else { + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.error( + `This is strange. The XML part with the id ${xmlPartIDSetting.value} wasn't deleted:`, + readableXml + ); + } + } else { + console.warn("Didn't find custom XML part to delete."); + } + }); +Word.CustomXmlPart#getXml:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml - if (entities.contacts.length > 0) { - console.warn("contacts: "); - entities.contacts.forEach(function (contact) { console.log(contact.personName); }) - entityTypesFound++; - } - if (entities.emailAddresses.length > 0) { - console.warn("email addresses: "); - console.log(entities.emailAddresses); - entityTypesFound++; - } + // Adds a custom XML part. - if (entities.meetingSuggestions.length > 0) { - console.warn("meetings suggestions: "); - entities.meetingSuggestions.forEach(function (meetingSuggestion) { console.log(meetingSuggestion.meetingString); }) - entityTypesFound++; - } + // If you want to populate the CustomXml.namespaceUri property, you must + include the xmlns attribute. - if (entities.phoneNumbers.length > 0) { - console.warn("phone numbers: "); - entities.phoneNumbers.forEach(function (phoneNumber) { console.log(phoneNumber.originalPhoneString); }) - entityTypesFound++; - } + await Word.run(async (context) => { + const originalXml = + "JuanHongSally"; + const customXmlPart = context.document.customXmlParts.add(originalXml); + customXmlPart.load(["id", "namespaceUri"]); + const xmlBlob = customXmlPart.getXml(); - if (entities.taskSuggestions.length > 0) { - console.warn("task suggestions: "); - entities.taskSuggestions.forEach(function (taskSuggestion) { console.log(taskSuggestion.taskString); }) - entityTypesFound++; - } + await context.sync(); - if (entities.urls.length > 0) { - console.warn("URLs: "); - console.log(entities.urls); - entityTypesFound++; - } + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.log(`Added custom XML part with namespace URI ${customXmlPart.namespaceUri}:`, readableXml); - if (entityTypesFound == 0) + // Store the XML part's ID in a setting so the ID is available to other functions. + const settings: Word.SettingCollection = context.document.settings; + settings.add("ContosoReviewXmlPartIdNS", customXmlPart.id); - { - console.error("Open add-in by clicking on a highlighted entity, for this API to return something useful."); - } -'Office.MessageRead#getSelectedRegExMatches:member(1)': + await context.sync(); + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/selected.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml - const matches = Office.context.mailbox.item.getSelectedRegExMatches(); - if (matches) { - console.log(matches); - } + // Adds a custom XML part. - else { - console.error("Open add-in by clicking on a highlighted regex match, for this API to return something useful."); - } -'Office.MessageRead#getSharedPropertiesAsync:member(2)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + await Word.run(async (context) => { + const originalXml = + "JuanHongSally"; + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.add(originalXml); + customXmlPart.load("id"); + const xmlBlob = customXmlPart.getXml(); - if (!Office.context.mailbox.item.getSharedPropertiesAsync) { - console.error("Try this sample on an item from a shared folder."); - return; - } + await context.sync(); + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.log("Added custom XML part:", readableXml); + + // Store the XML part's ID in a setting so the ID is available to other functions. + const settings: Word.SettingCollection = context.document.settings; + settings.add("ContosoReviewXmlPartId", customXmlPart.id); - Office.context.mailbox.item.getSharedPropertiesAsync(function(result) { - console.log(result.value); + await context.sync(); }); -'Office.MessageRead#getSharedPropertiesAsync:member(1)': +Word.CustomXmlPart#insertAttribute:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml - if (!Office.context.mailbox.item.getSharedPropertiesAsync) { - console.error("Try this sample on a message from a shared folder."); - return; - } + // Original XML: JuanHongSally - Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, - function(result) { - if (result.status === Office.AsyncResultStatus.Succeeded && result.value !== "") { - Office.context.mailbox.item.getSharedPropertiesAsync( - { - // Pass auth token along. - asyncContext: result.value - }, - function(result2) { - let sharedProperties = result2.value; - let delegatePermissions = sharedProperties.delegatePermissions; - - // Determine if user has the appropriate permission to do the operation. - if ((delegatePermissions & Office.MailboxEnums.DelegatePermissions.Read) != 0) { - const ewsId = Office.context.mailbox.item.itemId; - const restId = Office.context.mailbox.convertToRestId(ewsId, Office.MailboxEnums.RestVersion.v2_0); - let rest_url = - sharedProperties.targetRestUrl + "/v2.0/users/" + sharedProperties.targetMailbox + "/messages/" + restId; - - $.ajax({ - url: rest_url, - dataType: "json", - headers: { Authorization: "Bearer " + result2.asyncContext } - }) - .done(function(response) { - console.log(response); - }) - .fail(function(error) { - console.error(error); - }); - } - } - ); - } - }); -'Office.MessageRead#internetMessageId:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-internet-message-id-read.yaml - console.log(`Internet message ID: - ${Office.context.mailbox.item.internetMessageId}`); -'Office.MessageRead#itemClass:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-class-read.yaml + // Inserts an attribute into a custom XML part. - console.log(`Item class: ${Office.context.mailbox.item.itemClass}`); -'Office.MessageRead#itemType:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-type.yaml + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + await context.sync(); - const itemType = Office.context.mailbox.item.itemType; + if (xmlPartIDSetting.value) { + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); - switch (itemType) { - case Office.MailboxEnums.ItemType.Appointment: - console.log(`Current item is an ${itemType}.`); - break; - case Office.MailboxEnums.ItemType.Message: - console.log(`Current item is a ${itemType}. A message could be an email, meeting request, meeting response, or meeting cancellation.`); - break; - } -'Office.MessageRead#loadCustomPropertiesAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/15-item-custom-properties/load-set-get-save.yaml + // The insertAttribute method inserts an attribute with the given name and value into the element identified by the xpath parameter. + customXmlPart.insertAttribute( + "/contoso:Reviewers", + { contoso: "http://schemas.contoso.com/review/1.0" }, + "Nation", + "US" + ); + const xmlBlob = customXmlPart.getXml(); + await context.sync(); - Office.context.mailbox.item.loadCustomPropertiesAsync(function (result) { - if (result.status === Office.AsyncResultStatus.Succeeded) { - console.log("Loaded following custom properties:"); - customProps = result.value; - const dataKey = Object.keys(customProps)[0]; - const data = customProps[dataKey]; - for (let propertyName in data) - { - let propertyValue = data[propertyName]; - console.log(`${propertyName}: ${propertyValue}`); - } - } - else { - console.error(`loadCustomPropertiesAsync failed with message ${result.error.message}`); + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.log("Successfully inserted attribute:", readableXml); + } else { + console.warn("Didn't find custom XML part to insert attribute into."); } }); -'Office.MessageRead#location:member': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-location-read.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml - console.log(`Appointment location: - ${Office.context.mailbox.item.location}`); -'Office.MessageRead#normalizedSubject:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-normalized-subject-read.yaml - console.log(`Normalized subject: - ${Office.context.mailbox.item.normalizedSubject}`); -'Office.MessageRead#notificationMessages:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Original XML: + JuanHongSally - const id = $("#notificationId").val(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.ProgressIndicator, - message: "Progress indicator with id = " + id - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Inserts an attribute into a custom XML part. - const id = $("#notificationId").val(); + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); + await context.sync(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Non-persistent informational notification message with id = " + id, - icon: "icon1", - persistent: false - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); + if (xmlPartIDSetting.value) { + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + + // The insertAttribute method inserts an attribute with the given name and value into the element identified by the xpath parameter. + customXmlPart.insertAttribute("/Reviewers", { contoso: "http://schemas.contoso.com/review/1.0" }, "Nation", "US"); + const xmlBlob = customXmlPart.getXml(); + await context.sync(); + + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.log("Successfully inserted attribute:", readableXml); + } else { + console.warn("Didn't find custom XML part to insert attribute into."); + } + }); +Word.CustomXmlPart#insertElement:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml - const id = $("#notificationId").val(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Persistent informational notification message with id = " + id, - icon: "icon1", - persistent: true - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Original XML: JuanHongSally - Office.context.mailbox.item.notificationMessages.getAllAsync(handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml - const id = $("#notificationId").val(); + // Inserts an element into a custom XML part. - Office.context.mailbox.item.notificationMessages.replaceAsync( - id, - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Notification message with id = " + id + " has been replaced with an informational message.", - icon: "icon2", - persistent: false - }, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + await context.sync(); + + if (xmlPartIDSetting.value) { + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); - const id = $("#notificationId").val(); + // The insertElement method inserts the given XML under the parent element identified by the xpath parameter at the provided child position index. + customXmlPart.insertElement( + "/contoso:Reviewers", + "Mark", + { contoso: "http://schemas.contoso.com/review/1.0" }, + 0 + ); + const xmlBlob = customXmlPart.getXml(); + await context.sync(); - Office.context.mailbox.item.notificationMessages.removeAsync(id, - handleResult); -'Office.MessageRead#recurrence:member': + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.log("Successfully inserted element:", readableXml); + } else { + console.warn("Didn't find custom XML part to insert element into."); + } + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-recurrence-read.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml - const recurrence = Office.context.mailbox.item.recurrence; + // Original XML: + JuanHongSally - if (recurrence === undefined) { - console.log("This item is a message but not a meeting request."); - } else if (recurrence === null) { - console.log("This is a single appointment."); - } else { - console.log(JSON.stringify(recurrence)); - } -'Office.MessageRead#sender:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-sender-message-read.yaml - const msgSender = Office.context.mailbox.item.sender; + // Inserts an element into a custom XML part. - console.log("Sender: " + msgSender.displayName + " (" + - msgSender.emailAddress + ")"); -'Office.MessageRead#seriesId:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-series-id.yaml + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); + await context.sync(); - const seriesId = Office.context.mailbox.item.seriesId; + if (xmlPartIDSetting.value) { + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + // The insertElement method inserts the given XML under the parent element identified by the xpath parameter at the provided child position index. + customXmlPart.insertElement( + "/Reviewers", + "Mark", + { contoso: "http://schemas.contoso.com/review/1.0" }, + 0 + ); + const xmlBlob = customXmlPart.getXml(); + await context.sync(); - if (seriesId === undefined) { - console.log("This is a message that's not a meeting request."); - } else if (seriesId === null) { - console.log("This is a single appointment, a parent series, or a meeting request for a series or single meeting."); - } else { - console.log("This is an instance belonging to series with ID " + seriesId); - } -'Office.MessageRead#start:member': + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.log("Successfully inserted element:", readableXml); + } else { + console.warn("Didn't find custom XML part to insert element into."); + } + }); +Word.CustomXmlPart#query:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-start-read.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml - console.log(`Appointment starts: ${Office.context.mailbox.item.start}`); -'Office.MessageRead#subject:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-subject-read.yaml - console.log(`Subject: ${Office.context.mailbox.item.subject}`); -'Office.MessageRead#to:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-to-message-read.yaml + // Original XML: JuanHongSally - const msgTo = Office.context.mailbox.item.to; - const distributionLists = []; + // Queries a custom XML part for elements matching the search terms. - const externalRecipients = []; + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); - const internalRecipients = []; + await context.sync(); - const otherRecipients = []; + if (xmlPartIDSetting.value) { + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const xpathToQueryFor = "/contoso:Reviewers"; + const clientResult = customXmlPart.query(xpathToQueryFor, { + contoso: "http://schemas.contoso.com/review/1.0" + }); - for (let i = 0; i < msgTo.length; i++) { - switch (msgTo[i].recipientType) { - case Office.MailboxEnums.RecipientType.DistributionList: - distributionLists.push(msgTo[i]); - break; - case Office.MailboxEnums.RecipientType.ExternalUser: - externalRecipients.push(msgTo[i]); - break; - case Office.MailboxEnums.RecipientType.User: - internalRecipients.push(msgTo[i]); - break; - case Office.MailboxEnums.RecipientType.Other: - otherRecipients.push(msgTo[i]); + await context.sync(); + + console.log(`Queried custom XML part for ${xpathToQueryFor} and found ${clientResult.value.length} matches:`); + for (let i = 0; i < clientResult.value.length; i++) { + console.log(clientResult.value[i]); } - } + } else { + console.warn("Didn't find custom XML part to query."); + } + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml - if (distributionLists.length > 0) { - console.log("Distribution Lists:"); - distributionLists.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); - } + // Original XML: + JuanHongSally - if (externalRecipients.length > 0) { - console.log("External Recipients:"); - externalRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); - } + // Queries a custom XML part for elements matching the search terms. + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); - if (internalRecipients.length > 0) { - console.log("Internal Recipients:"); - internalRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); - } + await context.sync(); + if (xmlPartIDSetting.value) { + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const xpathToQueryFor = "/Reviewers/Reviewer"; + const clientResult = customXmlPart.query(xpathToQueryFor, { + contoso: "http://schemas.contoso.com/review/1.0" + }); - if (otherRecipients.length > 0) { - console.log("Other Recipients:"); - otherRecipients.forEach((recipient) => console.log(`${recipient.displayName}, ${recipient.emailAddress}`)); - } -'Office.NotificationMessages#addAsync:member(1)': + await context.sync(); + + console.log(`Queried custom XML part for ${xpathToQueryFor} and found ${clientResult.value.length} matches:`); + for (let i = 0; i < clientResult.value.length; i++) { + console.log(clientResult.value[i]); + } + } else { + console.warn("Didn't find custom XML part to query."); + } + }); +Word.CustomXmlPart#setXml:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml - const id = $("#notificationId").val(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.ProgressIndicator, - message: "Progress indicator with id = " + id - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Original XML: JuanHongSally - const id = $("#notificationId").val(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Non-persistent informational notification message with id = " + id, - icon: "icon1", - persistent: false - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Replaces a custom XML part. - const id = $("#notificationId").val(); + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + await context.sync(); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Persistent informational notification message with id = " + id, - icon: "icon1", - persistent: true - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + if (xmlPartIDSetting.value) { + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const originalXmlBlob = customXmlPart.getXml(); + await context.sync(); - const id = $("#notificationId").val(); + let readableXml = addLineBreaksToXML(originalXmlBlob.value); + console.log("Original custom XML part:", readableXml); - const details = - { - type: Office.MailboxEnums.ItemNotificationMessageType.ErrorMessage, - message: "Error notification message with id = " + id - }; - Office.context.mailbox.item.notificationMessages.addAsync(id, details, - handleResult); -'Office.NotificationMessages#getAllAsync:member(1)': + // The setXml method replaces the entire XML part. + customXmlPart.setXml( + "JohnHitomi" + ); + const updatedXmlBlob = customXmlPart.getXml(); + await context.sync(); + + readableXml = addLineBreaksToXML(updatedXmlBlob.value); + console.log("Replaced custom XML part:", readableXml); + } else { + console.warn("Didn't find custom XML part to replace."); + } + }); +Word.CustomXmlPart#id:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml + + + // Adds a custom XML part. + + await Word.run(async (context) => { + const originalXml = + "JuanHongSally"; + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.add(originalXml); + customXmlPart.load("id"); + const xmlBlob = customXmlPart.getXml(); + + await context.sync(); + + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.log("Added custom XML part:", readableXml); + + // Store the XML part's ID in a setting so the ID is available to other functions. + const settings: Word.SettingCollection = context.document.settings; + settings.add("ContosoReviewXmlPartId", customXmlPart.id); - Office.context.mailbox.item.notificationMessages.getAllAsync(handleResult); -'Office.NotificationMessages#removeAsync:member(1)': + await context.sync(); + }); +Word.CustomXmlPart#namespaceUri:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml - const id = $("#notificationId").val(); - Office.context.mailbox.item.notificationMessages.removeAsync(id, - handleResult); -'Office.NotificationMessages#replaceAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/35-notifications/add-getall-remove.yaml + // Original XML: JuanHongSally + + + // Gets the namespace URI from a custom XML part. + + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); - const id = $("#notificationId").val(); + await context.sync(); - Office.context.mailbox.item.notificationMessages.replaceAsync( - id, - { - type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage, - message: "Notification message with id = " + id + " has been replaced with an informational message.", - icon: "icon2", - persistent: false - }, - handleResult); -'Office.Organizer#getAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-organizer-appointment-organizer.yaml + if (xmlPartIDSetting.value) { + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + customXmlPart.load("namespaceUri"); + await context.sync(); - Office.context.mailbox.item.organizer.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const apptOrganizer = asyncResult.value; - console.log("Organizer: " + apptOrganizer.displayName + " (" + apptOrganizer.emailAddress + ")"); + const namespaceUri = customXmlPart.namespaceUri; + console.log(`Namespace URI: ${JSON.stringify(namespaceUri)}`); } else { - console.error(asyncResult.error); + console.warn("Didn't find custom XML part."); } }); -'Office.Recipients#getAsync:member(2)': +Word.CustomXmlPartCollection#add:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-bcc-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml - Office.context.mailbox.item.bcc.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const msgBcc = asyncResult.value; - console.log("Message being blind-copied to:"); - for (let i = 0; i < msgBcc.length; i++) { - console.log(msgBcc[i].displayName + " (" + msgBcc[i].emailAddress + ")"); - } - } else { - console.error(asyncResult.error); - } + + // Adds a custom XML part. + + // If you want to populate the CustomXml.namespaceUri property, you must + include the xmlns attribute. + + await Word.run(async (context) => { + const originalXml = + "JuanHongSally"; + const customXmlPart = context.document.customXmlParts.add(originalXml); + customXmlPart.load(["id", "namespaceUri"]); + const xmlBlob = customXmlPart.getXml(); + + await context.sync(); + + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.log(`Added custom XML part with namespace URI ${customXmlPart.namespaceUri}:`, readableXml); + + // Store the XML part's ID in a setting so the ID is available to other functions. + const settings: Word.SettingCollection = context.document.settings; + settings.add("ContosoReviewXmlPartIdNS", customXmlPart.id); + + await context.sync(); }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-cc-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml - Office.context.mailbox.item.cc.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const msgCc = asyncResult.value; - console.log("Message being copied to:"); - for (let i = 0; i < msgCc.length; i++) { - console.log(msgCc[i].displayName + " (" + msgCc[i].emailAddress + ")"); - } - } else { - console.error(asyncResult.error); - } + + // Adds a custom XML part. + + await Word.run(async (context) => { + const originalXml = + "JuanHongSally"; + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.add(originalXml); + customXmlPart.load("id"); + const xmlBlob = customXmlPart.getXml(); + + await context.sync(); + + const readableXml = addLineBreaksToXML(xmlBlob.value); + console.log("Added custom XML part:", readableXml); + + // Store the XML part's ID in a setting so the ID is available to other functions. + const settings: Word.SettingCollection = context.document.settings; + settings.add("ContosoReviewXmlPartId", customXmlPart.id); + + await context.sync(); }); +Word.CustomXmlPartCollection#getByNamespace:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-optional-attendees-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml - Office.context.mailbox.item.optionalAttendees.getAsync(function(asyncResult) - { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const apptOptionalAttendees = asyncResult.value; - for (let i = 0; i < apptOptionalAttendees.length; i++) { - console.log( - "Optional attendees: " + - apptOptionalAttendees[i].displayName + - " (" + - apptOptionalAttendees[i].emailAddress + - ") - response: " + - apptOptionalAttendees[i].appointmentResponse - ); - } - } else { - console.error(asyncResult.error); - } + + // Original XML: JuanHongSally + + + // Gets the custom XML parts with the specified namespace URI. + + await Word.run(async (context) => { + const namespaceUri = "http://schemas.contoso.com/review/1.0"; + console.log(`Specified namespace URI: ${namespaceUri}`); + const scopedCustomXmlParts: Word.CustomXmlPartScopedCollection = + context.document.customXmlParts.getByNamespace(namespaceUri); + scopedCustomXmlParts.load("items"); + await context.sync(); + + console.log(`Number of custom XML parts found with this namespace: ${!scopedCustomXmlParts.items ? 0 : scopedCustomXmlParts.items.length}`); }); +Word.CustomXmlPartCollection#getItem:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-required-attendees-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml - Office.context.mailbox.item.requiredAttendees.getAsync(function(asyncResult) - { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const apptRequiredAttendees = asyncResult.value; - for (let i = 0; i < apptRequiredAttendees.length; i++) { - console.log( - "Required attendees: " + - apptRequiredAttendees[i].displayName + - " (" + - apptRequiredAttendees[i].emailAddress + - ") - response: " + - apptRequiredAttendees[i].appointmentResponse - ); + + // Original XML: JuanHongSally + + + // Queries a custom XML part for elements matching the search terms. + + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + + await context.sync(); + + if (xmlPartIDSetting.value) { + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const xpathToQueryFor = "/contoso:Reviewers"; + const clientResult = customXmlPart.query(xpathToQueryFor, { + contoso: "http://schemas.contoso.com/review/1.0" + }); + + await context.sync(); + + console.log(`Queried custom XML part for ${xpathToQueryFor} and found ${clientResult.value.length} matches:`); + for (let i = 0; i < clientResult.value.length; i++) { + console.log(clientResult.value[i]); } } else { - console.error(asyncResult.error); + console.warn("Didn't find custom XML part to query."); } }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-to-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml - Office.context.mailbox.item.to.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const msgTo = asyncResult.value; - console.log("Message being sent to:"); - for (let i = 0; i < msgTo.length; i++) { - console.log(msgTo[i].displayName + " (" + msgTo[i].emailAddress + ")"); + + // Original XML: + JuanHongSally + + + // Queries a custom XML part for elements matching the search terms. + + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + const xmlPartIDSetting: Word.Setting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); + + await context.sync(); + + if (xmlPartIDSetting.value) { + const customXmlPart: Word.CustomXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const xpathToQueryFor = "/Reviewers/Reviewer"; + const clientResult = customXmlPart.query(xpathToQueryFor, { + contoso: "http://schemas.contoso.com/review/1.0" + }); + + await context.sync(); + + console.log(`Queried custom XML part for ${xpathToQueryFor} and found ${clientResult.value.length} matches:`); + for (let i = 0; i < clientResult.value.length; i++) { + console.log(clientResult.value[i]); } } else { - console.error(asyncResult.error); + console.warn("Didn't find custom XML part to query."); } }); -'Office.Recipients#setAsync:member(2)': +Word.CustomXmlPartScopedCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-bcc-message-compose.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml - const email = $("#emailBcc") - .val() - .toString(); - const emailArray = [email]; - Office.context.mailbox.item.bcc.setAsync(emailArray, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Succeeded in setting Bcc field."); - } else { - console.error(asyncResult.error); - } - }); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-cc-message-compose.yaml + // Original XML: JuanHongSally - const email = $("#emailCc") - .val() - .toString(); - const emailArray = [email]; - Office.context.mailbox.item.cc.setAsync(emailArray, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Succeeded in setting Cc field."); - } else { - console.error(asyncResult.error); - } + // Gets the custom XML parts with the specified namespace URI. + + await Word.run(async (context) => { + const namespaceUri = "http://schemas.contoso.com/review/1.0"; + console.log(`Specified namespace URI: ${namespaceUri}`); + const scopedCustomXmlParts: Word.CustomXmlPartScopedCollection = + context.document.customXmlParts.getByNamespace(namespaceUri); + scopedCustomXmlParts.load("items"); + await context.sync(); + + console.log(`Number of custom XML parts found with this namespace: ${!scopedCustomXmlParts.items ? 0 : scopedCustomXmlParts.items.length}`); }); +Word.Document:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-optional-attendees-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-change-tracking.yaml - const email = $("#emailOptional") - .val() - .toString(); - const emailArray = [email]; - Office.context.mailbox.item.optionalAttendees.setAsync(emailArray, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Succeeded in setting optional attendees field."); + // Gets the current change tracking mode. + + await Word.run(async (context) => { + const document: Word.Document = context.document; + document.load("changeTrackingMode"); + await context.sync(); + + if (document.changeTrackingMode === Word.ChangeTrackingMode.trackMineOnly) { + console.log("Only my changes are being tracked."); + } else if (document.changeTrackingMode === Word.ChangeTrackingMode.trackAll) { + console.log("Everyone's changes are being tracked."); } else { - console.error(asyncResult.error); + console.log("No changes are being tracked."); } }); +Word.Document#addStyle:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-required-attendees-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - const email = $("#emailRequired") - .val() - .toString(); - const emailArray = [email]; - Office.context.mailbox.item.requiredAttendees.setAsync(emailArray, - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Succeeded in setting required attendees field."); - } else { - console.error(asyncResult.error); + // Adds a new style. + + await Word.run(async (context) => { + const newStyleName = (document.getElementById("new-style-name") as HTMLInputElement).value; + if (newStyleName == "") { + console.warn("Enter a style name to add."); + return; } - }); - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-set-to-message-compose.yaml - const email = $("#emailTo") - .val() - .toString(); - const emailArray = [email]; + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(newStyleName); + style.load(); + await context.sync(); - Office.context.mailbox.item.to.setAsync(emailArray, function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Succeeded in setting To field."); - } else { - console.error(asyncResult.error); + if (!style.isNullObject) { + console.warn( + `There's an existing style with the same name '${newStyleName}'! Please provide another style name.` + ); + return; } + + const newStyleType = ((document.getElementById("new-style-type") as HTMLSelectElement).value as unknown) as Word.StyleType; + context.document.addStyle(newStyleName, newStyleType); + await context.sync(); + + console.log(newStyleName + " has been added to the style list."); }); -'Office.Recurrence#getAsync:member(1)': +Word.Document#close:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/save-close.yaml - Office.context.mailbox.item.recurrence.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const recurrence = asyncResult.value; - if (recurrence === null) { - console.log("This is a single appointment."); - } else { - console.log(`Recurrence pattern: ${JSON.stringify(recurrence)}`); - } - } else { - console.error(asyncResult.error); - } + + // Closes the document with default behavior + + // for current state of the document. + + await Word.run(async (context) => { + context.document.close(); }); -'Office.Recurrence#setAsync:member(1)': +Word.Document#compare:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/50-recurrence/get-set-recurrence-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/compare-documents.yaml - // Important: Can only set the recurrence pattern of an appointment series. + // Compares the current document with a specified external document. - const currentDate = new Date(); + await Word.run(async (context) => { + // Absolute path of an online or local document. + const filePath = (document.getElementById("filePath") as HTMLInputElement).value; + // Options that configure the compare operation. + const options: Word.DocumentCompareOptions = { + compareTarget: Word.CompareTarget.compareTargetCurrent, + detectFormatChanges: false + // Other options you choose... + }; + context.document.compare(filePath, options); - let seriesTimeObject: Office.SeriesTime; + await context.sync(); - // Set series start date to tomorrow. + console.log("Differences shown in the current document."); + }); +Word.Document#getContentControls:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml - seriesTimeObject.setStartDate(currentDate.getFullYear(), - currentDate.getMonth(), currentDate.getDay() + 1); - // Set series end date to one year from now. + // Toggles the isChecked property on all checkbox content controls. - seriesTimeObject.setEndDate(currentDate.getFullYear() + 1, - currentDate.getMonth() + 1, currentDate.getDay()); + await Word.run(async (context) => { + let contentControls = context.document.getContentControls({ + types: [Word.ContentControlType.checkBox] + }); + contentControls.load("items"); - // Set start time to 1:30 PM. + await context.sync(); - seriesTimeObject.setStartTime(13, 30); + const length = contentControls.items.length; + console.log(`Number of checkbox content controls: ${length}`); - // Set duration to 30 minutes. + if (length <= 0) { + return; + } - seriesTimeObject.setDuration(30); + const checkboxContentControls = []; + for (let i = 0; i < length; i++) { + let contentControl = contentControls.items[i]; + contentControl.load("id,checkboxContentControl/isChecked"); + checkboxContentControls.push(contentControl); + } + await context.sync(); - const pattern: Office.Recurrence = { - seriesTime: seriesTimeObject, - recurrenceType: Office.MailboxEnums.RecurrenceType.Yearly, - recurrenceProperties: { - interval: 1, - dayOfWeek: Office.MailboxEnums.Days.Tue, - weekNumber: Office.MailboxEnums.WeekNumber.Second, - month: Office.MailboxEnums.Month.Sep - }, - recurrenceTimeZone: { name: Office.MailboxEnums.RecurrenceTimeZone.PacificStandardTime } - }; + console.log("isChecked state before:"); + const updatedCheckboxContentControls = []; + for (let i = 0; i < checkboxContentControls.length; i++) { + const currentCheckboxContentControl = checkboxContentControls[i]; + const isCheckedBefore = currentCheckboxContentControl.checkboxContentControl.isChecked; + console.log(`id: ${currentCheckboxContentControl.id} ... isChecked: ${isCheckedBefore}`); + + currentCheckboxContentControl.checkboxContentControl.isChecked = !isCheckedBefore; + currentCheckboxContentControl.load("id,checkboxContentControl/isChecked"); + updatedCheckboxContentControls.push(currentCheckboxContentControl); + } + await context.sync(); - Office.context.mailbox.item.recurrence.setAsync(pattern, (asyncResult) => { - if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Failed to set recurrence. Error: ${asyncResult.error.message}`); - return; + console.log("isChecked state after:"); + for (let i = 0; i < updatedCheckboxContentControls.length; i++) { + const currentCheckboxContentControl = updatedCheckboxContentControls[i]; + console.log( + `id: ${currentCheckboxContentControl.id} ... isChecked: ${currentCheckboxContentControl.checkboxContentControl.isChecked}` + ); } - console.log(`Succeeded in setting recurrence pattern ${JSON.stringify(pattern)}`); }); -'Office.RoamingSettings#get:member(1)': +Word.Document#getParagraphByUniqueLocalId:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/10-roaming-settings/roaming-settings.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onadded-event.yaml - const settingName = $("#settingName").val(); - - const settingValue = Office.context.roamingSettings.get(settingName); - $("#settingValue").val(settingValue); + await Word.run(async (context) => { + const paragraphId = (document.getElementById("paragraph-id") as HTMLInputElement).value; + const paragraph: Word.Paragraph = context.document.getParagraphByUniqueLocalId(paragraphId); + paragraph.load(); + await paragraph.context.sync(); - console.log(`The value of setting "${settingName}" is "${settingValue}".`); -'Office.RoamingSettings#saveAsync:member(1)': + console.log(paragraph); + }); +Word.Document#getStyles:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/10-roaming-settings/roaming-settings.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Save settings in the mailbox to make it available in future sessions. - Office.context.roamingSettings.saveAsync(function(result) { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - } else { - console.log(`Settings saved with status: ${result.status}`); - } + // Gets the number of available styles stored with the document. + + await Word.run(async (context) => { + const styles: Word.StyleCollection = context.document.getStyles(); + const count = styles.getCount(); + await context.sync(); + + console.log(`Number of styles: ${count.value}`); }); -'Office.RoamingSettings#set:member(1)': +Word.Document#importStylesFromJson:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/10-roaming-settings/roaming-settings.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-custom-style.yaml - const settingName = $("#settingName").val(); - const settingValue = $("#settingValue").val(); + // Imports styles from JSON. - Office.context.roamingSettings.set(settingName, settingValue); + await Word.run(async (context) => { + const str = + '{"styles":[{"baseStyle":"Default Paragraph Font","builtIn":false,"inUse":true,"linked":false,"nameLocal":"NewCharStyle","priority":2,"quickStyle":true,"type":"Character","unhideWhenUsed":false,"visibility":false,"paragraphFormat":null,"font":{"name":"DengXian Light","size":16.0,"bold":true,"italic":false,"color":"#F1A983","underline":"None","subscript":false,"superscript":true,"strikeThrough":true,"doubleStrikeThrough":false,"highlightColor":null,"hidden":false},"shading":{"backgroundPatternColor":"#FF0000"}},{"baseStyle":"Normal","builtIn":false,"inUse":true,"linked":false,"nextParagraphStyle":"NewParaStyle","nameLocal":"NewParaStyle","priority":1,"quickStyle":true,"type":"Paragraph","unhideWhenUsed":false,"visibility":false,"paragraphFormat":{"alignment":"Centered","firstLineIndent":0.0,"keepTogether":false,"keepWithNext":false,"leftIndent":72.0,"lineSpacing":18.0,"lineUnitAfter":0.0,"lineUnitBefore":0.0,"mirrorIndents":false,"outlineLevel":"OutlineLevelBodyText","rightIndent":72.0,"spaceAfter":30.0,"spaceBefore":30.0,"widowControl":true},"font":{"name":"DengXian","size":14.0,"bold":true,"italic":true,"color":"#8DD873","underline":"Single","subscript":false,"superscript":false,"strikeThrough":false,"doubleStrikeThrough":true,"highlightColor":null,"hidden":false},"shading":{"backgroundPatternColor":"#00FF00"}},{"baseStyle":"Table Normal","builtIn":false,"inUse":true,"linked":false,"nextParagraphStyle":"NewTableStyle","nameLocal":"NewTableStyle","priority":100,"type":"Table","unhideWhenUsed":false,"visibility":false,"paragraphFormat":{"alignment":"Left","firstLineIndent":0.0,"keepTogether":false,"keepWithNext":false,"leftIndent":0.0,"lineSpacing":12.0,"lineUnitAfter":0.0,"lineUnitBefore":0.0,"mirrorIndents":false,"outlineLevel":"OutlineLevelBodyText","rightIndent":0.0,"spaceAfter":0.0,"spaceBefore":0.0,"widowControl":true},"font":{"name":"DengXian","size":20.0,"bold":false,"italic":true,"color":"#D86DCB","underline":"None","subscript":false,"superscript":false,"strikeThrough":false,"doubleStrikeThrough":false,"highlightColor":null,"hidden":false},"tableStyle":{"allowBreakAcrossPage":true,"alignment":"Left","bottomCellMargin":0.0,"leftCellMargin":0.08,"rightCellMargin":0.08,"topCellMargin":0.0,"cellSpacing":0.0},"shading":{"backgroundPatternColor":"#60CAF3"}}]}'; + const styles = context.document.importStylesFromJson(str); - console.log(`Setting "${settingName}" set to value "${settingValue}".`); -'Office.Sensitivity#getAsync:member(2)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/calendar-properties-apis.yaml + // If you'd like to set how conflicting styles are handled, use the importedStylesConflictBehavior parameter that was introduced in the Desktop 1.1 requirement set. "Ignore" is the default. + ////const styles = context.document.importStylesFromJson(str, Word.ImportedStylesConflictBehavior.Ignore); - Office.context.mailbox.item.sensitivity.getAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("Sensitivity: " + asyncResult.value); - } else { - console.log("Failed to get sensitivity: " + JSON.stringify(asyncResult.error)); - } + await context.sync(); + console.log("Styles imported from JSON:", styles); }); -'Office.Sensitivity#setAsync:member(1)': +Word.Document#insertFileFromBase64:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/calendar-properties-apis.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-external-document.yaml - Office.context.mailbox.item.sensitivity.setAsync( - Office.MailboxEnums.AppointmentSensitivityType.Confidential, - function callback(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Failed) { - console.log("Failed to set appointment sensitivity: " + JSON.stringify(asyncResult.error)); - } else { - console.log("Successfully set appointment sensitivity."); - } - } - ); -'Office.SensitivityLabel#getAsync:member(2)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/60-sensitivity-label/sensitivity-label.yaml - // This snippet gets the current mail item's sensitivity label. + // Inserts content (applying selected settings) from another document passed + in as a Base64-encoded string. - Office.context.sensitivityLabelsCatalog.getIsEnabledAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded && asyncResult.value == true) { - Office.context.mailbox.item.sensitivityLabel.getAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(asyncResult.value); - } else { - console.log("Action failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("Action failed with error: " + asyncResult.error.message); - } + await Word.run(async (context) => { + // Use the Base64-encoded string representation of the selected .docx file. + context.document.insertFileFromBase64(externalDocument, "Replace", { + importTheme: true, + importStyles: true, + importParagraphSpacing: true, + importPageColor: true, + importChangeTrackingMode: true, + importCustomProperties: true, + importCustomXmlParts: true, + importDifferentOddEvenPages: true + }); + await context.sync(); }); -'Office.SensitivityLabel#setAsync:member(2)': +Word.Document#save:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/60-sensitivity-label/sensitivity-label.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/save-close.yaml - // This snippet sets the sensitivity label on the current mail item. - Office.context.sensitivityLabelsCatalog.getIsEnabledAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded && asyncResult.value == true) { - Office.context.sensitivityLabelsCatalog.getAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const catalog = asyncResult.value; - if (catalog.length > 0) { - var id = catalog[0].id; - Office.context.mailbox.item.sensitivityLabel.setAsync(id, (asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(asyncResult.status); - } else { - console.log("Action failed with error: " + asyncResult.error.message); - } - }); - } - else { - console.log("Catalog list is empty"); - } - } else { - console.log("Action failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("Action failed with error: " + asyncResult.error.message); - } - }); -'Office.SensitivityLabelsCatalog#getAsync:member(2)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/60-sensitivity-label/sensitivity-labels-catalog.yaml + // Saves the document with default behavior - // This snippet gets all available sensitivity labels from the catalog. + // for current state of the document. - Office.context.sensitivityLabelsCatalog.getIsEnabledAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded && asyncResult.value == true) { - Office.context.sensitivityLabelsCatalog.getAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - const catalog = asyncResult.value; - console.log("Sensitivity Labels Catalog:"); - console.log(JSON.stringify(catalog)); - } else { - console.log("Action failed with error: " + asyncResult.error.message); - } - }); - } else { - console.log("Action failed with error: " + asyncResult.error.message); - } + await Word.run(async (context) => { + context.document.save(); + await context.sync(); }); -'Office.SensitivityLabelsCatalog#getIsEnabledAsync:member(2)': +Word.Document#activeWindow:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/60-sensitivity-label/sensitivity-labels-catalog.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml - // This snippet determines if the sensitivity labels catalog is enabled on - the current mailbox. - Office.context.sensitivityLabelsCatalog.getIsEnabledAsync((asyncResult) => { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log(asyncResult.value); - } else { - console.log("Action failed with error: " + asyncResult.error.message); - } - }); -'Office.SessionData#clearAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + await Word.run(async (context) => { + // Gets the first paragraph of each page. + console.log("Getting first paragraph of each page..."); - Office.context.mailbox.item.sessionData.clearAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("sessionData.clearAsync succeeded"); - } else { - console.log("Failed to clear sessionData. Error: " + JSON.stringify(asyncResult.error)); - } - }); -'Office.SessionData#getAllAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + // Get the active window. + const activeWindow: Word.Window = context.document.activeWindow; + activeWindow.load(); - Office.context.mailbox.item.sessionData.getAllAsync(function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("The sessionData is " + JSON.stringify(asyncResult.value)); - } else { - console.log("Failed to get all sessionData. Error: " + JSON.stringify(asyncResult.error)); + // Get the active pane. + const activePane: Word.Pane = activeWindow.activePane; + activePane.load(); + + // Get all pages. + const pages: Word.PageCollection = activePane.pages; + pages.load(); + + await context.sync(); + + // Get page index and paragraphs of each page. + const pagesIndexes = []; + const pagesNumberOfParagraphs = []; + const pagesFirstParagraphText = []; + for (let i = 0; i < pages.items.length; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); + + const paragraphs = page.getRange().paragraphs; + paragraphs.load("items/length"); + pagesNumberOfParagraphs.push(paragraphs); + + const firstParagraph = paragraphs.getFirst(); + firstParagraph.load("text"); + pagesFirstParagraphText.push(firstParagraph); } - }); -'Office.SessionData#getAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml - Office.context.mailbox.item.sessionData.getAsync( - "Date", - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("The sessionData value is " + JSON.stringify(asyncResult.value)); - } else { - console.log("Failed to get sessionData. Error: " + JSON.stringify(asyncResult.error)); + await context.sync(); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Page index: ${pagesIndexes[i].index}`); + console.log(`Number of paragraphs: ${pagesNumberOfParagraphs[i].items.length}`); + console.log("First paragraph's text:", pagesFirstParagraphText[i].text); } }); -'Office.SessionData#removeAsync:member(1)': +Word.Document#changeTrackingMode:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-change-tracking.yaml - Office.context.mailbox.item.sessionData.removeAsync( - "Date", - function callback(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("sessionData.removeAsync succeeded"); - } else { - console.log("Failed to remove sessionData. Error: " + JSON.stringify(asyncResult.error)); - } - } - ); -'Office.SessionData#setAsync:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml - Office.context.mailbox.item.sessionData.setAsync( - "Date", - "7/24/2020", - function(asyncResult) { - if (asyncResult.status === Office.AsyncResultStatus.Succeeded) { - console.log("sessionData.setAsync succeeded"); + // Gets the current change tracking mode. + + await Word.run(async (context) => { + const document: Word.Document = context.document; + document.load("changeTrackingMode"); + await context.sync(); + + if (document.changeTrackingMode === Word.ChangeTrackingMode.trackMineOnly) { + console.log("Only my changes are being tracked."); + } else if (document.changeTrackingMode === Word.ChangeTrackingMode.trackAll) { + console.log("Everyone's changes are being tracked."); } else { - console.log("Failed to set sessionData. Error: " + JSON.stringify(asyncResult.error)); + console.log("No changes are being tracked."); } }); -'Office.Time#getAsync:member(2)': +Word.Document#onAnnotationClicked:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - Office.context.mailbox.item.start.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; - } - console.log(`Appointment starts: ${result.value}`); + + // Registers event handlers. + + await Word.run(async (context) => { + eventContexts[0] = context.document.onParagraphAdded.add(paragraphChanged); + eventContexts[1] = context.document.onParagraphChanged.add(paragraphChanged); + + eventContexts[2] = context.document.onAnnotationClicked.add(onClickedHandler); + eventContexts[3] = context.document.onAnnotationHovered.add(onHoveredHandler); + eventContexts[4] = context.document.onAnnotationInserted.add(onInsertedHandler); + eventContexts[5] = context.document.onAnnotationRemoved.add(onRemovedHandler); + eventContexts[6] = context.document.onAnnotationPopupAction.add(onPopupActionHandler); + + await context.sync(); + + console.log("Event handlers registered."); }); -'Office.Time#setAsync:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-start-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - const start = new Date(); // Represents current date and time. - start.setDate(start.getDate() + 2); // Add 2 days to current date. + async function onClickedHandler(args: Word.AnnotationClickedEventArgs) { + await Word.run(async (context) => { + const annotation: Word.Annotation = context.document.getAnnotationById(args.id); + annotation.load("critiqueAnnotation"); - Office.context.mailbox.item.start.setAsync(start, (result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Action failed with message ${result.error.message}`); - return; - } - console.log(`Successfully set start date and time to ${start}`); - }); + await context.sync(); + + console.log(`AnnotationClicked: ID ${args.id}:`, annotation.critiqueAnnotation.critique); + }); + } +Word.Document#onAnnotationHovered:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-end-appointment-organizer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - Office.context.mailbox.item.start.getAsync((result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Get start date failed with message ${result.error.message}`); - return; - } - const end = result.value; // Set end to current start date and time. - end.setDate(end.getDate() + 1); // Set end as 1 day later than start date. - Office.context.mailbox.item.end.setAsync(end, (result) => { - if (result.status !== Office.AsyncResultStatus.Succeeded) { - console.error(`Set end date failed with message ${result.error.message}`); - return; - } - console.log(`Successfully set end date and time to ${end}`); - }); + // Registers event handlers. + + await Word.run(async (context) => { + eventContexts[0] = context.document.onParagraphAdded.add(paragraphChanged); + eventContexts[1] = context.document.onParagraphChanged.add(paragraphChanged); + + eventContexts[2] = context.document.onAnnotationClicked.add(onClickedHandler); + eventContexts[3] = context.document.onAnnotationHovered.add(onHoveredHandler); + eventContexts[4] = context.document.onAnnotationInserted.add(onInsertedHandler); + eventContexts[5] = context.document.onAnnotationRemoved.add(onRemovedHandler); + eventContexts[6] = context.document.onAnnotationPopupAction.add(onPopupActionHandler); + + await context.sync(); + + console.log("Event handlers registered."); }); -'PowerPoint.Presentation#getSelectedShapes:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // Arranges the selected shapes in a line from left to right. - await PowerPoint.run(async (context) => { - const shapes = context.presentation.getSelectedShapes(); - const shapeCount = shapes.getCount(); - shapes.load("items"); - await context.sync(); - let maxHeight = 0; - shapes.items.map((shape) => { - shape.load("width,height"); - }); - await context.sync(); - shapes.items.map((shape) => { - shape.left = currentLeft; - shape.top = currentTop; - currentLeft += shape.width; - if (shape.height > maxHeight) maxHeight = shape.height; + async function onHoveredHandler(args: Word.AnnotationHoveredEventArgs) { + await Word.run(async (context) => { + const annotation: Word.Annotation = context.document.getAnnotationById(args.id); + annotation.load("critiqueAnnotation"); + + await context.sync(); + + console.log(`AnnotationHovered: ID ${args.id}:`, annotation.critiqueAnnotation.critique); }); - await context.sync(); - currentLeft = 0; - if (currentTop > slideHeight - 200) currentTop = 0; - }); + } +Word.Document#onAnnotationInserted:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // Gets the shapes you selected on the slide and displays their IDs on the - task pane. - await PowerPoint.run(async (context) => { - let finalTable = ""; - const shapes = context.presentation.getSelectedShapes(); - const shapeCount = shapes.getCount(); - await context.sync(); - finalTable += "
getSelectedShapes.getCount returned:" + shapeCount.value + "
"; - finalTable += - "
"; - shapes.load("items"); + // Registers event handlers. + + await Word.run(async (context) => { + eventContexts[0] = context.document.onParagraphAdded.add(paragraphChanged); + eventContexts[1] = context.document.onParagraphChanged.add(paragraphChanged); + + eventContexts[2] = context.document.onAnnotationClicked.add(onClickedHandler); + eventContexts[3] = context.document.onAnnotationHovered.add(onHoveredHandler); + eventContexts[4] = context.document.onAnnotationInserted.add(onInsertedHandler); + eventContexts[5] = context.document.onAnnotationRemoved.add(onRemovedHandler); + eventContexts[6] = context.document.onAnnotationPopupAction.add(onPopupActionHandler); + await context.sync(); - shapes.items.map((shape, index) => { - finalTable += ""; - }); - finalTable += "
IndexId
" + index + "" + shape.id + "
"; - $("#outputSpan").empty(); - $("#outputSpan").append(finalTable); + + console.log("Event handlers registered."); }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // Saves which shapes are selected so that they can be reselected later. - await PowerPoint.run(async (context) => { - context.presentation.load("slides"); - await context.sync(); - const slides = context.presentation.getSelectedSlides(); - const slideCount = slides.getCount(); - slides.load("items"); - await context.sync(); - savedSlideSelection = []; - slides.items.map((slide) => { - savedSlideSelection.push(slide.id); + async function onInsertedHandler(args: Word.AnnotationInsertedEventArgs) { + await Word.run(async (context) => { + const annotations = []; + for (let i = 0; i < args.ids.length; i++) { + let annotation: Word.Annotation = context.document.getAnnotationById(args.ids[i]); + annotation.load("id,critiqueAnnotation"); + + annotations.push(annotation); + } + + await context.sync(); + + for (let annotation of annotations) { + console.log(`AnnotationInserted: ID ${annotation.id}:`, annotation.critiqueAnnotation.critique); + } }); - const shapes = context.presentation.getSelectedShapes(); - const shapeCount = shapes.getCount(); - shapes.load("items"); + } +Word.Document#onAnnotationPopupAction:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml + + + // Registers event handlers. + + await Word.run(async (context) => { + eventContexts[0] = context.document.onParagraphAdded.add(paragraphChanged); + eventContexts[1] = context.document.onParagraphChanged.add(paragraphChanged); + + eventContexts[2] = context.document.onAnnotationClicked.add(onClickedHandler); + eventContexts[3] = context.document.onAnnotationHovered.add(onHoveredHandler); + eventContexts[4] = context.document.onAnnotationInserted.add(onInsertedHandler); + eventContexts[5] = context.document.onAnnotationRemoved.add(onRemovedHandler); + eventContexts[6] = context.document.onAnnotationPopupAction.add(onPopupActionHandler); + await context.sync(); - shapes.items.map((shape) => { - savedShapeSelection.push(shape.id); - }); + + console.log("Event handlers registered."); }); -'PowerPoint.Presentation#getSelectedSlides:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // Gets the selected slides and displays their IDs on the task pane. - await PowerPoint.run(async (context) => { - let finalTable = ""; - context.presentation.load("slides"); - await context.sync(); - const allSlidesList = {}; - const allSlidesCount = context.presentation.slides.getCount(); - context.presentation.slides.load("items"); - await context.sync(); - let allSlideItems = context.presentation.slides.items; - allSlideItems.map((slide, index) => { - allSlidesList[slide.id] = `Slide ${index + 1}`; + async function onPopupActionHandler(args: + Word.AnnotationPopupActionEventArgs) { + await Word.run(async (context) => { + let message = `AnnotationPopupAction: ID ${args.id} = `; + if (args.action === "Accept") { + message += `Accepted: ${args.critiqueSuggestion}`; + } else { + message += "Rejected"; + } + + console.log(message); }); + } +Word.Document#onAnnotationRemoved:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml + + + // Registers event handlers. + + await Word.run(async (context) => { + eventContexts[0] = context.document.onParagraphAdded.add(paragraphChanged); + eventContexts[1] = context.document.onParagraphChanged.add(paragraphChanged); + + eventContexts[2] = context.document.onAnnotationClicked.add(onClickedHandler); + eventContexts[3] = context.document.onAnnotationHovered.add(onHoveredHandler); + eventContexts[4] = context.document.onAnnotationInserted.add(onInsertedHandler); + eventContexts[5] = context.document.onAnnotationRemoved.add(onRemovedHandler); + eventContexts[6] = context.document.onAnnotationPopupAction.add(onPopupActionHandler); - if ($("#id-check-usenative").is(":checked")) { - context.presentation.load("tags"); - } - const slides = context.presentation.getSelectedSlides(); - const slideCount = slides.getCount(); - slides.load("items"); await context.sync(); - finalTable += "
getSelectedSlides.getCount returned:" + slideCount.value + "
"; - finalTable += - "
"; - slides.items.map((slide, index) => { - finalTable += ""; - }); - finalTable += "
IndexId
" + index + " - " + allSlidesList[slide.id] + "" + slide.id + "
"; - $("#outputSpan").empty(); - $("#outputSpan").append(finalTable); + + console.log("Event handlers registered."); }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // Saves which slides are currently selected so they can be reselected - later. - await PowerPoint.run(async (context) => { - let finalTable = ""; - context.presentation.load("slides"); - await context.sync(); - const slides = context.presentation.getSelectedSlides(); - const slideCount = slides.getCount(); - await context.sync(); - finalTable += "
getSelectedSlides.getCount returned:" + slideCount.value + "
"; - finalTable += - "
"; - savedSlideSelection = []; - slides.load("items"); - await context.sync(); - slides.items.map((slide, index) => { - finalTable += ""; - savedSlideSelection.push(slide.id); + async function onRemovedHandler(args: Word.AnnotationRemovedEventArgs) { + await Word.run(async (context) => { + for (let id of args.ids) { + console.log(`AnnotationRemoved: ID ${id}`); + } }); - finalTable += "
IndexId
" + index + "" + slide.id + "
"; - $("#outputSpan").empty(); - $("#outputSpan").append(finalTable); - }); -'PowerPoint.Presentation#getSelectedTextRange:member(1)': + } +Word.Document#onContentControlAdded:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onadded-event.yaml - // Gets the selected text range and prints data about the range on the task - pane. - await PowerPoint.run(async (context) => { - const textRange = context.presentation.getSelectedTextRange(); - try { - await context.sync(); - } catch (error) { - console.warn("You must select only one range of text for this action to work."); - return; - } - textRange.load("text"); - textRange.load("start"); - textRange.load("length"); + // Registers the onAdded event handler on the document. + + await Word.run(async (context) => { + eventContext = context.document.onContentControlAdded.add(contentControlAdded); await context.sync(); - let txtHtml = textRange.text; - txtHtml = txtHtml.replace(/\n/g, "
"); - txtHtml = txtHtml.replace(/\r/g, "
"); - txtHtml = txtHtml.replace(/\v/g, "
"); - let txtExplained = textRange.text; - txtExplained = txtExplained.replace(/\n/g, "NL"); - txtExplained = txtExplained.replace(/\r/g, "CR"); - txtExplained = txtExplained.replace(/\v/g, "VV"); - let finalTable = ""; - finalTable += - "
"; - finalTable += ""; - finalTable += ""; - finalTable += ""; - finalTable += ""; - finalTable += ""; - finalTable += "
IndexId
Raw" + textRange.text + "
Html" + txtHtml + "
Exp" + txtExplained + "
Start" + textRange.start + "
Length" + textRange.length + "
"; - $("#outputSpan").empty(); - $("#outputSpan").append(finalTable); + + console.log("Added event handler for when content controls are added."); }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onadded-event.yaml - // Sets the range selection to the range that was saved previously. - await PowerPoint.run(async (context) => { - const slide1 = context.presentation.slides.getItem(savedTextSlideSelection[0]); - const shape1 = slide1.shapes.getItem(savedTextShapeSelection[0]); - const textRange = shape1.textFrame.textRange.getSubstring(savedTextTextRangeStart, savedTextTextRangeLength); - textRange.setSelected(); + async function contentControlAdded(event: Word.ContentControlAddedEventArgs) + { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. IDs of content controls that were added:`, event.ids); + }); + } +Word.Document#onParagraphAdded:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onadded-event.yaml + + + // Registers the onParagraphAdded event handler on the document. + + await Word.run(async (context) => { + eventContext = context.document.onParagraphAdded.add(paragraphAdded); await context.sync(); + + console.log("Added event handler for when paragraphs are added."); }); -'PowerPoint.Presentation#insertSlidesFromBase64:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/insert-slides.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onadded-event.yaml + + + async function paragraphAdded(event: Word.ParagraphAddedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.type} event detected. IDs of paragraphs that were added:`, event.uniqueLocalIds); + }); + } +Word.Document#onParagraphChanged:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onchanged-event.yaml + + + // Registers the onParagraphChanged event handler on the document. - await PowerPoint.run(async function(context) { - const selectedSlideID = await getSelectedSlideID(); + await Word.run(async (context) => { + eventContext = context.document.onParagraphChanged.add(paragraphChanged); + await context.sync(); - context.presentation.insertSlidesFromBase64(chosenFileBase64, { - formatting: PowerPoint.InsertSlideFormatting.useDestinationTheme, - targetSlideId: selectedSlideID + "#" - }); - await context.sync(); + console.log("Added event handler for when content is changed in paragraphs."); }); -'PowerPoint.Presentation#setSelectedSlides:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onchanged-event.yaml - // Sets selection to the slides that were saved. - await PowerPoint.run(async (context) => { - context.presentation.setSelectedSlides(savedSlideSelection); - await context.sync(); - }); + async function paragraphChanged(event: Word.ParagraphChangedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.type} event detected. IDs of paragraphs where content was changed:`, event.uniqueLocalIds); + }); + } +Word.Document#onParagraphDeleted:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/ondeleted-event.yaml - // Selects slides 2, 4, and 5. - await PowerPoint.run(async (context) => { - context.presentation.load("slides"); - await context.sync(); - const slide2 = context.presentation.slides.getItemAt(1); - const slide4 = context.presentation.slides.getItemAt(3); - const slide5 = context.presentation.slides.getItemAt(4); - slide2.load("id"); - slide4.load("id"); - slide5.load("id"); - try { - await context.sync(); - } catch (error) { - console.warn("This action requires at least 5 slides in the presentation."); - return; - } - await context.sync(); - context.presentation.setSelectedSlides([slide2.id, slide4.id, slide5.id]); + // Registers the onParagraphDeleted event handler on the document. + + await Word.run(async (context) => { + eventContext = context.document.onParagraphDeleted.add(paragraphDeleted); await context.sync(); + + console.log("Added event handlers for when paragraphs are deleted."); }); -'PowerPoint.Shape#fill:member': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/ondeleted-event.yaml - // Changes the selected shapes fill color to red. - await PowerPoint.run(async (context) => { - const shapes = context.presentation.getSelectedShapes(); - const shapeCount = shapes.getCount(); - shapes.load("items"); - await context.sync(); - shapes.items.map((shape) => { - shape.fill.setSolidColor("red"); + async function paragraphDeleted(event: Word.ParagraphDeletedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.type} event detected. IDs of paragraphs that were deleted:`, event.uniqueLocalIds); }); - await context.sync(); - }); -'PowerPoint.Shape#height:member': + } +Word.Document#properties:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/get-built-in-properties.yaml - // Arranges the selected shapes in a line from left to right. - await PowerPoint.run(async (context) => { - const shapes = context.presentation.getSelectedShapes(); - const shapeCount = shapes.getCount(); - shapes.load("items"); - await context.sync(); - let maxHeight = 0; - shapes.items.map((shape) => { - shape.load("width,height"); - }); - await context.sync(); - shapes.items.map((shape) => { - shape.left = currentLeft; - shape.top = currentTop; - currentLeft += shape.width; - if (shape.height > maxHeight) maxHeight = shape.height; - }); - await context.sync(); - currentLeft = 0; - if (currentTop > slideHeight - 200) currentTop = 0; + await Word.run(async (context) => { + const builtInProperties: Word.DocumentProperties = context.document.properties; + builtInProperties.load("*"); // Let's get all! + + await context.sync(); + console.log(JSON.stringify(builtInProperties, null, 4)); }); -'PowerPoint.Shape#left:member': +Word.Document#settings:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-settings.yaml - // Arranges the selected shapes in a line from left to right. - await PowerPoint.run(async (context) => { - const shapes = context.presentation.getSelectedShapes(); - const shapeCount = shapes.getCount(); - shapes.load("items"); - await context.sync(); - let maxHeight = 0; - shapes.items.map((shape) => { - shape.load("width,height"); - }); - await context.sync(); - shapes.items.map((shape) => { - shape.left = currentLeft; - shape.top = currentTop; - currentLeft += shape.width; - if (shape.height > maxHeight) maxHeight = shape.height; - }); + // Gets all custom settings this add-in set on this document. + + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + settings.load("items"); await context.sync(); - currentLeft = 0; - if (currentTop > slideHeight - 200) currentTop = 0; + + if (settings.items.length == 0) { + console.log("There are no settings."); + } else { + console.log("All settings:"); + for (let i = 0; i < settings.items.length; i++) { + console.log(settings.items[i]); + } + } }); -'PowerPoint.Shape#top:member': +Word.Document#windows:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml - // Arranges the selected shapes in a line from left to right. - await PowerPoint.run(async (context) => { - const shapes = context.presentation.getSelectedShapes(); - const shapeCount = shapes.getCount(); - shapes.load("items"); - await context.sync(); - let maxHeight = 0; - shapes.items.map((shape) => { - shape.load("width,height"); - }); - await context.sync(); - shapes.items.map((shape) => { - shape.left = currentLeft; - shape.top = currentTop; - currentLeft += shape.width; - if (shape.height > maxHeight) maxHeight = shape.height; - }); + await Word.run(async (context) => { + // Gets the document windows. + const windows: Word.WindowCollection = context.document.windows; + windows.load("windows/items/length"); + await context.sync(); - currentLeft = 0; - if (currentTop > slideHeight - 200) currentTop = 0; + + console.log(`Number of windows for this document: ${windows.items.length}`); }); -'PowerPoint.Shape#width:member': +Word.DocumentCompareOptions:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/compare-documents.yaml - // Arranges the selected shapes in a line from left to right. - await PowerPoint.run(async (context) => { - const shapes = context.presentation.getSelectedShapes(); - const shapeCount = shapes.getCount(); - shapes.load("items"); - await context.sync(); - let maxHeight = 0; - shapes.items.map((shape) => { - shape.load("width,height"); - }); - await context.sync(); - shapes.items.map((shape) => { - shape.left = currentLeft; - shape.top = currentTop; - currentLeft += shape.width; - if (shape.height > maxHeight) maxHeight = shape.height; - }); + // Compares the current document with a specified external document. + + await Word.run(async (context) => { + // Absolute path of an online or local document. + const filePath = (document.getElementById("filePath") as HTMLInputElement).value; + // Options that configure the compare operation. + const options: Word.DocumentCompareOptions = { + compareTarget: Word.CompareTarget.compareTargetCurrent, + detectFormatChanges: false + // Other options you choose... + }; + context.document.compare(filePath, options); + await context.sync(); - currentLeft = 0; - if (currentTop > slideHeight - 200) currentTop = 0; + + console.log("Differences shown in the current document."); }); -'PowerPoint.ShapeCollection#addGeometricShape:member(1)': +Word.DocumentCreated:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-external-document.yaml - // This function gets the collection of shapes on the first slide, - // and adds a hexagon shape to the collection, while specifying its + // Updates the text of the current document with the text from another + document passed in as a Base64-encoded string. - // location and size. Then it names the shape. + await Word.run(async (context) => { + // Use the Base64-encoded string representation of the selected .docx file. + const externalDoc: Word.DocumentCreated = context.application.createDocument(externalDocument); + await context.sync(); - await PowerPoint.run(async (context) => { - const shapes = context.presentation.slides.getItemAt(0).shapes; - const hexagon = shapes.addGeometricShape(PowerPoint.GeometricShapeType.hexagon, - { - left: 100, - top: 100, - height: 150, - width: 150 - }); - hexagon.name = "Hexagon"; + if (!Office.context.requirements.isSetSupported("WordApiHiddenDocument", "1.3")) { + console.warn("The WordApiHiddenDocument 1.3 requirement set isn't supported on this client so can't proceed. Try this action on a platform that supports this requirement set."); + return; + } + + const externalDocBody: Word.Body = externalDoc.body; + externalDocBody.load("text"); + await context.sync(); + // Insert the external document's text at the beginning of the current document's body. + const externalDocBodyText = externalDocBody.text; + const currentDocBody: Word.Body = context.document.body; + currentDocBody.insertText(externalDocBodyText, Word.InsertLocation.start); await context.sync(); }); -'PowerPoint.ShapeCollection#addLine:member(1)': +Word.DocumentProperties:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/get-built-in-properties.yaml - // This function gets the collection of shapes on the first slide, - // and adds a line to the collection, while specifying its + await Word.run(async (context) => { + const builtInProperties: Word.DocumentProperties = context.document.properties; + builtInProperties.load("*"); // Let's get all! - // start and end points. Then it names the shape. + await context.sync(); + console.log(JSON.stringify(builtInProperties, null, 4)); + }); +Word.DocumentPropertyType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml - await PowerPoint.run(async (context) => { - const shapes = context.presentation.slides.getItemAt(0).shapes; - // For a line, left and top are the coordinates of the start point, - // while height and width are the coordinates of the end point. - const line = shapes.addLine(PowerPoint.ConnectorType.straight, - { - left: 400, - top: 200, - height: 20, - width: 150 - }); - line.name = "StraightLine"; + await Word.run(async (context) => { + const properties: Word.CustomPropertyCollection = context.document.properties.customProperties; + properties.load("key,type,value"); - await context.sync(); + await context.sync(); + for (let i = 0; i < properties.items.length; i++) + console.log("Property Name:" + properties.items[i].key + "; Type=" + properties.items[i].type + "; Property Value=" + properties.items[i].value); }); -'PowerPoint.ShapeCollection#addTextBox:member(1)': +Word.DropDownListContentControl:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml - - // This function gets the collection of shapes on the first slide, + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml - // and adds a text box to the collection, while specifying its text, - // location, and size. Then it names the text box. + // Places a dropdown list content control at the end of the selection. - await PowerPoint.run(async (context) => { - const shapes = context.presentation.slides.getItemAt(0).shapes; - const textbox = shapes.addTextBox("Hello!", - { - left: 100, - top: 300, - height: 300, - width: 450 - }); - textbox.name = "Textbox"; + await Word.run(async (context) => { + let selection = context.document.getSelection(); + selection.getRange(Word.RangeLocation.end).insertContentControl(Word.ContentControlType.dropDownList); + await context.sync(); - return context.sync(); + console.log("Dropdown list content control inserted at the end of the selection."); }); -'PowerPoint.ShapeCollection#getItemAt:member(1)': +Word.DropDownListContentControl#addListItem:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/tags/tags.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml - await PowerPoint.run(async function(context) { - const slide = context.presentation.slides.getItemAt(0); - const shape = slide.shapes.getItemAt(0); - shape.tags.add("MOUNTAIN", "Denali"); + // Adds the provided list item to the first dropdown list content control in + the selection. + + await Word.run(async (context) => { + const listItemText = (document.getElementById("item-to-add") as HTMLInputElement).value.trim(); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.dropDownList] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,dropDownListContentControl"); await context.sync(); - const myShapeTag = shape.tags.getItem("MOUNTAIN"); - myShapeTag.load("key, value"); + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,dropDownListContentControl"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.dropDownList) { + console.warn("No dropdown list content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + selectedContentControl.dropDownListContentControl.addListItem(listItemText); await context.sync(); - console.log("Added key " + JSON.stringify(myShapeTag.key) + " with value " + JSON.stringify(myShapeTag.value)); + console.log(`List item added to control with ID ${selectedContentControl.id}: ${listItemText}`); }); -'PowerPoint.ShapeFill#setSolidColor:member(1)': +Word.DropDownListContentControl#deleteAllListItems:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml - // Changes the selected shapes fill color to red. - await PowerPoint.run(async (context) => { - const shapes = context.presentation.getSelectedShapes(); - const shapeCount = shapes.getCount(); - shapes.load("items"); + // Deletes the list items from first dropdown list content control found in + the selection. + + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.dropDownList] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,dropDownListContentControl"); await context.sync(); - shapes.items.map((shape) => { - shape.fill.setSolidColor("red"); - }); + + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,dropDownListContentControl"); + await context.sync(); + + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.dropDownList) { + console.warn("No dropdown list content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + + console.log( + `About to delete the list from the dropdown list content control with ID ${selectedContentControl.id}` + ); + selectedContentControl.dropDownListContentControl.deleteAllListItems(); await context.sync(); + + console.log("Deleted the list from the dropdown list content control."); }); -'PowerPoint.ShapeFont#color:member': +Word.DropDownListContentControl#listItems:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml - // Sets the color of the selected text range to green. - await PowerPoint.run(async (context) => { - const textRange = context.presentation.getSelectedTextRange(); - textRange.font.color = "green"; + // Deletes the provided list item from the first dropdown list content + control in the selection. + + await Word.run(async (context) => { + const listItemText = (document.getElementById("item-to-delete") as HTMLInputElement).value.trim(); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.dropDownList] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,dropDownListContentControl"); await context.sync(); - }); -'PowerPoint.Slide#delete:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml - // Deletes the selected slides. + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,dropDownListContentControl"); + await context.sync(); - await PowerPoint.run(async (context) => { - context.presentation.load("slides"); + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.dropDownList) { + console.warn("No dropdown list content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + + let selectedDropdownList: Word.DropDownListContentControl = selectedContentControl.dropDownListContentControl; + selectedDropdownList.listItems.load("items/*"); await context.sync(); - const slides = context.presentation.getSelectedSlides(); - const slideCount = slides.getCount(); - slides.load("items"); + + let listItems: Word.ContentControlListItemCollection = selectedContentControl.dropDownListContentControl.listItems; + let itemToDelete: Word.ContentControlListItem = listItems.items.find((item) => item.displayText === listItemText); + if (!itemToDelete) { + console.warn(`List item doesn't exist in control with ID ${selectedContentControl.id}: ${listItemText}`) + return; + } + + itemToDelete.delete(); await context.sync(); - slides.items.map((slide) => { - slide.delete(); - }); + + console.log(`List item deleted from control with ID ${selectedContentControl.id}: ${listItemText}`); }); -'PowerPoint.Slide#setSelectedShapes:member(1)': +Word.ErrorCodes:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml - // Reselects shapes that were saved previously. - await PowerPoint.run(async (context) => { - const slide1 = context.presentation.slides.getItem(savedSlideSelection[0]); - await context.sync(); - slide1.setSelectedShapes(savedShapeSelection); - await context.sync(); - }); + async function tryCatch(callback) { + try { + await callback(); + } catch (error) { + // Note: In a production add-in, you'd want to notify the user through your add-in's UI. + if (error.code === Word.ErrorCodes.itemNotFound) { + console.warn("No checkbox content control is currently selected."); + } else { + console.error(error); + } + } + } +Word.EventSource:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - // Selects the first two shapes on slide 1. - await PowerPoint.run(async (context) => { - context.presentation.load("slides"); - await context.sync(); - const slide1 = context.presentation.slides.getItemAt(0); - slide1.load("shapes"); - await context.sync(); - const shapes = slide1.shapes; - const shape1 = shapes.getItemAt(0); - const shape2 = shapes.getItemAt(1); - shape1.load("id"); - shape2.load("id"); + // Registers event handlers. + + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + body.track(); await context.sync(); - slide1.setSelectedShapes([shape1.id, shape2.id]); + + eventContexts[0] = body.onCommentAdded.add(onEventHandler); + eventContexts[1] = body.onCommentChanged.add(onChangedHandler); + eventContexts[2] = body.onCommentDeleted.add(onEventHandler); + eventContexts[3] = body.onCommentDeselected.add(onEventHandler); + eventContexts[4] = body.onCommentSelected.add(onEventHandler); await context.sync(); + + console.log("Event handlers registered."); }); -'PowerPoint.SlideCollection#add:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml - - const chosenMaster = $("#master-id").val() as string; - - const chosenLayout = $("#layout-id").val() as string; + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml - await PowerPoint.run(async function(context) { - context.presentation.slides.add({ - slideMasterId: chosenMaster, - layoutId: chosenLayout + async function onEventHandler(event: Word.CommentEventArgs) { + // Handler for all events except onCommentChanged. + await Word.run(async (context) => { + console.log(`${event.type} event detected. Event source: ${event.source}. Comment info:`, event.commentDetails); }); - await context.sync(); - }); -'PowerPoint.SlideCollection#getItemAt:member(1)': + } +Word.EventType:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml - // Selects slides 2, 4, and 5. - await PowerPoint.run(async (context) => { - context.presentation.load("slides"); - await context.sync(); - const slide2 = context.presentation.slides.getItemAt(1); - const slide4 = context.presentation.slides.getItemAt(3); - const slide5 = context.presentation.slides.getItemAt(4); - slide2.load("id"); - slide4.load("id"); - slide5.load("id"); - try { - await context.sync(); - } catch (error) { - console.warn("This action requires at least 5 slides in the presentation."); - return; - } - await context.sync(); - context.presentation.setSelectedSlides([slide2.id, slide4.id, slide5.id]); - await context.sync(); - }); -'PowerPoint.TagCollection#add:member(1)': + async function contentControlDeleted(event: + Word.ContentControlDeletedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.eventType} event detected. IDs of content controls that were deleted:`, event.ids); + }); + } +Word.Field:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/tags/tags.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - await PowerPoint.run(async function(context) { - const slide = context.presentation.slides.getItemAt(0); - slide.tags.add("OCEAN", "Indian"); - slide.tags.add("PLANET", "Jupiter"); - slide.tags.add("CONTINENT", "Antarctica"); - await context.sync(); + // Gets the first field in the document. - slide.tags.load("key, value"); + await Word.run(async (context) => { + const field: Word.Field = context.document.body.fields.getFirstOrNullObject(); + field.load(["code", "result", "locked", "type", "data", "kind"]); await context.sync(); - for (let i = 0; i < slide.tags.items.length; i++) { - console.log("Added key " + JSON.stringify(slide.tags.items[i].key) + " with value " + JSON.stringify(slide.tags.items[i].value)); + if (field.isNullObject) { + console.log("This document has no fields."); + } else { + console.log("Code of first field: " + field.code, "Result of first field: " + JSON.stringify(field.result), "Type of first field: " + field.type, "Is the first field locked? " + field.locked, "Kind of the first field: " + field.kind); } }); -'PowerPoint.TagCollection#delete:member(1)': +Word.Field#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/tags/tags.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - await PowerPoint.run(async function (context) { - let presentationTags = context.presentation.tags; - presentationTags.delete("COLOR"); + // Deletes the first field in the document. + + await Word.run(async (context) => { + const field: Word.Field = context.document.body.fields.getFirstOrNullObject(); + field.load(); await context.sync(); - console.log(JSON.stringify(presentationTags)); + if (field.isNullObject) { + console.log("This document has no fields."); + } else { + field.delete(); + await context.sync(); + + console.log("The first field in the document was deleted."); + } }); -'PowerPoint.TagCollection#getItem:member(1)': +Word.Field#select:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/tags/tags.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - await PowerPoint.run(async function(context) { - let selectedSlideIndex = await getSelectedSlideIndex(); - // Decrement because the getSelectedSlideByIndex method is 1-based, - // but the getItemAt method is 0-based. - selectedSlideIndex = selectedSlideIndex - 1; - const slide = context.presentation.slides.getItemAt(selectedSlideIndex); - slide.tags.add("CUSTOMER_TYPE", "Premium"); + // Gets and updates the first field in the selection. + + await Word.run(async (context) => { + let field = context.document.getSelection().fields.getFirstOrNullObject(); + field.load(["code", "result", "type", "locked"]); await context.sync(); - const audienceTag = slide.tags.getItem("CUSTOMER_TYPE"); - audienceTag.load("key, value"); + if (field.isNullObject) { + console.log("No field in selection."); + } else { + console.log("Before updating:", "Code of first field: " + field.code, "Result of first field: " + JSON.stringify(field.result)); - await context.sync(); + field.updateResult(); + field.select(); + await context.sync(); - console.log("Added key " + JSON.stringify(audienceTag.key) + " with value " + JSON.stringify(audienceTag.value)); + field.load(["code", "result"]); + await context.sync(); + + console.log("After updating:", "Code of first field: " + field.code, "Result of first field: " + JSON.stringify(field.result)); + } }); -'PowerPoint.TextRange#setSelected:member(1)': +Word.Field#updateResult:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - // Selects the first 10 characters of the selected shape. - await PowerPoint.run(async (context) => { - const shapes = context.presentation.getSelectedShapes(); - const shapeCount = shapes.getCount(); - await context.sync(); - if (shapeCount.value !== 1) { - console.warn("You must select only one shape with text in it."); - return; - } - const shape = shapes.getItemAt(0); - const textFrame = shape.textFrame.load("textRange,hasText"); - await context.sync(); - if (textFrame.hasText != true) { - console.warn("You must select only one shape with text in it."); - return; - } - const textRange = textFrame.textRange; - textRange.load("text"); + // Gets and updates the first field in the selection. + + await Word.run(async (context) => { + let field = context.document.getSelection().fields.getFirstOrNullObject(); + field.load(["code", "result", "type", "locked"]); + await context.sync(); - if (textRange.text.length < 10) { - console.warn("You must select only one shape with at least 10 characters in it."); - return; + + if (field.isNullObject) { + console.log("No field in selection."); + } else { + console.log("Before updating:", "Code of first field: " + field.code, "Result of first field: " + JSON.stringify(field.result)); + + field.updateResult(); + field.select(); + await context.sync(); + + field.load(["code", "result"]); + await context.sync(); + + console.log("After updating:", "Code of first field: " + field.code, "Result of first field: " + JSON.stringify(field.result)); } - const textRange10 = textRange.getSubstring(0, 10); - textRange10.setSelected(); - await context.sync(); }); +Word.Field#code:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - // Sets the range selection to the range that was saved previously. - await PowerPoint.run(async (context) => { - const slide1 = context.presentation.slides.getItem(savedTextSlideSelection[0]); - const shape1 = slide1.shapes.getItem(savedTextShapeSelection[0]); - const textRange = shape1.textFrame.textRange.getSubstring(savedTextTextRangeStart, savedTextTextRangeLength); - textRange.setSelected(); - await context.sync(); - }); -'PowerPoint.TextRange#font:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml + // Gets the first field in the document. - // Sets the color of the selected text range to green. + await Word.run(async (context) => { + const field: Word.Field = context.document.body.fields.getFirstOrNullObject(); + field.load(["code", "result", "locked", "type", "data", "kind"]); - await PowerPoint.run(async (context) => { - const textRange = context.presentation.getSelectedTextRange(); - textRange.font.color = "green"; await context.sync(); - }); -'Word.Alignment:enum': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml - await Word.run(async (context) => { - const body = context.document.body; - body.clear(); - body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", - "Start" - ); - body.paragraphs - .getLast() - .insertText( - "To make your document look professionally produced, Word provides header, footer, cover page, and text box designs that complement each other. For example, you can add a matching cover page, header, and sidebar. Click Insert and then choose the elements you want from the different galleries.", - "Replace" - ); - body.paragraphs.getFirst().alignment = "Left"; - body.paragraphs.getLast().alignment = Word.Alignment.left; + if (field.isNullObject) { + console.log("This document has no fields."); + } else { + console.log("Code of first field: " + field.code, "Result of first field: " + JSON.stringify(field.result), "Type of first field: " + field.type, "Is the first field locked? " + field.locked, "Kind of the first field: " + field.kind); + } }); -'Word.Application#createDocument:member(1)': +Word.Field#kind:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-external-document.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - // Updates the text of the current document with the text from another - document passed in as a Base64-encoded string. + + // Gets the first field in the document. await Word.run(async (context) => { - // Use the Base64-encoded string representation of the selected .docx file. - const externalDoc = context.application.createDocument(externalDocument); - await context.sync(); + const field: Word.Field = context.document.body.fields.getFirstOrNullObject(); + field.load(["code", "result", "locked", "type", "data", "kind"]); - const externalDocBody = externalDoc.body; - externalDocBody.load("text"); await context.sync(); - // Insert the external document's text at the beginning of the current document's body. - const externalDocBodyText = externalDocBody.text; - const currentDocBody = context.document.body; - currentDocBody.insertText(externalDocBodyText, Word.InsertLocation.start); - await context.sync(); + if (field.isNullObject) { + console.log("This document has no fields."); + } else { + console.log("Code of first field: " + field.code, "Result of first field: " + JSON.stringify(field.result), "Type of first field: " + field.type, "Is the first field locked? " + field.locked, "Kind of the first field: " + field.kind); + } }); -'Word.Application#retrieveStylesFromBase64:member(1)': +Word.Field#locked:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - // Gets style info from another document passed in as a Base64-encoded - string. + + // Gets the first field in the selection and toggles between setting it to + locked or unlocked. await Word.run(async (context) => { - const retrievedStyles = context.application.retrieveStylesFromBase64(externalDocument); + let field = context.document.getSelection().fields.getFirstOrNullObject(); + field.load(["code", "result", "type", "locked"]); await context.sync(); - console.log("Styles from the other document:"); - console.log(retrievedStyles.value); + if (field.isNullObject) { + console.log("The selection has no fields."); + } else { + console.log(`The first field in the selection is currently ${field.locked ? "locked" : "unlocked"}.`); + field.locked = !field.locked; + await context.sync(); + + console.log(`The first field in the selection is now ${field.locked ? "locked" : "unlocked"}.`); + } }); -'Word.Body#getComments:member(1)': +Word.Field#parentBody:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - // Gets the comments in the document body. + + // Gets the parent body of the first field in the document. await Word.run(async (context) => { - const comments = context.document.body.getComments(); + const field: Word.Field = context.document.body.fields.getFirstOrNullObject(); + field.load("parentBody/text"); - // Load objects for display in Script Lab console. - comments.load(); await context.sync(); - console.log("All comments:"); - console.log(comments); + if (field.isNullObject) { + console.log("This document has no fields."); + } else { + const parentBody: Word.Body = field.parentBody; + console.log("Text of first field's parent body: " + JSON.stringify(parentBody.text)); + } }); -'Word.Body#insertParagraph:member(1)': +Word.Field#result:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-formatted-text.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + + + // Gets the first field in the document. await Word.run(async (context) => { - // Second sentence, let's insert it as a paragraph after the previously inserted one. - const secondSentence = context.document.body.insertParagraph( - "This is the first text with a custom style.", - "End" - ); - secondSentence.font.set({ - bold: false, - italic: true, - name: "Berlin Sans FB", - color: "blue", - size: 30 - }); + const field: Word.Field = context.document.body.fields.getFirstOrNullObject(); + field.load(["code", "result", "locked", "type", "data", "kind"]); await context.sync(); + + if (field.isNullObject) { + console.log("This document has no fields."); + } else { + console.log("Code of first field: " + field.code, "Result of first field: " + JSON.stringify(field.result), "Type of first field: " + field.type, "Is the first field locked? " + field.locked, "Kind of the first field: " + field.kind); + } }); -'Word.Body#insertTable:member(1)': +Word.Field#type:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/table-cell-access.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + + + // Gets the first field in the document. await Word.run(async (context) => { - // Use a two-dimensional array to hold the initial table values. - const data = [ - ["Tokyo", "Beijing", "Seattle"], - ["Apple", "Orange", "Pineapple"] - ]; - const table = context.document.body.insertTable(2, 3, "Start", data); - table.styleBuiltIn = Word.BuiltInStyleName.gridTable5Dark_Accent2; - table.styleFirstColumn = false; + const field: Word.Field = context.document.body.fields.getFirstOrNullObject(); + field.load(["code", "result", "locked", "type", "data", "kind"]); await context.sync(); + + if (field.isNullObject) { + console.log("This document has no fields."); + } else { + console.log("Code of first field: " + field.code, "Result of first field: " + JSON.stringify(field.result), "Type of first field: " + field.type, "Is the first field locked? " + field.locked, "Kind of the first field: " + field.kind); + } }); -'Word.Body#search:member(1)': +Word.FieldCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/search.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - // Does a basic text search and highlights matches in the document. + + // Gets all fields in the document body. await Word.run(async (context) => { - const results = context.document.body.search("Online"); - results.load("length"); + const fields: Word.FieldCollection = context.document.body.fields.load("items"); await context.sync(); - // Let's traverse the search results and highlight matches. - for (let i = 0; i < results.items.length; i++) { - results.items[i].font.highlightColor = "yellow"; - } + if (fields.items.length === 0) { + console.log("No fields in this document."); + } else { + fields.load(["code", "result"]); + await context.sync(); - await context.sync(); + for (let i = 0; i < fields.items.length; i++) { + console.log(`Field ${i + 1}'s code: ${fields.items[i].code}`, `Field ${i + 1}'s result: ${JSON.stringify(fields.items[i].result)}`); + } + } }); +Word.FieldCollection#getFirstOrNullObject:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/search.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - // Does a wildcard search and highlights matches in the document. + + // Gets the first field in the document. await Word.run(async (context) => { - // Construct a wildcard expression and set matchWildcards to true in order to use wildcards. - const results = context.document.body.search("$*.[0-9][0-9]", { matchWildcards: true }); - results.load("length"); + const field: Word.Field = context.document.body.fields.getFirstOrNullObject(); + field.load(["code", "result", "locked", "type", "data", "kind"]); await context.sync(); - // Let's traverse the search results and highlight matches. - for (let i = 0; i < results.items.length; i++) { - results.items[i].font.highlightColor = "red"; - results.items[i].font.color = "white"; + if (field.isNullObject) { + console.log("This document has no fields."); + } else { + console.log("Code of first field: " + field.code, "Result of first field: " + JSON.stringify(field.result), "Type of first field: " + field.type, "Is the first field locked? " + field.locked, "Kind of the first field: " + field.kind); } - - await context.sync(); }); -'Word.Body#fields:member': +Word.FieldCollection#items:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + // Gets all fields in the document body. await Word.run(async (context) => { - const fields = context.document.body.fields.load("items"); + const fields: Word.FieldCollection = context.document.body.fields.load("items"); await context.sync(); @@ -13973,1850 +24958,1965 @@ await context.sync(); for (let i = 0; i < fields.items.length; i++) { - console.log(`Field ${i + 1}'s code: ${fields.items[i].code}`); - console.log(`Field ${i + 1}'s result: ${JSON.stringify(fields.items[i].result)}`); + console.log(`Field ${i + 1}'s code: ${fields.items[i].code}`, `Field ${i + 1}'s result: ${JSON.stringify(fields.items[i].result)}`); } } }); -'Word.Body#footnotes:member': +Word.FieldKind:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - // Gets the footnotes in the document body. + + // Gets the first field in the document. await Word.run(async (context) => { - const footnotes = context.document.body.footnotes; - footnotes.load("length"); + const field: Word.Field = context.document.body.fields.getFirstOrNullObject(); + field.load(["code", "result", "locked", "type", "data", "kind"]); + await context.sync(); - console.log("Number of footnotes in the document body: " + footnotes.items.length); + if (field.isNullObject) { + console.log("This document has no fields."); + } else { + console.log("Code of first field: " + field.code, "Result of first field: " + JSON.stringify(field.result), "Type of first field: " + field.type, "Is the first field locked? " + field.locked, "Kind of the first field: " + field.kind); + } }); -'Word.Body#inlinePictures:member': +Word.FieldType:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - // Gets the first image in the document. + + // Inserts a Date field before selection. await Word.run(async (context) => { - const firstPicture = context.document.body.inlinePictures.getFirst(); - firstPicture.load("width, height"); + const range: Word.Range = context.document.getSelection().getRange(); - await context.sync(); - console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`); - // Get the image encoded as Base64. - const base64 = firstPicture.getBase64ImageSrc(); + const field: Word.Field = range.insertField(Word.InsertLocation.before, Word.FieldType.date, '\\@ "M/d/yyyy h:mm am/pm"', true); + field.load("result,code"); await context.sync(); - console.log(base64.value); + + if (field.isNullObject) { + console.log("There are no fields in this document."); + } else { + console.log("Code of the field: " + field.code, "Result of the field: " + JSON.stringify(field.result)); + } }); -'Word.Body#paragraphs:member': +Word.GetTextOptions:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-word-count.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-text.yaml - // Counts how many times each term appears in the document. await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("text"); - await context.sync(); - - // Split up the document text using existing spaces as the delimiter. - let text = []; - paragraphs.items.forEach((item) => { - let paragraph = item.text.trim(); - if (paragraph) { - paragraph.split(" ").forEach((term) => { - let currentTerm = term.trim(); - if (currentTerm) { - text.push(currentTerm); - } - }); - } - }); - - // Determine the list of unique terms. - let makeTextDistinct = new Set(text); - let distinctText = Array.from(makeTextDistinct); - let allSearchResults = []; - - for (let i = 0; i < distinctText.length; i++) { - let results = context.document.body.search(distinctText[i], { matchCase: true, matchWholeWord: true }); - results.load("text"); - - // Map each search term with its results. - let correlatedResults = { - searchTerm: distinctText[i], - hits: results - }; + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); - allSearchResults.push(correlatedResults); - } + const text = paragraph.getText(); + const textIncludingHidden = paragraph.getText({ IncludeHiddenText: true }); + const textIncludingDeleted = paragraph.getText({ IncludeTextMarkedAsDeleted: true }); await context.sync(); - // Display the count for each search term. - allSearchResults.forEach((result) => { - let length = result.hits.items.length; - - console.log("Search term: " + result.searchTerm + " => Count: " + length); - }); + console.log("Text:- " + text.value, "Including hidden text:- " + textIncludingHidden.value, "Including text marked as deleted:- " + textIncludingDeleted.value); }); -'Word.Body#tables:member': +Word.HeaderFooterType:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/table-cell-access.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-header-and-footer.yaml - // Gets the content of the first cell in the first table. await Word.run(async (context) => { - const firstCell = context.document.body.tables.getFirst().getCell(0, 0).body; - firstCell.load("text"); + context.document.sections + .getFirst() + .getHeader(Word.HeaderFooterType.primary) + .insertParagraph("This is a primary header.", "End"); await context.sync(); - console.log("First cell's text is: " + firstCell.text); }); -'Word.Body#type:member': +Word.ImageFormat:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml - // Gets the referenced note's item type and body type, which are both - "Footnote". - await Word.run(async (context) => { - const footnotes = context.document.body.footnotes; - footnotes.load("items"); - await context.sync(); + // Gets the first image in the document. - const referenceNumber = $("#input-reference").val(); - const mark = (referenceNumber as number) - 1; - const item = footnotes.items[mark]; - console.log(`Note type of footnote ${referenceNumber}: ${item.type}`); + await Word.run(async (context) => { + const firstPicture: Word.InlinePicture = context.document.body.inlinePictures.getFirst(); + firstPicture.load("width, height, imageFormat"); - item.body.load("type"); await context.sync(); + console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`, `Image format: ${firstPicture.imageFormat}`); + // Get the image encoded as Base64. + const base64 = firstPicture.getBase64ImageSrc(); - console.log(`Body type of note: ${item.body.type}`); + await context.sync(); + console.log(base64.value); }); -'Word.BodyType:enum': +Word.ImportedStylesConflictBehavior:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-custom-style.yaml - // Gets the referenced note's item type and body type, which are both - "Footnote". + + // Imports styles from JSON. await Word.run(async (context) => { - const footnotes = context.document.body.footnotes; - footnotes.load("items"); - await context.sync(); + const str = + '{"styles":[{"baseStyle":"Default Paragraph Font","builtIn":false,"inUse":true,"linked":false,"nameLocal":"NewCharStyle","priority":2,"quickStyle":true,"type":"Character","unhideWhenUsed":false,"visibility":false,"paragraphFormat":null,"font":{"name":"DengXian Light","size":16.0,"bold":true,"italic":false,"color":"#F1A983","underline":"None","subscript":false,"superscript":true,"strikeThrough":true,"doubleStrikeThrough":false,"highlightColor":null,"hidden":false},"shading":{"backgroundPatternColor":"#FF0000"}},{"baseStyle":"Normal","builtIn":false,"inUse":true,"linked":false,"nextParagraphStyle":"NewParaStyle","nameLocal":"NewParaStyle","priority":1,"quickStyle":true,"type":"Paragraph","unhideWhenUsed":false,"visibility":false,"paragraphFormat":{"alignment":"Centered","firstLineIndent":0.0,"keepTogether":false,"keepWithNext":false,"leftIndent":72.0,"lineSpacing":18.0,"lineUnitAfter":0.0,"lineUnitBefore":0.0,"mirrorIndents":false,"outlineLevel":"OutlineLevelBodyText","rightIndent":72.0,"spaceAfter":30.0,"spaceBefore":30.0,"widowControl":true},"font":{"name":"DengXian","size":14.0,"bold":true,"italic":true,"color":"#8DD873","underline":"Single","subscript":false,"superscript":false,"strikeThrough":false,"doubleStrikeThrough":true,"highlightColor":null,"hidden":false},"shading":{"backgroundPatternColor":"#00FF00"}},{"baseStyle":"Table Normal","builtIn":false,"inUse":true,"linked":false,"nextParagraphStyle":"NewTableStyle","nameLocal":"NewTableStyle","priority":100,"type":"Table","unhideWhenUsed":false,"visibility":false,"paragraphFormat":{"alignment":"Left","firstLineIndent":0.0,"keepTogether":false,"keepWithNext":false,"leftIndent":0.0,"lineSpacing":12.0,"lineUnitAfter":0.0,"lineUnitBefore":0.0,"mirrorIndents":false,"outlineLevel":"OutlineLevelBodyText","rightIndent":0.0,"spaceAfter":0.0,"spaceBefore":0.0,"widowControl":true},"font":{"name":"DengXian","size":20.0,"bold":false,"italic":true,"color":"#D86DCB","underline":"None","subscript":false,"superscript":false,"strikeThrough":false,"doubleStrikeThrough":false,"highlightColor":null,"hidden":false},"tableStyle":{"allowBreakAcrossPage":true,"alignment":"Left","bottomCellMargin":0.0,"leftCellMargin":0.08,"rightCellMargin":0.08,"topCellMargin":0.0,"cellSpacing":0.0},"shading":{"backgroundPatternColor":"#60CAF3"}}]}'; + const styles = context.document.importStylesFromJson(str); - const referenceNumber = $("#input-reference").val(); - const mark = (referenceNumber as number) - 1; - const item = footnotes.items[mark]; - console.log(`Note type of footnote ${referenceNumber}: ${item.type}`); + // If you'd like to set how conflicting styles are handled, use the importedStylesConflictBehavior parameter that was introduced in the Desktop 1.1 requirement set. "Ignore" is the default. + ////const styles = context.document.importStylesFromJson(str, Word.ImportedStylesConflictBehavior.Ignore); - item.body.load("type"); await context.sync(); - - console.log(`Body type of note: ${item.body.type}`); + console.log("Styles imported from JSON:", styles); }); -'Word.BorderLocation:enum': +Word.InlinePicture#getBase64ImageSrc:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml - // Gets border details about the first table in the document. + + // Gets the first image in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const borderLocation = Word.BorderLocation.top; - const border = firstTable.getBorder(borderLocation); - border.load(["type", "color", "width"]); + const firstPicture: Word.InlinePicture = context.document.body.inlinePictures.getFirst(); + firstPicture.load("width, height, imageFormat"); + await context.sync(); + console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`, `Image format: ${firstPicture.imageFormat}`); + // Get the image encoded as Base64. + const base64 = firstPicture.getBase64ImageSrc(); - console.log(`Details about the ${borderLocation} border of the first table:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + await context.sync(); + console.log(base64.value); }); -'Word.BorderType:enum': +Word.InlinePicture:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml - // Gets border details about the first of the first table in the document. + + // Inserts an image anchored to the last paragraph. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstCell = firstTable.getCell(0, 0); - const borderLocation = "Left"; - const border = firstCell.getBorder(borderLocation); - border.load(["type", "color", "width"]); - await context.sync(); + context.document.body.paragraphs + .getLast() + .insertParagraph("", "After") + .insertInlinePictureFromBase64(base64Image, "End"); - console.log(`Details about the ${borderLocation} border of the first table's first cell:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + await context.sync(); }); -'Word.BreakType:enum': +Word.InlinePicture#imageFormat:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-line-and-page-breaks.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml + + + // Gets the first image in the document. await Word.run(async (context) => { - context.document.body.paragraphs.getFirst().insertBreak(Word.BreakType.page, "After"); + const firstPicture: Word.InlinePicture = context.document.body.inlinePictures.getFirst(); + firstPicture.load("width, height, imageFormat"); await context.sync(); - console.log("success"); + console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`, `Image format: ${firstPicture.imageFormat}`); + // Get the image encoded as Base64. + const base64 = firstPicture.getBase64ImageSrc(); + + await context.sync(); + console.log(base64.value); }); -'Word.BuiltInStyleName:enum': +Word.InlinePictureCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-formatted-text.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml + + + // Gets the first image in the document. await Word.run(async (context) => { - const sentence = context.document.body.insertParagraph( - "To be or not to be", - "End" - ); + const firstPicture: Word.InlinePicture = context.document.body.inlinePictures.getFirst(); + firstPicture.load("width, height, imageFormat"); - // Use styleBuiltIn to use an enumeration of existing styles. If your style is custom make sure to use: range.style = "name of your style"; - sentence.styleBuiltIn = Word.BuiltInStyleName.intenseReference; + await context.sync(); + console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`, `Image format: ${firstPicture.imageFormat}`); + // Get the image encoded as Base64. + const base64 = firstPicture.getBase64ImageSrc(); await context.sync(); + console.log(base64.value); }); -'Word.CellPaddingLocation:enum': +Word.InsertFileOptions:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-external-document.yaml + - // Gets cell padding details about the first table in the document. + // Inserts content (applying selected settings) from another document passed + in as a Base64-encoded string. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const cellPaddingLocation = Word.CellPaddingLocation.right; - const cellPadding = firstTable.getCellPadding(cellPaddingLocation); + // Use the Base64-encoded string representation of the selected .docx file. + context.document.insertFileFromBase64(externalDocument, "Replace", { + importTheme: true, + importStyles: true, + importParagraphSpacing: true, + importPageColor: true, + importChangeTrackingMode: true, + importCustomProperties: true, + importCustomXmlParts: true, + importDifferentOddEvenPages: true + }); await context.sync(); - - console.log( - `Cell padding details about the ${cellPaddingLocation} border of the first table: ${cellPadding.value} points` - ); }); -'Word.ChangeTrackingMode:enum': +Word.InsertLocation:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-change-tracking.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-section-breaks.yaml - // Gets the current change tracking mode. + + // Inserts a section without an associated page break. await Word.run(async (context) => { - const document = context.document; - document.load("changeTrackingMode"); + const body: Word.Body = context.document.body; + body.insertBreak(Word.BreakType.sectionContinuous, Word.InsertLocation.end); + await context.sync(); - if (document.changeTrackingMode === Word.ChangeTrackingMode.trackMineOnly) { - console.log("Only my changes are being tracked."); - } else if (document.changeTrackingMode === Word.ChangeTrackingMode.trackAll) { - console.log("Everyone's changes are being tracked."); - } else { - console.log("No changes are being tracked."); - } + console.log("Inserted section without an associated page break."); }); -'Word.ChangeTrackingVersion:enum': +Word.InsertShapeOptions:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-change-tracking.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml - // Gets the reviewed text. await Word.run(async (context) => { - const range = context.document.getSelection(); - const before = range.getReviewedText(Word.ChangeTrackingVersion.original); - const after = range.getReviewedText(Word.ChangeTrackingVersion.current); + // Inserts a text box at the beginning of the selection. + const range: Word.Range = context.document.getSelection(); + const insertShapeOptions: Word.InsertShapeOptions = { + top: 0, + left: 0, + height: 100, + width: 100 + }; + const newTextBox: Word.Shape = range.insertTextBox("placeholder text", insertShapeOptions); await context.sync(); - console.log(`Reviewed text (before):\n${before.value}`); - console.log(`Reviewed text (after):\n${after.value}`); + console.log("Inserted a text box at the beginning of the current selection."); }); -'Word.Comment#delete:member(1)': +Word.List:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/insert-list.yaml - // Deletes the first comment in the selected content. + + // This example starts a new list with the second paragraph. await Word.run(async (context) => { - context.document - .getSelection() - .getComments() - .getFirst() - .delete(); + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("$none"); + + await context.sync(); + + // Start new list using the second paragraph. + const list: Word.List = paragraphs.items[1].startNewList(); + list.load("$none"); + await context.sync(); - console.log("Comment deleted"); + // To add new items to the list, use Start or End on the insertLocation parameter. + list.insertParagraph("New list item at the start of the list", "Start"); + const paragraph: Word.Paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + + // Set up list level for the list item. + paragraph.listItem.level = 4; + + // To add paragraphs outside the list, use Before or After. + list.insertParagraph("New paragraph goes after (not part of the list)", "After"); + + await context.sync(); }); -'Word.Comment#getRange:member(1)': +Word.List#insertParagraph:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/insert-list.yaml - // Gets the range of the first comment in the selected content. + + // This example starts a new list with the second paragraph. await Word.run(async (context) => { - const range = context.document - .getSelection() - .getComments() - .getFirst() - .getRange(); - range.load("text"); + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("$none"); + await context.sync(); - console.log(`Comment location: ${range.text}`); - }); -'Word.Comment#reply:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml + // Start new list using the second paragraph. + const list: Word.List = paragraphs.items[1].startNewList(); + list.load("$none"); - // Replies to the first active comment in the selected content. + await context.sync(); + + // To add new items to the list, use Start or End on the insertLocation parameter. + list.insertParagraph("New list item at the start of the list", "Start"); + const paragraph: Word.Paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + + // Set up list level for the list item. + paragraph.listItem.level = 4; + + // To add paragraphs outside the list, use Before or After. + list.insertParagraph("New paragraph goes after (not part of the list)", "After"); - await Word.run(async (context) => { - const text = $("#reply-text") - .val() - .toString(); - const comments = context.document.getSelection().getComments(); - comments.load("items"); await context.sync(); - const firstActiveComment = comments.items.find((item) => item.resolved !== true); - if (firstActiveComment) { - const reply = firstActiveComment.reply(text); - console.log("Reply added"); - } else { - console.log("No active comment was found in the selection so couldn't reply."); - } }); -'Word.Comment#content:member': +Word.List#setLevelBullet:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml - // Edits the first comment in the selected content. + + // Inserts a list starting with the first paragraph then set numbering and + bullet types of the list items. await Word.run(async (context) => { - const text = $("#edit-comment-text") - .val() - .toString(); - const comment = context.document - .getSelection() - .getComments() - .getFirst(); - comment.content = text; + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("$none"); + + await context.sync(); + + // Use the first paragraph to start a new list. + const list: Word.List = paragraphs.items[0].startNewList(); + list.load("$none"); - // Load object for display in Script Lab console. - comment.load(); await context.sync(); - console.log("Comment content changed:"); - console.log(comment); + // To add new items to the list, use Start or End on the insertLocation parameter. + list.insertParagraph("New list item at the start of the list", "Start"); + const paragraph: Word.Paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + + // Set numbering for list level 1. + list.setLevelNumbering(0, Word.ListNumbering.arabic); + + // Set bullet type for list level 5. + list.setLevelBullet(4, Word.ListBullet.arrow); + + // Set list level for the last item in this list. + paragraph.listItem.level = 4; + + list.load("levelTypes"); + + await context.sync(); }); -'Word.Comment#resolved:member': +Word.List#setLevelNumbering:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml - // Toggles Resolved status of the first comment in the selected content. + + // Inserts a list starting with the first paragraph then set numbering and + bullet types of the list items. await Word.run(async (context) => { - const comment = context.document - .getSelection() - .getComments() - .getFirst(); - comment.load("resolved"); + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("$none"); + await context.sync(); - // Toggle resolved status. - // If the comment is active, set as resolved. - // If it's resolved, set resolved to false. - const toggleResolved: boolean = comment.resolved; - comment.resolved = !toggleResolved; - comment.load(); + // Use the first paragraph to start a new list. + const list: Word.List = paragraphs.items[0].startNewList(); + list.load("$none"); + await context.sync(); - console.log(`Comment Resolved status: ${comment.resolved}`); - console.log(comment); + // To add new items to the list, use Start or End on the insertLocation parameter. + list.insertParagraph("New list item at the start of the list", "Start"); + const paragraph: Word.Paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + + // Set numbering for list level 1. + list.setLevelNumbering(0, Word.ListNumbering.arabic); + + // Set bullet type for list level 5. + list.setLevelBullet(4, Word.ListBullet.arrow); + + // Set list level for the last item in this list. + paragraph.listItem.level = 4; + + list.load("levelTypes"); + + await context.sync(); }); -'Word.CommentCollection#getFirst:member(1)': +Word.List#levelExistences:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml - // Gets the range of the first comment in the selected content. + + // Gets information about the first list in the document. await Word.run(async (context) => { - const range = context.document - .getSelection() - .getComments() - .getFirst() - .getRange(); - range.load("text"); + const lists: Word.ListCollection = context.document.body.lists; + lists.load("items"); + await context.sync(); - console.log(`Comment location: ${range.text}`); + if (lists.items.length === 0) { + console.warn("There are no lists in this document."); + return; + } + + // Get the first list. + const list: Word.List = lists.getFirst(); + list.load("levelTypes,levelExistences"); + + await context.sync(); + + const levelTypes = list.levelTypes; + console.log("Level types of the first list:"); + for (let i = 0; i < levelTypes.length; i++) { + console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); + } + + const levelExistences = list.levelExistences; + console.log("Level existences of the first list:"); + for (let i = 0; i < levelExistences.length; i++) { + console.log(`- Level ${i + 1} (index ${i}): ${levelExistences[i]}`); + } }); -'Word.CommentCollection#items:member': +Word.List#levelTypes:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml - // Replies to the first active comment in the selected content. + + // Gets information about the first list in the document. await Word.run(async (context) => { - const text = $("#reply-text") - .val() - .toString(); - const comments = context.document.getSelection().getComments(); - comments.load("items"); + const lists: Word.ListCollection = context.document.body.lists; + lists.load("items"); + await context.sync(); - const firstActiveComment = comments.items.find((item) => item.resolved !== true); - if (firstActiveComment) { - const reply = firstActiveComment.reply(text); - console.log("Reply added"); - } else { - console.log("No active comment was found in the selection so couldn't reply."); + + if (lists.items.length === 0) { + console.warn("There are no lists in this document."); + return; + } + + // Get the first list. + const list: Word.List = lists.getFirst(); + list.load("levelTypes,levelExistences"); + + await context.sync(); + + const levelTypes = list.levelTypes; + console.log("Level types of the first list:"); + for (let i = 0; i < levelTypes.length; i++) { + console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); + } + + const levelExistences = list.levelExistences; + console.log("Level existences of the first list:"); + for (let i = 0; i < levelExistences.length; i++) { + console.log(`- Level ${i + 1} (index ${i}): ${levelExistences[i]}`); } }); -'Word.ContentControl#delete:member(1)': +Word.ListBuiltInNumberStyle:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/manage-list-styles.yaml + + + // Gets the properties of the specified style. await Word.run(async (context) => { - const contentControls = context.document.contentControls.getByTag("forTesting"); - contentControls.load("items"); + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to get properties."); + return; + } + + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load("type"); await context.sync(); - if (contentControls.items.length === 0) { - console.log("There are no content controls in this document."); + if (style.isNullObject || style.type != Word.StyleType.list) { + console.warn(`There's no existing style with the name '${styleName}'. Or this isn't a list style.`); } else { - console.log("Control to be deleted:"); - console.log(contentControls.items[0]); - contentControls.items[0].delete(false); + // Load objects to log properties and their values in the console. + style.load(); + style.listTemplate.load(); + await context.sync(); + + console.log(`Properties of the '${styleName}' style:`, style); + + const listLevels = style.listTemplate.listLevels; + listLevels.load("items"); await context.sync(); + + console.log(`List levels of the '${styleName}' style:`, listLevels); } }); -'Word.ContentControl#set:member(1)': +Word.ListBullet:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-content-controls.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml - // Adds title and colors to odd and even content controls and changes their - appearance. + + // Inserts a list starting with the first paragraph then set numbering and + bullet types of the list items. await Word.run(async (context) => { - // Get the complete sentence (as range) associated with the insertion point. - let evenContentControls = context.document.contentControls.getByTag("even"); - let oddContentControls = context.document.contentControls.getByTag("odd"); - evenContentControls.load("length"); - oddContentControls.load("length"); + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("$none"); await context.sync(); - for (let i = 0; i < evenContentControls.items.length; i++) { - // Change a few properties and append a paragraph - evenContentControls.items[i].set({ - color: "red", - title: "Odd ContentControl #" + (i + 1), - appearance: Word.ContentControlAppearance.tags - }); - evenContentControls.items[i].insertParagraph("This is an odd content control", "End"); - } + // Use the first paragraph to start a new list. + const list: Word.List = paragraphs.items[0].startNewList(); + list.load("$none"); - for (let j = 0; j < oddContentControls.items.length; j++) { - // Change a few properties and append a paragraph - oddContentControls.items[j].set({ - color: "green", - title: "Even ContentControl #" + (j + 1), - appearance: "Tags" - }); - oddContentControls.items[j].insertHtml("This is an even content control", "End"); - } + await context.sync(); + + // To add new items to the list, use Start or End on the insertLocation parameter. + list.insertParagraph("New list item at the start of the list", "Start"); + const paragraph: Word.Paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + + // Set numbering for list level 1. + list.setLevelNumbering(0, Word.ListNumbering.arabic); + + // Set bullet type for list level 5. + list.setLevelBullet(4, Word.ListBullet.arrow); + + // Set list level for the last item in this list. + paragraph.listItem.level = 4; + + list.load("levelTypes"); await context.sync(); }); -'Word.ContentControl#onDataChanged:member': +Word.ListCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondatachanged-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml + + + // Gets information about the first list in the document. await Word.run(async (context) => { - const contentControls = context.document.contentControls; - contentControls.load("items"); + const lists: Word.ListCollection = context.document.body.lists; + lists.load("items"); + await context.sync(); - // Register the onDataChanged event handler on each content control. - if (contentControls.items.length === 0) { - console.log("There aren't any content controls in this document so can't register event handlers."); - } else { - for (let i = 0; i < contentControls.items.length; i++) { - eventContexts[i] = contentControls.items[i].onDataChanged.add(contentControlDataChanged); - contentControls.items[i].track(); - } + if (lists.items.length === 0) { + console.warn("There are no lists in this document."); + return; + } + + // Get the first list. + const list: Word.List = lists.getFirst(); + list.load("levelTypes,levelExistences"); - await context.sync(); + await context.sync(); - console.log("Added event handlers for when data is changed in content controls."); + const levelTypes = list.levelTypes; + console.log("Level types of the first list:"); + for (let i = 0; i < levelTypes.length; i++) { + console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); + } + + const levelExistences = list.levelExistences; + console.log("Level existences of the first list:"); + for (let i = 0; i < levelExistences.length; i++) { + console.log(`- Level ${i + 1} (index ${i}): ${levelExistences[i]}`); } }); +Word.ListItem:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondatachanged-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/insert-list.yaml - async function contentControlDataChanged(event: - Word.ContentControlDataChangedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls where data was changed:`); - console.log(event.ids); - }); - } -'Word.ContentControl#onDeleted:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml + + // This example starts a new list with the second paragraph. await Word.run(async (context) => { - const contentControls = context.document.contentControls; - contentControls.load("items"); + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("$none"); + await context.sync(); - // Register the onDeleted event handler on each content control. - if (contentControls.items.length === 0) { - console.log("There aren't any content controls in this document so can't register event handlers."); - } else { - for (let i = 0; i < contentControls.items.length; i++) { - eventContexts[i] = contentControls.items[i].onDeleted.add(contentControlDeleted); - contentControls.items[i].track(); - } + // Start new list using the second paragraph. + const list: Word.List = paragraphs.items[1].startNewList(); + list.load("$none"); - await context.sync(); + await context.sync(); - console.log("Added event handlers for when content controls are deleted."); - } + // To add new items to the list, use Start or End on the insertLocation parameter. + list.insertParagraph("New list item at the start of the list", "Start"); + const paragraph: Word.Paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + + // Set up list level for the list item. + paragraph.listItem.level = 4; + + // To add paragraphs outside the list, use Before or After. + list.insertParagraph("New paragraph goes after (not part of the list)", "After"); + + await context.sync(); }); +Word.ListItem#level:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/insert-list.yaml - async function contentControlDeleted(event: - Word.ContentControlDeletedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls that were deleted:`); - console.log(event.ids); - }); - } -'Word.ContentControl#onEntered:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onentered-event.yaml + + // This example starts a new list with the second paragraph. await Word.run(async (context) => { - const contentControls = context.document.contentControls; - contentControls.load("items"); + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("$none"); + await context.sync(); - // Register the onEntered event handler on each content control. - if (contentControls.items.length === 0) { - console.log("There aren't any content controls in this document so can't register event handlers."); - } else { - for (let i = 0; i < contentControls.items.length; i++) { - eventContexts[i] = contentControls.items[i].onEntered.add(contentControlEntered); - contentControls.items[i].track(); - } + // Start new list using the second paragraph. + const list: Word.List = paragraphs.items[1].startNewList(); + list.load("$none"); - await context.sync(); + await context.sync(); - console.log("Added event handlers for when the cursor is placed in content controls."); - } + // To add new items to the list, use Start or End on the insertLocation parameter. + list.insertParagraph("New list item at the start of the list", "Start"); + const paragraph: Word.Paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + + // Set up list level for the list item. + paragraph.listItem.level = 4; + + // To add paragraphs outside the list, use Before or After. + list.insertParagraph("New paragraph goes after (not part of the list)", "After"); + + await context.sync(); }); +Word.ListLevel:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onentered-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/manage-list-styles.yaml - async function contentControlEntered(event: - Word.ContentControlEnteredEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. ID of content control that was entered: ${event.ids[0]}`); - }); - } -'Word.ContentControl#onExited:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onexited-event.yaml + + // Gets the properties of the specified style. await Word.run(async (context) => { - const contentControls = context.document.contentControls; - contentControls.load("items"); + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to get properties."); + return; + } + + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load("type"); await context.sync(); - // Register the onExited event handler on each content control. - if (contentControls.items.length === 0) { - console.log("There aren't any content controls in this document so can't register event handlers."); + if (style.isNullObject || style.type != Word.StyleType.list) { + console.warn(`There's no existing style with the name '${styleName}'. Or this isn't a list style.`); } else { - for (let i = 0; i < contentControls.items.length; i++) { - eventContexts[i] = contentControls.items[i].onExited.add(contentControlExited); - contentControls.items[i].track(); - } + // Load objects to log properties and their values in the console. + style.load(); + style.listTemplate.load(); + await context.sync(); + + console.log(`Properties of the '${styleName}' style:`, style); + const listLevels = style.listTemplate.listLevels; + listLevels.load("items"); await context.sync(); - console.log("Added event handlers for when the cursor is removed from within content controls."); + console.log(`List levels of the '${styleName}' style:`, listLevels); } }); +Word.ListLevelCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onexited-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/manage-list-styles.yaml - async function contentControlExited(event: - Word.ContentControlExitedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. ID of content control that was exited: ${event.ids[0]}`); - }); - } -'Word.ContentControl#onSelectionChanged:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onselectionchanged-event.yaml + + // Gets the properties of the specified style. await Word.run(async (context) => { - const contentControls = context.document.contentControls; - contentControls.load("items"); + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to get properties."); + return; + } + + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load("type"); await context.sync(); - if (contentControls.items.length === 0) { - console.log("There aren't any content controls in this document so can't register event handlers."); + if (style.isNullObject || style.type != Word.StyleType.list) { + console.warn(`There's no existing style with the name '${styleName}'. Or this isn't a list style.`); } else { - for (let i = 0; i < contentControls.items.length; i++) { - eventContexts[i] = contentControls.items[i].onSelectionChanged.add(contentControlSelectionChanged); - contentControls.items[i].track(); - } + // Load objects to log properties and their values in the console. + style.load(); + style.listTemplate.load(); + await context.sync(); + console.log(`Properties of the '${styleName}' style:`, style); + + const listLevels = style.listTemplate.listLevels; + listLevels.load("items"); await context.sync(); - console.log("Added event handlers for when selections are changed in content controls."); + console.log(`List levels of the '${styleName}' style:`, listLevels); } }); +Word.ListLevelType:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onselectionchanged-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml - async function contentControlSelectionChanged(event: - Word.ContentControlSelectionChangedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls where selection was changed:`); - console.log(event.ids); - }); - } -'Word.ContentControl#tag:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-content-controls.yaml - // Traverses each paragraph of the document and wraps a content control on - each with either a even or odd tags. + // Gets information about the first list in the document. await Word.run(async (context) => { - let paragraphs = context.document.body.paragraphs; - paragraphs.load("$none"); // Don't need any properties; just wrap each paragraph with a content control. + const lists: Word.ListCollection = context.document.body.lists; + lists.load("items"); await context.sync(); - for (let i = 0; i < paragraphs.items.length; i++) { - let contentControl = paragraphs.items[i].insertContentControl(); - // For even, tag "even". - if (i % 2 === 0) { - contentControl.tag = "even"; - } else { - contentControl.tag = "odd"; - } + if (lists.items.length === 0) { + console.warn("There are no lists in this document."); + return; } - console.log("Content controls inserted: " + paragraphs.items.length); + + // Get the first list. + const list: Word.List = lists.getFirst(); + list.load("levelTypes,levelExistences"); await context.sync(); - }); -'Word.ContentControlAddedEventArgs#eventType:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onadded-event.yaml - async function contentControlAdded(event: Word.ContentControlAddedEventArgs) - { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls that were added:`); - console.log(event.ids); - }); - } -'Word.ContentControlAddedEventArgs#ids:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onadded-event.yaml + const levelTypes = list.levelTypes; + console.log("Level types of the first list:"); + for (let i = 0; i < levelTypes.length; i++) { + console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); + } - async function contentControlAdded(event: Word.ContentControlAddedEventArgs) - { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls that were added:`); - console.log(event.ids); - }); - } -'Word.ContentControlAppearance:enum': + const levelExistences = list.levelExistences; + console.log("Level existences of the first list:"); + for (let i = 0; i < levelExistences.length; i++) { + console.log(`- Level ${i + 1} (index ${i}): ${levelExistences[i]}`); + } + }); +Word.ListNumbering:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-content-controls.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml - // Adds title and colors to odd and even content controls and changes their - appearance. + + // Inserts a list starting with the first paragraph then set numbering and + bullet types of the list items. await Word.run(async (context) => { - // Get the complete sentence (as range) associated with the insertion point. - let evenContentControls = context.document.contentControls.getByTag("even"); - let oddContentControls = context.document.contentControls.getByTag("odd"); - evenContentControls.load("length"); - oddContentControls.load("length"); + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("$none"); await context.sync(); - for (let i = 0; i < evenContentControls.items.length; i++) { - // Change a few properties and append a paragraph - evenContentControls.items[i].set({ - color: "red", - title: "Odd ContentControl #" + (i + 1), - appearance: Word.ContentControlAppearance.tags - }); - evenContentControls.items[i].insertParagraph("This is an odd content control", "End"); - } + // Use the first paragraph to start a new list. + const list: Word.List = paragraphs.items[0].startNewList(); + list.load("$none"); - for (let j = 0; j < oddContentControls.items.length; j++) { - // Change a few properties and append a paragraph - oddContentControls.items[j].set({ - color: "green", - title: "Even ContentControl #" + (j + 1), - appearance: "Tags" - }); - oddContentControls.items[j].insertHtml("This is an even content control", "End"); - } + await context.sync(); + + // To add new items to the list, use Start or End on the insertLocation parameter. + list.insertParagraph("New list item at the start of the list", "Start"); + const paragraph: Word.Paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + + // Set numbering for list level 1. + list.setLevelNumbering(0, Word.ListNumbering.arabic); + + // Set bullet type for list level 5. + list.setLevelBullet(4, Word.ListBullet.arrow); + + // Set list level for the last item in this list. + paragraph.listItem.level = 4; + + list.load("levelTypes"); await context.sync(); }); -'Word.ContentControlCollection#getByTag:member(1)': +Word.ListTemplate:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/doc-assembly.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/manage-list-styles.yaml + + + // Gets the properties of the specified style. await Word.run(async (context) => { - const contentControls = context.document.contentControls.getByTag("customer"); - contentControls.load("text"); + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to get properties."); + return; + } - await context.sync(); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load("type"); + await context.sync(); - for (let i = 0; i < contentControls.items.length; i++) { - contentControls.items[i].insertText("Fabrikam", "Replace"); - } + if (style.isNullObject || style.type != Word.StyleType.list) { + console.warn(`There's no existing style with the name '${styleName}'. Or this isn't a list style.`); + } else { + // Load objects to log properties and their values in the console. + style.load(); + style.listTemplate.load(); + await context.sync(); + + console.log(`Properties of the '${styleName}' style:`, style); + const listLevels = style.listTemplate.listLevels; + listLevels.load("items"); await context.sync(); + + console.log(`List levels of the '${styleName}' style:`, listLevels); + } }); -'Word.ContentControlDataChangedEventArgs#eventType:member': +Word.LocationRelation:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondatachanged-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/compare-location.yaml - async function contentControlDataChanged(event: - Word.ContentControlDataChangedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls where data was changed:`); - console.log(event.ids); - }); - } -'Word.ContentControlDataChangedEventArgs#ids:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondatachanged-event.yaml - async function contentControlDataChanged(event: - Word.ContentControlDataChangedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls where data was changed:`); - console.log(event.ids); - }); - } -'Word.ContentControlDeletedEventArgs#eventType:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml + // Compares the location of one paragraph in relation to another paragraph. - async function contentControlDeleted(event: - Word.ContentControlDeletedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls that were deleted:`); - console.log(event.ids); - }); - } -'Word.ContentControlDeletedEventArgs#ids:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml + await Word.run(async (context) => { + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("items"); - async function contentControlDeleted(event: - Word.ContentControlDeletedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls that were deleted:`); - console.log(event.ids); - }); - } -'Word.ContentControlEnteredEventArgs#eventType:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onentered-event.yaml + await context.sync(); - async function contentControlEntered(event: - Word.ContentControlEnteredEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. ID of content control that was entered: ${event.ids[0]}`); - }); - } -'Word.ContentControlEnteredEventArgs#ids:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onentered-event.yaml + const firstParagraphAsRange: Word.Range = paragraphs.items[0].getRange(); + const secondParagraphAsRange: Word.Range = paragraphs.items[1].getRange(); - async function contentControlEntered(event: - Word.ContentControlEnteredEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. ID of content control that was entered: ${event.ids[0]}`); - }); - } -'Word.ContentControlExitedEventArgs#eventType:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onexited-event.yaml + const comparedLocation = firstParagraphAsRange.compareLocationWith(secondParagraphAsRange); - async function contentControlExited(event: - Word.ContentControlExitedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. ID of content control that was exited: ${event.ids[0]}`); - }); - } -'Word.ContentControlExitedEventArgs#ids:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onexited-event.yaml + await context.sync(); - async function contentControlExited(event: - Word.ContentControlExitedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. ID of content control that was exited: ${event.ids[0]}`); - }); - } -'Word.ContentControlSelectionChangedEventArgs#eventType:member': + const locationValue: Word.LocationRelation = comparedLocation.value; + console.log(`Location of the first paragraph in relation to the second paragraph: ${locationValue}`); + }); +Word.NoteItem:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onselectionchanged-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml - async function contentControlSelectionChanged(event: - Word.ContentControlSelectionChangedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls where selection was changed:`); - console.log(event.ids); - }); - } -'Word.ContentControlSelectionChangedEventArgs#ids:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onselectionchanged-event.yaml - async function contentControlSelectionChanged(event: - Word.ContentControlSelectionChangedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls where selection was changed:`); - console.log(event.ids); - }); - } -'Word.CustomProperty:class': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml + // Gets the text of the referenced footnote. await Word.run(async (context) => { - const properties = context.document.properties.customProperties; - properties.load("key,type,value"); + const footnotes: Word.NoteItemCollection = context.document.body.footnotes; + footnotes.load("items/body"); + await context.sync(); - await context.sync(); - for (let i = 0; i < properties.items.length; i++) - console.log("Property Name:" + properties.items[i].key + "; Type=" + properties.items[i].type + "; Property Value=" + properties.items[i].value); + const referenceNumber = (document.getElementById("input-reference") as HTMLInputElement).value; + const mark = (referenceNumber as number) - 1; + const footnoteBody: Word.Range = footnotes.items[mark].body.getRange(); + footnoteBody.load("text"); + await context.sync(); + + console.log(`Text of footnote ${referenceNumber}: ${footnoteBody.text}`); }); -'Word.CustomPropertyCollection#add:member(1)': +Word.NoteItem#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + + + // Deletes this referenced footnote. await Word.run(async (context) => { - context.document.properties.customProperties.add("Numeric Property", 1234); + const footnotes: Word.NoteItemCollection = context.document.body.footnotes; + footnotes.load("items"); + await context.sync(); - await context.sync(); - console.log("Property added"); + const referenceNumber = (document.getElementById("input-reference") as HTMLInputElement).value; + const mark = (referenceNumber as number) - 1; + footnotes.items[mark].delete(); + await context.sync(); + + console.log("Footnote deleted."); }); +Word.NoteItem#getNext:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + + + // Selects the next footnote in the document body. await Word.run(async (context) => { - context.document.properties.customProperties.add("String Property", "Hello World!"); + const footnotes: Word.NoteItemCollection = context.document.body.footnotes; + footnotes.load("items/reference"); + await context.sync(); - await context.sync(); - console.log("Property added"); + const referenceNumber = (document.getElementById("input-reference") as HTMLInputElement).value; + const mark = (referenceNumber as number) - 1; + const reference: Word.Range = footnotes.items[mark].getNext().reference; + reference.select(); + console.log("Selected is the next footnote: " + (mark + 2)); }); -'Word.CustomPropertyCollection#items:member': +Word.NoteItem#body:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + + + // Gets the text of the referenced footnote. await Word.run(async (context) => { - const properties = context.document.properties.customProperties; - properties.load("key,type,value"); + const footnotes: Word.NoteItemCollection = context.document.body.footnotes; + footnotes.load("items/body"); + await context.sync(); - await context.sync(); - for (let i = 0; i < properties.items.length; i++) - console.log("Property Name:" + properties.items[i].key + "; Type=" + properties.items[i].type + "; Property Value=" + properties.items[i].value); + const referenceNumber = (document.getElementById("input-reference") as HTMLInputElement).value; + const mark = (referenceNumber as number) - 1; + const footnoteBody: Word.Range = footnotes.items[mark].body.getRange(); + footnoteBody.load("text"); + await context.sync(); + + console.log(`Text of footnote ${referenceNumber}: ${footnoteBody.text}`); }); -'Word.CustomXmlPart#delete:member(1)': +Word.NoteItem#reference:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml - // Deletes a custom XML part. + + // Selects the footnote's reference mark in the document body. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); + const footnotes: Word.NoteItemCollection = context.document.body.footnotes; + footnotes.load("items/reference"); await context.sync(); - if (xmlPartIDSetting.value) { - let customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); - const xmlBlob = customXmlPart.getXml(); - customXmlPart.delete(); - customXmlPart = context.document.customXmlParts.getItemOrNullObject(xmlPartIDSetting.value); + const referenceNumber = (document.getElementById("input-reference") as HTMLInputElement).value; + const mark = (referenceNumber as number) - 1; + const item: Word.NoteItem = footnotes.items[mark]; + const reference: Word.Range = item.reference; + reference.select(); + await context.sync(); - await context.sync(); + console.log(`Reference ${referenceNumber} is selected.`); + }); +Word.NoteItem#type:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml - if (customXmlPart.isNullObject) { - console.log(`The XML part with the ID ${xmlPartIDSetting.value} has been deleted`); - // Delete the associated setting too. - xmlPartIDSetting.delete(); + // Gets the referenced note's item type and body type, which are both + "Footnote". - await context.sync(); - } else { - const readableXml = addLineBreaksToXML(xmlBlob.value); - const strangeMessage = `This is strange. The XML part with the id ${xmlPartIDSetting.value} wasn't deleted:\n${readableXml}`; - console.error(strangeMessage); - } - } else { - console.warn("Didn't find custom XML part to delete"); - } + await Word.run(async (context) => { + const footnotes: Word.NoteItemCollection = context.document.body.footnotes; + footnotes.load("items"); + await context.sync(); + + const referenceNumber = (document.getElementById("input-reference") as HTMLInputElement).value; + const mark = (referenceNumber as number) - 1; + const item: Word.NoteItem = footnotes.items[mark]; + console.log(`Note type of footnote ${referenceNumber}: ${item.type}`); + + item.body.load("type"); + await context.sync(); + + console.log(`Body type of note: ${item.body.type}`); }); -'Word.CustomXmlPart#getXml:member(1)': +Word.NoteItemCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml - // Adds a custom XML part. - await Word.run(async (context) => { - const originalXml = - "JuanHongSally"; - const customXmlPart = context.document.customXmlParts.add(originalXml); - customXmlPart.load("id"); - const xmlBlob = customXmlPart.getXml(); + // Gets the first footnote in the document body and select its reference + mark. - await context.sync(); + await Word.run(async (context) => { + const reference: Word.Range = context.document.body.footnotes.getFirst().reference; + reference.select(); + console.log("The first footnote is selected."); + }); +Word.NoteItemCollection#getFirst:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml - const readableXml = addLineBreaksToXML(xmlBlob.value); - console.log("Added custom XML part:"); - console.log(readableXml); - // Store the XML part's ID in a setting so the ID is available to other functions. - const settings = context.document.settings; - settings.add("ContosoReviewXmlPartId", customXmlPart.id); + // Gets the first footnote in the document body and select its reference + mark. - await context.sync(); + await Word.run(async (context) => { + const reference: Word.Range = context.document.body.footnotes.getFirst().reference; + reference.select(); + console.log("The first footnote is selected."); }); -'Word.CustomXmlPart#insertAttribute:member(1)': +Word.NoteItemType:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml - // Inserts an attribute into a custom XML part. + + // Gets the referenced note's item type and body type, which are both + "Footnote". await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); + const footnotes: Word.NoteItemCollection = context.document.body.footnotes; + footnotes.load("items"); await context.sync(); - if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + const referenceNumber = (document.getElementById("input-reference") as HTMLInputElement).value; + const mark = (referenceNumber as number) - 1; + const item: Word.NoteItem = footnotes.items[mark]; + console.log(`Note type of footnote ${referenceNumber}: ${item.type}`); - // The insertAttribute method inserts an attribute with the given name and value into the element identified by the xpath parameter. - customXmlPart.insertAttribute("/Reviewers", { contoso: "http://schemas.contoso.com/review/1.0" }, "Nation", "US"); - const xmlBlob = customXmlPart.getXml(); - await context.sync(); + item.body.load("type"); + await context.sync(); - const readableXml = addLineBreaksToXML(xmlBlob.value); - console.log("Successfully inserted attribute:"); - console.log(readableXml); - } else { - console.warn("Didn't find custom XML part to insert attribute into"); - } + console.log(`Body type of note: ${item.body.type}`); }); -'Word.CustomXmlPart#insertElement:member(1)': +Word.OutlineLevel:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-custom-style.yaml - // Inserts an element into a custom XML part. - await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); - await context.sync(); + // Imports styles from JSON. - if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); + await Word.run(async (context) => { + const str = + '{"styles":[{"baseStyle":"Default Paragraph Font","builtIn":false,"inUse":true,"linked":false,"nameLocal":"NewCharStyle","priority":2,"quickStyle":true,"type":"Character","unhideWhenUsed":false,"visibility":false,"paragraphFormat":null,"font":{"name":"DengXian Light","size":16.0,"bold":true,"italic":false,"color":"#F1A983","underline":"None","subscript":false,"superscript":true,"strikeThrough":true,"doubleStrikeThrough":false,"highlightColor":null,"hidden":false},"shading":{"backgroundPatternColor":"#FF0000"}},{"baseStyle":"Normal","builtIn":false,"inUse":true,"linked":false,"nextParagraphStyle":"NewParaStyle","nameLocal":"NewParaStyle","priority":1,"quickStyle":true,"type":"Paragraph","unhideWhenUsed":false,"visibility":false,"paragraphFormat":{"alignment":"Centered","firstLineIndent":0.0,"keepTogether":false,"keepWithNext":false,"leftIndent":72.0,"lineSpacing":18.0,"lineUnitAfter":0.0,"lineUnitBefore":0.0,"mirrorIndents":false,"outlineLevel":"OutlineLevelBodyText","rightIndent":72.0,"spaceAfter":30.0,"spaceBefore":30.0,"widowControl":true},"font":{"name":"DengXian","size":14.0,"bold":true,"italic":true,"color":"#8DD873","underline":"Single","subscript":false,"superscript":false,"strikeThrough":false,"doubleStrikeThrough":true,"highlightColor":null,"hidden":false},"shading":{"backgroundPatternColor":"#00FF00"}},{"baseStyle":"Table Normal","builtIn":false,"inUse":true,"linked":false,"nextParagraphStyle":"NewTableStyle","nameLocal":"NewTableStyle","priority":100,"type":"Table","unhideWhenUsed":false,"visibility":false,"paragraphFormat":{"alignment":"Left","firstLineIndent":0.0,"keepTogether":false,"keepWithNext":false,"leftIndent":0.0,"lineSpacing":12.0,"lineUnitAfter":0.0,"lineUnitBefore":0.0,"mirrorIndents":false,"outlineLevel":"OutlineLevelBodyText","rightIndent":0.0,"spaceAfter":0.0,"spaceBefore":0.0,"widowControl":true},"font":{"name":"DengXian","size":20.0,"bold":false,"italic":true,"color":"#D86DCB","underline":"None","subscript":false,"superscript":false,"strikeThrough":false,"doubleStrikeThrough":false,"highlightColor":null,"hidden":false},"tableStyle":{"allowBreakAcrossPage":true,"alignment":"Left","bottomCellMargin":0.0,"leftCellMargin":0.08,"rightCellMargin":0.08,"topCellMargin":0.0,"cellSpacing":0.0},"shading":{"backgroundPatternColor":"#60CAF3"}}]}'; + const styles = context.document.importStylesFromJson(str); - // The insertElement method inserts the given XML under the parent element identified by the xpath parameter at the provided child position index. - customXmlPart.insertElement( - "/Reviewers", - "Mark", - { contoso: "http://schemas.contoso.com/review/1.0" }, - 0 - ); - const xmlBlob = customXmlPart.getXml(); - await context.sync(); + // If you'd like to set how conflicting styles are handled, use the importedStylesConflictBehavior parameter that was introduced in the Desktop 1.1 requirement set. "Ignore" is the default. + ////const styles = context.document.importStylesFromJson(str, Word.ImportedStylesConflictBehavior.Ignore); - const readableXml = addLineBreaksToXML(xmlBlob.value); - console.log("Successfully inserted element:"); - console.log(readableXml); - } else { - console.warn("Didn't find custom XML part to insert element into"); - } + await context.sync(); + console.log("Styles imported from JSON:", styles); }); -'Word.CustomXmlPart#query:member(1)': +Word.Page:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml - // Queries a custom XML part for elements matching the search terms. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); - + // Gets pages of the selection. + const pages: Word.PageCollection = context.document.getSelection().pages; + pages.load(); await context.sync(); - if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); - const xpathToQueryFor = "/Reviewers/Reviewer"; - const clientResult = customXmlPart.query(xpathToQueryFor, { - contoso: "http://schemas.contoso.com/review/1.0" - }); + // Log info for pages included in selection. + console.log(pages); + const pagesIndexes = []; + const pagesText = []; + for (let i = 0; i < pages.items.length; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); - await context.sync(); + const range = page.getRange(); + range.load("text"); + pagesText.push(range); + } - console.log(`Queried custom XML part for ${xpathToQueryFor} and found ${clientResult.value.length} matches:`); - for (let i = 0; i < clientResult.value.length; i++) { - console.log(clientResult.value[i]); - } - } else { - console.warn("Didn't find custom XML part to query"); + await context.sync(); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Index info for page ${i + 1} in the selection: ${pagesIndexes[i].index}`); + console.log("Text of that page in the selection:", pagesText[i].text); } }); -'Word.CustomXmlPart#setXml:member(1)': +Word.Page#getRange:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml - // Replaces a custom XML part. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); + // Gets pages of the selection. + const pages: Word.PageCollection = context.document.getSelection().pages; + pages.load(); await context.sync(); - if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); - const originalXmlBlob = customXmlPart.getXml(); - await context.sync(); + // Log info for pages included in selection. + console.log(pages); + const pagesIndexes = []; + const pagesText = []; + for (let i = 0; i < pages.items.length; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); - let readableXml = addLineBreaksToXML(originalXmlBlob.value); - console.log("Original custom XML part:"); - console.log(readableXml); + const range = page.getRange(); + range.load("text"); + pagesText.push(range); + } - // The setXml method replaces the entire XML part. - customXmlPart.setXml( - "JohnHitomi" - ); - const updatedXmlBlob = customXmlPart.getXml(); - await context.sync(); + await context.sync(); - readableXml = addLineBreaksToXML(updatedXmlBlob.value); - console.log("Replaced custom XML part:"); - console.log(readableXml); - } else { - console.warn("Didn't find custom XML part to replace"); + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Index info for page ${i + 1} in the selection: ${pagesIndexes[i].index}`); + console.log("Text of that page in the selection:", pagesText[i].text); } }); -'Word.CustomXmlPart#id:member': +Word.Page#index:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml - // Adds a custom XML part. await Word.run(async (context) => { - const originalXml = - "JuanHongSally"; - const customXmlPart = context.document.customXmlParts.add(originalXml); - customXmlPart.load("id"); - const xmlBlob = customXmlPart.getXml(); + // Gets the pages that contain the third paragraph. + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load(); + await context.sync(); + const paraThree = paragraphs.items[2]; + const rangeOfParagraph = paraThree.getRange(); + const pages: Word.PageCollection = rangeOfParagraph.pages; + pages.load(); await context.sync(); - const readableXml = addLineBreaksToXML(xmlBlob.value); - console.log("Added custom XML part:"); - console.log(readableXml); + // Log info for pages in range. + console.log(pages); + const pagesIndexes = []; + const pagesText = []; + for (let i = 0; i < pages.items.length; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); - // Store the XML part's ID in a setting so the ID is available to other functions. - const settings = context.document.settings; - settings.add("ContosoReviewXmlPartId", customXmlPart.id); + const range = page.getRange(); + range.load("text"); + pagesText.push(range); + } await context.sync(); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Index of page ${i + 1} that contains the third paragraph: ${pagesIndexes[i].index}`); + console.log("Text of that page:", pagesText[i].text); + } }); -'Word.CustomXmlPart#namespaceUri:member': +Word.PageCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml - // Gets the namespace URI from a custom XML part. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartIdNS").load("value"); - + // Gets pages of the selection. + const pages: Word.PageCollection = context.document.getSelection().pages; + pages.load(); await context.sync(); - if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); - customXmlPart.load("namespaceUri"); - await context.sync(); + // Log info for pages included in selection. + console.log(pages); + const pagesIndexes = []; + const pagesText = []; + for (let i = 0; i < pages.items.length; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); - const namespaceUri = customXmlPart.namespaceUri; - console.log(`Namespace URI: ${JSON.stringify(namespaceUri)}`); - } else { - console.warn("Didn't find custom XML part"); + const range = page.getRange(); + range.load("text"); + pagesText.push(range); + } + + await context.sync(); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Index info for page ${i + 1} in the selection: ${pagesIndexes[i].index}`); + console.log("Text of that page in the selection:", pagesText[i].text); } }); -'Word.CustomXmlPartCollection#add:member(1)': +Word.Pane:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml - // Adds a custom XML part. await Word.run(async (context) => { - const originalXml = - "JuanHongSally"; - const customXmlPart = context.document.customXmlParts.add(originalXml); - customXmlPart.load("id"); - const xmlBlob = customXmlPart.getXml(); + // Gets the first paragraph of each page. + console.log("Getting first paragraph of each page..."); + + // Get the active window. + const activeWindow: Word.Window = context.document.activeWindow; + activeWindow.load(); + + // Get the active pane. + const activePane: Word.Pane = activeWindow.activePane; + activePane.load(); + + // Get all pages. + const pages: Word.PageCollection = activePane.pages; + pages.load(); await context.sync(); - const readableXml = addLineBreaksToXML(xmlBlob.value); - console.log("Added custom XML part:"); - console.log(readableXml); + // Get page index and paragraphs of each page. + const pagesIndexes = []; + const pagesNumberOfParagraphs = []; + const pagesFirstParagraphText = []; + for (let i = 0; i < pages.items.length; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); - // Store the XML part's ID in a setting so the ID is available to other functions. - const settings = context.document.settings; - settings.add("ContosoReviewXmlPartId", customXmlPart.id); + const paragraphs = page.getRange().paragraphs; + paragraphs.load("items/length"); + pagesNumberOfParagraphs.push(paragraphs); + + const firstParagraph = paragraphs.getFirst(); + firstParagraph.load("text"); + pagesFirstParagraphText.push(firstParagraph); + } await context.sync(); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Page index: ${pagesIndexes[i].index}`); + console.log(`Number of paragraphs: ${pagesNumberOfParagraphs[i].items.length}`); + console.log("First paragraph's text:", pagesFirstParagraphText[i].text); + } }); -'Word.CustomXmlPartCollection#getItem:member(1)': +Word.Pane#pages:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml - // Queries a custom XML part for elements matching the search terms. await Word.run(async (context) => { - const settings = context.document.settings; - const xmlPartIDSetting = settings.getItemOrNullObject("ContosoReviewXmlPartId").load("value"); + // Gets the first paragraph of each page. + console.log("Getting first paragraph of each page..."); + + // Get the active window. + const activeWindow: Word.Window = context.document.activeWindow; + activeWindow.load(); + + // Get the active pane. + const activePane: Word.Pane = activeWindow.activePane; + activePane.load(); + + // Get all pages. + const pages: Word.PageCollection = activePane.pages; + pages.load(); await context.sync(); - if (xmlPartIDSetting.value) { - const customXmlPart = context.document.customXmlParts.getItem(xmlPartIDSetting.value); - const xpathToQueryFor = "/Reviewers/Reviewer"; - const clientResult = customXmlPart.query(xpathToQueryFor, { - contoso: "http://schemas.contoso.com/review/1.0" - }); + // Get page index and paragraphs of each page. + const pagesIndexes = []; + const pagesNumberOfParagraphs = []; + const pagesFirstParagraphText = []; + for (let i = 0; i < pages.items.length; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); - await context.sync(); + const paragraphs = page.getRange().paragraphs; + paragraphs.load("items/length"); + pagesNumberOfParagraphs.push(paragraphs); - console.log(`Queried custom XML part for ${xpathToQueryFor} and found ${clientResult.value.length} matches:`); - for (let i = 0; i < clientResult.value.length; i++) { - console.log(clientResult.value[i]); - } - } else { - console.warn("Didn't find custom XML part to query"); + const firstParagraph = paragraphs.getFirst(); + firstParagraph.load("text"); + pagesFirstParagraphText.push(firstParagraph); + } + + await context.sync(); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Page index: ${pagesIndexes[i].index}`); + console.log(`Number of paragraphs: ${pagesNumberOfParagraphs[i].items.length}`); + console.log("First paragraph's text:", pagesFirstParagraphText[i].text); } }); -'Word.Document#addStyle:member(1)': +Word.Pane#pagesEnclosingViewport:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml - // Adds a new style. await Word.run(async (context) => { - const newStyleName = $("#new-style-name").val() as string; - if (newStyleName == "") { - console.warn("Enter a style name to add."); - return; - } + // Gets the pages enclosing the viewport. + + // Get the active window. + const activeWindow: Word.Window = context.document.activeWindow; + activeWindow.load(); + + // Get the active pane. + const activePane: Word.Pane = activeWindow.activePane; + activePane.load(); + + // Get pages enclosing the viewport. + const pages: Word.PageCollection = activePane.pagesEnclosingViewport; + pages.load(); - const style = context.document.getStyles().getByNameOrNullObject(newStyleName); - style.load(); await context.sync(); - if (!style.isNullObject) { - console.warn( - `There's an existing style with the same name '${newStyleName}'! Please provide another style name.` - ); - return; + // Log the number of pages. + const pageCount = pages.items.length; + console.log(`Number of pages enclosing the viewport: ${pageCount}`); + + // Log index info of these pages. + const pagesIndexes = []; + for (let i = 0; i < pageCount; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); } - const newStyleType = ($("#new-style-type").val() as unknown) as Word.StyleType; - context.document.addStyle(newStyleName, newStyleType); await context.sync(); - - console.log(newStyleName + " has been added to the style list."); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Page index: ${pagesIndexes[i].index}`); + } }); -'Word.Document#getStyles:member(1)': +Word.PaneCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml - // Gets the number of styles. await Word.run(async (context) => { - const styles = context.document.getStyles(); - const count = styles.getCount(); + // Gets all the panes in the active document window. + + // Get the active window. + const activeWindow: Word.Window = context.document.activeWindow; + activeWindow.load("panes/items/length"); + await context.sync(); - console.log(`Number of styles: ${count.value}`); + const panes: Word.PaneCollection = activeWindow.panes; + console.log(`Number of panes in the current document window: ${panes.items.length}`); }); -'Word.Document#changeTrackingMode:member': +Word.Paragraph:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-change-tracking.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml - // Gets the current change tracking mode. await Word.run(async (context) => { - const document = context.document; - document.load("changeTrackingMode"); - await context.sync(); + // The collection of paragraphs of the current selection returns the full paragraphs contained in it. + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + paragraph.load("text"); - if (document.changeTrackingMode === Word.ChangeTrackingMode.trackMineOnly) { - console.log("Only my changes are being tracked."); - } else if (document.changeTrackingMode === Word.ChangeTrackingMode.trackAll) { - console.log("Everyone's changes are being tracked."); - } else { - console.log("No changes are being tracked."); - } + await context.sync(); + console.log(paragraph.text); }); -'Word.Document#onContentControlAdded:member': +Word.Paragraph#getRange:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onadded-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml - // Registers the onAdded event handler on the document. await Word.run(async (context) => { - eventContext = context.document.onContentControlAdded.add(contentControlAdded); + // Get the complete sentence (as range) associated with the insertion point. + const sentences: Word.RangeCollection = context.document + .getSelection() + .getTextRanges(["."] /* Using the "." as delimiter */, false /*means without trimming spaces*/); + sentences.load("$none"); await context.sync(); - console.log("Added event handler for when content controls are added."); + // Expand the range to the end of the paragraph to get all the complete sentences. + const sentencesToTheEndOfParagraph: Word.RangeCollection = sentences.items[0] + .getRange() + .expandTo( + context.document + .getSelection() + .paragraphs.getFirst() + .getRange(Word.RangeLocation.end) + ) + .getTextRanges(["."], false /* Don't trim spaces*/); + sentencesToTheEndOfParagraph.load("text"); + await context.sync(); + + for (let i = 0; i < sentencesToTheEndOfParagraph.items.length; i++) { + console.log(sentencesToTheEndOfParagraph.items[i].text); + } }); +Word.Paragraph#insertAnnotations:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onadded-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - async function contentControlAdded(event: Word.ContentControlAddedEventArgs) - { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls that were added:`); - console.log(event.ids); - }); - } -'Word.Document#properties:member': + + // Adds annotations to the selected paragraph. + + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const options: Word.CritiquePopupOptions = { + brandingTextResourceId: "PG.TabLabel", + subtitleResourceId: "PG.HelpCommand.TipTitle", + titleResourceId: "PG.HelpCommand.Label", + suggestions: ["suggestion 1", "suggestion 2", "suggestion 3"] + }; + const critique1: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.red, + start: 1, + length: 3, + popupOptions: options + }; + const critique2: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.green, + start: 6, + length: 1, + popupOptions: options + }; + const critique3: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.blue, + start: 10, + length: 3, + popupOptions: options + }; + const critique4: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.lavender, + start: 14, + length: 3, + popupOptions: options + }; + const critique5: Word.Critique = { + colorScheme: Word.CritiqueColorScheme.berry, + start: 18, + length: 10, + popupOptions: options + }; + const annotationSet: Word.AnnotationSet = { + critiques: [critique1, critique2, critique3, critique4, critique5] + }; + + const annotationIds = paragraph.insertAnnotations(annotationSet); + + await context.sync(); + + console.log("Annotations inserted:", annotationIds.value); + }); +Word.Paragraph#insertBreak:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/get-built-in-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-line-and-page-breaks.yaml - await Word.run(async (context) => { - const builtInProperties = context.document.properties; - builtInProperties.load("*"); // Let's get all! - await context.sync(); - console.log(JSON.stringify(builtInProperties, null, 4)); + Word.run(async (context) => { + context.document.body.paragraphs.getFirst().insertBreak(Word.BreakType.line, "After"); + + await context.sync(); + console.log("success"); }); -'Word.Document#settings:member': +Word.Paragraph#insertContentControl:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-settings.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-content-controls.yaml - // Gets all custom settings this add-in set on this document. + + // Traverses each paragraph of the document and wraps a content control on + each with either a even or odd tags. await Word.run(async (context) => { - const settings = context.document.settings; - settings.load("items"); + let paragraphs = context.document.body.paragraphs; + paragraphs.load("$none"); // Don't need any properties; just wrap each paragraph with a content control. + await context.sync(); - if (settings.items.length == 0) { - console.log("There are no settings"); - } else { - console.log("All settings:"); - for (let i = 0; i < settings.items.length; i++) { - console.log(settings.items[i]); + for (let i = 0; i < paragraphs.items.length; i++) { + let contentControl = paragraphs.items[i].insertContentControl(); + // For even, tag "even". + if (i % 2 === 0) { + contentControl.tag = "even"; + } else { + contentControl.tag = "odd"; } } + console.log("Content controls inserted: " + paragraphs.items.length); + + await context.sync(); }); -'Word.DocumentCreated:class': +Word.Paragraph#insertText:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-external-document.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-in-different-locations.yaml - // Updates the text of the current document with the text from another - document passed in as a Base64-encoded string. await Word.run(async (context) => { - // Use the Base64-encoded string representation of the selected .docx file. - const externalDoc = context.application.createDocument(externalDocument); + // Replace the last paragraph. + const range: Word.Range = context.document.body.paragraphs.getLast().insertText("Just replaced the last paragraph!", "Replace"); + range.font.highlightColor = "black"; + range.font.color = "white"; + await context.sync(); + }); +Word.Paragraph#insertTextBox:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml - const externalDocBody = externalDoc.body; - externalDocBody.load("text"); + + await Word.run(async (context) => { + // Inserts a text box at the beginning of the first paragraph in header. + const headerFooterBody: Word.Body = context.document.sections.getFirst().getHeader(Word.HeaderFooterType.primary); + headerFooterBody.load("paragraphs"); + const firstParagraph: Word.Paragraph = headerFooterBody.paragraphs.getFirst(); + const insertShapeOptions: Word.InsertShapeOptions = { + top: 0, + left: 0, + height: 100, + width: 100 + }; + const newTextBox: Word.Shape = firstParagraph.insertTextBox("placeholder text", insertShapeOptions); + newTextBox.select(); await context.sync(); - // Insert the external document's text at the beginning of the current document's body. - const externalDocBodyText = externalDocBody.text; - const currentDocBody = context.document.body; - currentDocBody.insertText(externalDocBodyText, Word.InsertLocation.start); + console.log("Inserted a text box at the beginning of the first paragraph in the header."); + }); +Word.Paragraph#select:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/scroll-to-range.yaml + + + await Word.run(async (context) => { + // If select is called with no parameters, it selects the object. + context.document.body.paragraphs.getLast().select(); + await context.sync(); }); -'Word.DocumentPropertyType:enum': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/scroll-to-range.yaml + await Word.run(async (context) => { - const properties = context.document.properties.customProperties; - properties.load("key,type,value"); + // Select can be at the start or end of a range; this by definition moves the insertion point without selecting the range. + context.document.body.paragraphs.getLast().select(Word.SelectionMode.end); - await context.sync(); - for (let i = 0; i < properties.items.length; i++) - console.log("Property Name:" + properties.items[i].key + "; Type=" + properties.items[i].type + "; Property Value=" + properties.items[i].value); + await context.sync(); }); -'Word.EventType:enum': +Word.Paragraph#set:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/multiple-property-set.yaml - async function contentControlDeleted(event: - Word.ContentControlDeletedEventArgs) { - await Word.run(async (context) => { - console.log(`${event.eventType} event detected. IDs of content controls that were deleted:`); - console.log(event.ids); + + await Word.run(async (context) => { + const paragraph: Word.Paragraph = context.document.body.paragraphs.getFirst(); + paragraph.set({ + leftIndent: 30, + font: { + bold: true, + color: "red" + } }); - } -'Word.Field#delete:member(1)': + + await context.sync(); + }); - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/multiple-property-set.yaml - // Deletes the first field in the document. await Word.run(async (context) => { - const field = context.document.body.fields.getFirstOrNullObject(); - field.load(); + const firstParagraph: Word.Paragraph = context.document.body.paragraphs.getFirst(); + const secondParagraph: Word.Paragraph = firstParagraph.getNext(); + firstParagraph.load("text, font/color, font/bold, leftIndent"); await context.sync(); - if (field.isNullObject) { - console.log("This document has no fields."); - } else { - field.delete(); - await context.sync(); + secondParagraph.set(firstParagraph); - console.log("The first field in the document was deleted."); - } + await context.sync(); }); -'Word.Field#select:member(1)': +Word.Paragraph#split:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/split-words-of-first-paragraph.yaml - // Gets and updates the first field in the selection. await Word.run(async (context) => { - var field = context.document.getSelection().fields.getFirstOrNullObject(); - field.load(["code", "result", "type", "locked"]); + const paragraph: Word.Paragraph = context.document.body.paragraphs.getFirst(); + const words = paragraph.split([" "], true /* trimDelimiters*/, true /* trimSpaces */); + words.load("text"); await context.sync(); - if (field.isNullObject) { - console.log("No field in selection."); - } else { - console.log("Before updating:"); - console.log("Code of first field: " + field.code); - console.log("Result of first field: " + JSON.stringify(field.result)); - - field.updateResult(); - field.select(); - await context.sync(); + for (let i = 0; i < words.items.length; i++) { + if (i >= 1) { + words.items[i - 1].font.highlightColor = "#FFFFFF"; + } + words.items[i].font.highlightColor = "#FFFF00"; - field.load(["code", "result"]); await context.sync(); - - console.log("After updating:"); - console.log("Code of first field: " + field.code); - console.log("Result of first field: " + JSON.stringify(field.result)); + await pause(200); } }); -'Word.Field#updateResult:member(1)': +Word.Paragraph#startNewList:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/insert-list.yaml - // Gets and updates the first field in the selection. + + // This example starts a new list with the second paragraph. await Word.run(async (context) => { - var field = context.document.getSelection().fields.getFirstOrNullObject(); - field.load(["code", "result", "type", "locked"]); + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("$none"); await context.sync(); - if (field.isNullObject) { - console.log("No field in selection."); - } else { - console.log("Before updating:"); - console.log("Code of first field: " + field.code); - console.log("Result of first field: " + JSON.stringify(field.result)); - - field.updateResult(); - field.select(); - await context.sync(); + // Start new list using the second paragraph. + const list: Word.List = paragraphs.items[1].startNewList(); + list.load("$none"); - field.load(["code", "result"]); - await context.sync(); + await context.sync(); - console.log("After updating:"); - console.log("Code of first field: " + field.code); - console.log("Result of first field: " + JSON.stringify(field.result)); - } - }); -'Word.Field#code:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + // To add new items to the list, use Start or End on the insertLocation parameter. + list.insertParagraph("New list item at the start of the list", "Start"); + const paragraph: Word.Paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); - // Gets the first field in the document. + // Set up list level for the list item. + paragraph.listItem.level = 4; - await Word.run(async (context) => { - const field = context.document.body.fields.getFirstOrNullObject(); - field.load(["code", "result", "locked", "type", "data", "kind"]); + // To add paragraphs outside the list, use Before or After. + list.insertParagraph("New paragraph goes after (not part of the list)", "After"); await context.sync(); - - if (field.isNullObject) { - console.log("This document has no fields."); - } else { - console.log("Code of first field: " + field.code); - console.log("Result of first field: " + JSON.stringify(field.result)); - console.log("Type of first field: " + field.type); - console.log("Is the first field locked? " + field.locked); - console.log("Kind of the first field: " + field.kind); - } }); -'Word.Field#kind:member': +Word.Paragraph#alignment:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml - // Gets the first field in the document. await Word.run(async (context) => { - const field = context.document.body.fields.getFirstOrNullObject(); - field.load(["code", "result", "locked", "type", "data", "kind"]); + // Center last paragraph alignment. + context.document.body.paragraphs.getLast().alignment = "Centered"; await context.sync(); - - if (field.isNullObject) { - console.log("This document has no fields."); - } else { - console.log("Code of first field: " + field.code); - console.log("Result of first field: " + JSON.stringify(field.result)); - console.log("Type of first field: " + field.type); - console.log("Is the first field locked? " + field.locked); - console.log("Kind of the first field: " + field.kind); - } }); -'Word.Field#locked:member': +Word.Paragraph#leftIndent:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml - // Gets the first field in the selection and toggles between setting it to - locked or unlocked. await Word.run(async (context) => { - var field = context.document.getSelection().fields.getFirstOrNullObject(); - field.load(["code", "result", "type", "locked"]); - await context.sync(); - - if (field.isNullObject) { - console.log("The selection has no fields."); - } else { - console.log(`The first field in the selection is currently ${field.locked ? "locked" : "unlocked"}.`); - field.locked = !field.locked; - await context.sync(); + // Indent the first paragraph. + context.document.body.paragraphs.getFirst().leftIndent = 75; //units = points - console.log(`The first field in the selection is now ${field.locked ? "locked" : "unlocked"}.`); - } + return context.sync(); }); -'Word.Field#parentBody:member': +Word.Paragraph#lineSpacing:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml - // Gets the parent body of the first field in the document. await Word.run(async (context) => { - const field = context.document.body.fields.getFirstOrNullObject(); - field.load("parentBody/text"); + // Adjust line spacing. + context.document.body.paragraphs.getFirst().lineSpacing = 20; await context.sync(); - - if (field.isNullObject) { - console.log("This document has no fields."); - } else { - const parentBody = field.parentBody; - console.log("Text of first field's parent body: " + JSON.stringify(parentBody.text)); - } }); -'Word.Field#result:member': +Word.Paragraph#lineUnitAfter:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml - // Gets the first field in the document. await Word.run(async (context) => { - const field = context.document.body.fields.getFirstOrNullObject(); - field.load(["code", "result", "locked", "type", "data", "kind"]); + // Set the space (in line units) after the first paragraph. + context.document.body.paragraphs.getFirst().lineUnitAfter = 1; await context.sync(); - - if (field.isNullObject) { - console.log("This document has no fields."); - } else { - console.log("Code of first field: " + field.code); - console.log("Result of first field: " + JSON.stringify(field.result)); - console.log("Type of first field: " + field.type); - console.log("Is the first field locked? " + field.locked); - console.log("Kind of the first field: " + field.kind); - } }); -'Word.Field#type:member': +Word.Paragraph#lineUnitBefore:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml - // Gets the first field in the document. await Word.run(async (context) => { - const field = context.document.body.fields.getFirstOrNullObject(); - field.load(["code", "result", "locked", "type", "data", "kind"]); + // Set the space (in line units) before the first paragraph. + context.document.body.paragraphs.getFirst().lineUnitBefore = 1; await context.sync(); - - if (field.isNullObject) { - console.log("This document has no fields."); - } else { - console.log("Code of first field: " + field.code); - console.log("Result of first field: " + JSON.stringify(field.result)); - console.log("Type of first field: " + field.type); - console.log("Is the first field locked? " + field.locked); - console.log("Kind of the first field: " + field.kind); - } }); -'Word.FieldCollection#getFirstOrNullObject:member(1)': +Word.Paragraph#spaceAfter:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml - // Gets the first field in the document. await Word.run(async (context) => { - const field = context.document.body.fields.getFirstOrNullObject(); - field.load(["code", "result", "locked", "type", "data", "kind"]); + // Set the space (in points) after the first paragraph. + context.document.body.paragraphs.getFirst().spaceAfter = 20; await context.sync(); - - if (field.isNullObject) { - console.log("This document has no fields."); - } else { - console.log("Code of first field: " + field.code); - console.log("Result of first field: " + JSON.stringify(field.result)); - console.log("Type of first field: " + field.type); - console.log("Is the first field locked? " + field.locked); - console.log("Kind of the first field: " + field.kind); - } }); -'Word.FieldCollection#items:member': +Word.Paragraph#style:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Gets all fields in the document body. + + // Applies the specified style to a paragraph. await Word.run(async (context) => { - const fields = context.document.body.fields.load("items"); + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to apply."); + return; + } + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); await context.sync(); - if (fields.items.length === 0) { - console.log("No fields in this document."); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else if (style.type != Word.StyleType.paragraph) { + console.log(`The '${styleName}' style isn't a paragraph style.`); } else { - fields.load(["code", "result"]); - await context.sync(); - - for (let i = 0; i < fields.items.length; i++) { - console.log(`Field ${i + 1}'s code: ${fields.items[i].code}`); - console.log(`Field ${i + 1}'s result: ${JSON.stringify(fields.items[i].result)}`); - } + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph( + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", + "Start" + ); + const paragraph: Word.Paragraph = body.paragraphs.getFirst(); + paragraph.style = style.nameLocal; + console.log(`'${styleName}' style applied to first paragraph.`); } }); -'Word.FieldType:enum': +Word.Paragraph#styleBuiltIn:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/doc-assembly.yaml - // Inserts a Date field before selection. await Word.run(async (context) => { - var range = context.document.getSelection().getRange(); - - const field = range.insertField(Word.InsertLocation.before, Word.FieldType.date, '\\@ "M/d/yyyy h:mm am/pm"', true); - - field.load("result,code"); - await context.sync(); + const paragraph: Word.Paragraph = context.document.body.insertParagraph("Timeline", "End"); + paragraph.styleBuiltIn = "Heading2"; + const paragraph2: Word.Paragraph = context.document.body.insertParagraph("The Services shall commence on July 31, 2015, and shall continue through July 29, 2015.", "End"); + paragraph2.styleBuiltIn = "Normal"; + const paragraph3: Word.Paragraph = context.document.body.insertParagraph("Project Costs by Phase", "End"); + paragraph3.styleBuiltIn = "Heading2"; + // Note a content control with the title of "ProjectCosts" is added. Content will be replaced later. + const paragraph4: Word.Paragraph = context.document.body.insertParagraph("", "End"); + paragraph4.styleBuiltIn = "Normal"; + paragraph4.font.highlightColor = "#FFFF00"; + const contentControl: Word.ContentControl = paragraph4.insertContentControl(); + contentControl.title = "ProjectCosts"; + const paragraph5: Word.Paragraph = context.document.body.insertParagraph("Project Team", "End"); + paragraph5.styleBuiltIn = "Heading2"; + paragraph5.font.highlightColor = "#FFFFFF"; + const paragraph6: Word.Paragraph = context.document.body.insertParagraph("Terms of Work", "End"); + paragraph6.styleBuiltIn = "Heading1"; + const paragraph7: Word.Paragraph = context.document.body.insertParagraph("Contractor shall provide the Services and Deliverable(s) as follows:", "End"); + paragraph7.styleBuiltIn = "Normal"; + const paragraph8: Word.Paragraph = context.document.body.insertParagraph("Out-of-Pocket Expenses / Invoice Procedures", "End"); + paragraph8.styleBuiltIn = "Heading2"; + const paragraph9 : Word.Paragraph= context.document.body.insertParagraph("Client will be invoiced monthly for the consulting services and T&L expenses. Standard Contractor invoicing is assumed to be acceptable. Invoices are due upon receipt. client will be invoiced all costs associated with out-of-pocket expenses (including, without limitation, costs and expenses associated with meals, lodging, local transportation and any other applicable business expenses) listed on the invoice as a separate line item. Reimbursement for out-of-pocket expenses in connection with performance of this SOW, when authorized and up to the limits set forth in this SOW, shall be in accordance with Client's then-current published policies governing travel and associated business expenses, which information shall be provided by the Client Project Manager.", "End"); + paragraph9.styleBuiltIn = "Normal"; + // Insert a page break at the end of the document. + context.document.body.insertBreak("Page", "End"); - if (field.isNullObject) { - console.log("There are no fields in this document."); - } else { - console.log("Code of the field: " + field.code); - console.log("Result of the field: " + JSON.stringify(field.result)); - } + await context.sync(); }); -'Word.HeaderFooterType:enum': +Word.Paragraph#text:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-header-and-footer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml + await Word.run(async (context) => { - context.document.sections - .getFirst() - .getHeader(Word.HeaderFooterType.primary) - .insertParagraph("This is a primary header.", "End"); + // The collection of paragraphs of the current selection returns the full paragraphs contained in it. + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + paragraph.load("text"); await context.sync(); + console.log(paragraph.text); }); -'Word.ImageFormat:enum': +Word.Paragraph#uniqueLocalId:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/insert-and-get-pictures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // Gets the first image in the document. + + // Registers event handlers. await Word.run(async (context) => { - const firstPicture = context.document.body.inlinePictures.getFirst(); - firstPicture.load("width, height, imageFormat"); + eventContexts[0] = context.document.onParagraphAdded.add(paragraphChanged); + eventContexts[1] = context.document.onParagraphChanged.add(paragraphChanged); - await context.sync(); - console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`); - console.log(`Image format: ${firstPicture.imageFormat}`); - // Get the image encoded as Base64. - const base64 = firstPicture.getBase64ImageSrc(); + eventContexts[2] = context.document.onAnnotationClicked.add(onClickedHandler); + eventContexts[3] = context.document.onAnnotationHovered.add(onHoveredHandler); + eventContexts[4] = context.document.onAnnotationInserted.add(onInsertedHandler); + eventContexts[5] = context.document.onAnnotationRemoved.add(onRemovedHandler); + eventContexts[6] = context.document.onAnnotationPopupAction.add(onPopupActionHandler); await context.sync(); - console.log(base64.value); + + console.log("Event handlers registered."); }); -'Word.InlinePicture:class': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // Inserts an image anchored to the last paragraph. - await Word.run(async (context) => { - context.document.body.paragraphs - .getLast() - .insertParagraph("", "After") - .insertInlinePictureFromBase64(base64Image, "End"); + async function paragraphChanged(args: Word.ParagraphChangedEventArgs) { + await Word.run(async (context) => { + const results = []; + for (let id of args.uniqueLocalIds) { + let para = context.document.getParagraphByUniqueLocalId(id); + para.load("uniqueLocalId"); - await context.sync(); - }); -'Word.InlinePicture#getBase64ImageSrc:member(1)': + results.push({ para: para, text: para.getText() }); + } + + await context.sync(); + + for (let result of results) { + console.log(`${args.type}: ID ${result.para.uniqueLocalId}:-`, result.text.value); + } + }); + } +Word.ParagraphAddedEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onadded-event.yaml - // Gets the first image in the document. - await Word.run(async (context) => { - const firstPicture = context.document.body.inlinePictures.getFirst(); - firstPicture.load("width, height"); + // Registers the onParagraphAdded event handler on the document. + await Word.run(async (context) => { + eventContext = context.document.onParagraphAdded.add(paragraphAdded); await context.sync(); - console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`); - // Get the image encoded as Base64. - const base64 = firstPicture.getBase64ImageSrc(); - await context.sync(); - console.log(base64.value); + console.log("Added event handler for when paragraphs are added."); }); -'Word.InlinePicture#imageFormat:member': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/insert-and-get-pictures.yaml - - // Gets the first image in the document. - - await Word.run(async (context) => { - const firstPicture = context.document.body.inlinePictures.getFirst(); - firstPicture.load("width, height, imageFormat"); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onadded-event.yaml - await context.sync(); - console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`); - console.log(`Image format: ${firstPicture.imageFormat}`); - // Get the image encoded as Base64. - const base64 = firstPicture.getBase64ImageSrc(); - await context.sync(); - console.log(base64.value); - }); -'Word.InlinePictureCollection:class': + async function paragraphAdded(event: Word.ParagraphAddedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.type} event detected. IDs of paragraphs that were added:`, event.uniqueLocalIds); + }); + } +Word.ParagraphChangedEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onchanged-event.yaml - // Gets the first image in the document. - await Word.run(async (context) => { - const firstPicture = context.document.body.inlinePictures.getFirst(); - firstPicture.load("width, height"); + // Registers the onParagraphChanged event handler on the document. + await Word.run(async (context) => { + eventContext = context.document.onParagraphChanged.add(paragraphChanged); await context.sync(); - console.log(`Image dimensions: ${firstPicture.width} x ${firstPicture.height}`); - // Get the image encoded as Base64. - const base64 = firstPicture.getBase64ImageSrc(); - await context.sync(); - console.log(base64.value); + console.log("Added event handler for when content is changed in paragraphs."); }); -'Word.InsertLocation:enum': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-section-breaks.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onchanged-event.yaml - // Inserts a section without an associated page break. + + async function paragraphChanged(event: Word.ParagraphChangedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.type} event detected. IDs of paragraphs where content was changed:`, event.uniqueLocalIds); + }); + } +Word.ParagraphCollection:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml + + + // Inserts an image anchored to the last paragraph. await Word.run(async (context) => { - const body = context.document.body; - body.insertBreak(Word.BreakType.sectionContinuous, Word.InsertLocation.end); + context.document.body.paragraphs + .getLast() + .insertParagraph("", "After") + .insertInlinePictureFromBase64(base64Image, "End"); await context.sync(); - - console.log("Inserted section without an associated page break"); }); -'Word.List:class': +Word.ParagraphCollection#getFirst:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/insert-list.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml - // This example starts a new list with the second paragraph. + + // Gets annotations found in the selected paragraph. await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("$none"); + const paragraph: Word.Paragraph = context.document.getSelection().paragraphs.getFirst(); + const annotations: Word.AnnotationCollection = paragraph.getAnnotations(); + annotations.load("id,state,critiqueAnnotation"); await context.sync(); - // Start new list using the second paragraph. - const list = paragraphs.items[1].startNewList(); - list.load("$none"); + console.log("Annotations found:"); - await context.sync(); + for (let i = 0; i < annotations.items.length; i++) { + const annotation: Word.Annotation = annotations.items[i]; - // To add new items to the list, use Start or End on the insertLocation parameter. - list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + console.log(`ID ${annotation.id} - state '${annotation.state}':`, annotation.critiqueAnnotation.critique); + } + }); +Word.ParagraphCollection#getLast:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml - // Set up list level for the list item. - paragraph.listItem.level = 4; - // To add paragraphs outside the list, use Before or After. - list.insertParagraph("New paragraph goes after (not part of the list)", "After"); + // Inserts an image anchored to the last paragraph. + + await Word.run(async (context) => { + context.document.body.paragraphs + .getLast() + .insertParagraph("", "After") + .insertInlinePictureFromBase64(base64Image, "End"); await context.sync(); }); -'Word.List#insertParagraph:member(1)': +Word.ParagraphCollection#items:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/insert-list.yaml + // This example starts a new list with the second paragraph. await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; paragraphs.load("$none"); await context.sync(); // Start new list using the second paragraph. - const list = paragraphs.items[1].startNewList(); + const list: Word.List = paragraphs.items[1].startNewList(); list.load("$none"); await context.sync(); // To add new items to the list, use Start or End on the insertLocation parameter. list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + const paragraph: Word.Paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); // Set up list level for the list item. paragraph.listItem.level = 4; @@ -15826,469 +26926,564 @@ await context.sync(); }); -'Word.List#setLevelBullet:member(1)': +Word.ParagraphDeletedEventArgs:interface: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/ondeleted-event.yaml - // Inserts a list starting with the first paragraph then set numbering and - bullet types of the list items. - await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("$none"); + // Registers the onParagraphDeleted event handler on the document. + await Word.run(async (context) => { + eventContext = context.document.onParagraphDeleted.add(paragraphDeleted); await context.sync(); - // Use the first paragraph to start a new list. - const list = paragraphs.items[0].startNewList(); - list.load("$none"); - - await context.sync(); + console.log("Added event handlers for when paragraphs are deleted."); + }); + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/ondeleted-event.yaml - // To add new items to the list, use Start or End on the insertLocation parameter. - list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); - // Set numbering for list level 1. - list.setLevelNumbering(0, Word.ListNumbering.arabic); + async function paragraphDeleted(event: Word.ParagraphDeletedEventArgs) { + await Word.run(async (context) => { + console.log(`${event.type} event detected. IDs of paragraphs that were deleted:`, event.uniqueLocalIds); + }); + } +Word.ParagraphFormat:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Set bullet type for list level 5. - list.setLevelBullet(4, Word.ListBullet.arrow); - // Set list level for the last item in this list. - paragraph.listItem.level = 4; + // Sets certain aspects of the specified style's paragraph format e.g., the + left indent size and the alignment. - list.load("levelTypes"); + await Word.run(async (context) => { + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update its paragraph format."); + return; + } + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); await context.sync(); - const levelTypes = list.levelTypes; - console.log("Level types of this list:"); - for (let i = 0; i < levelTypes.length; i++) { - console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + style.paragraphFormat.leftIndent = 30; + style.paragraphFormat.alignment = Word.Alignment.centered; + console.log(`Successfully the paragraph format of the '${styleName}' style.`); } }); -'Word.List#setLevelNumbering:member(1)': +Word.ParagraphFormat#alignment:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml - - // Inserts a list starting with the first paragraph then set numbering and - bullet types of the list items. + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("$none"); - await context.sync(); + // Sets certain aspects of the specified style's paragraph format e.g., the + left indent size and the alignment. - // Use the first paragraph to start a new list. - const list = paragraphs.items[0].startNewList(); - list.load("$none"); + await Word.run(async (context) => { + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update its paragraph format."); + return; + } + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); await context.sync(); - // To add new items to the list, use Start or End on the insertLocation parameter. - list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); - - // Set numbering for list level 1. - list.setLevelNumbering(0, Word.ListNumbering.arabic); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + style.paragraphFormat.leftIndent = 30; + style.paragraphFormat.alignment = Word.Alignment.centered; + console.log(`Successfully the paragraph format of the '${styleName}' style.`); + } + }); +Word.ParagraphFormat#leftIndent:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Set bullet type for list level 5. - list.setLevelBullet(4, Word.ListBullet.arrow); - // Set list level for the last item in this list. - paragraph.listItem.level = 4; + // Sets certain aspects of the specified style's paragraph format e.g., the + left indent size and the alignment. - list.load("levelTypes"); + await Word.run(async (context) => { + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update its paragraph format."); + return; + } + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); await context.sync(); - const levelTypes = list.levelTypes; - console.log("Level types of this list:"); - for (let i = 0; i < levelTypes.length; i++) { - console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + style.paragraphFormat.leftIndent = 30; + style.paragraphFormat.alignment = Word.Alignment.centered; + console.log(`Successfully the paragraph format of the '${styleName}' style.`); } }); -'Word.List#levelTypes:member': +Word.Range:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - // Inserts a list starting with the first paragraph then set numbering and - bullet types of the list items. - await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("$none"); + // Gets the range of the first comment in the selected content. + await Word.run(async (context) => { + const comment: Word.Comment = context.document.getSelection().getComments().getFirstOrNullObject(); + comment.load("contentRange"); + const range: Word.Range = comment.getRange(); + range.load("text"); await context.sync(); - // Use the first paragraph to start a new list. - const list = paragraphs.items[0].startNewList(); - list.load("$none"); + if (comment.isNullObject) { + console.warn("No comments in the selection, so no range to get."); + return; + } - await context.sync(); + console.log(`Comment location: ${range.text}`); + const contentRange: Word.CommentContentRange = comment.contentRange; + console.log("Comment content range:", contentRange); + }); +Word.Range#compareLocationWith:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/compare-location.yaml - // To add new items to the list, use Start or End on the insertLocation parameter. - list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); - // Set numbering for list level 1. - list.setLevelNumbering(0, Word.ListNumbering.arabic); + // Compares the location of one paragraph in relation to another paragraph. - // Set bullet type for list level 5. - list.setLevelBullet(4, Word.ListBullet.arrow); + await Word.run(async (context) => { + const paragraphs: Word.ParagraphCollection = context.document.body.paragraphs; + paragraphs.load("items"); - // Set list level for the last item in this list. - paragraph.listItem.level = 4; + await context.sync(); - list.load("levelTypes"); + const firstParagraphAsRange: Word.Range = paragraphs.items[0].getRange(); + const secondParagraphAsRange: Word.Range = paragraphs.items[1].getRange(); + + const comparedLocation = firstParagraphAsRange.compareLocationWith(secondParagraphAsRange); await context.sync(); - const levelTypes = list.levelTypes; - console.log("Level types of this list:"); - for (let i = 0; i < levelTypes.length; i++) { - console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); - } + const locationValue: Word.LocationRelation = comparedLocation.value; + console.log(`Location of the first paragraph in relation to the second paragraph: ${locationValue}`); }); -'Word.ListItem#level:member': +Word.Range#expandTo:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/insert-list.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml - // This example starts a new list with the second paragraph. await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("$none"); - + // Get the complete sentence (as range) associated with the insertion point. + const sentences: Word.RangeCollection = context.document + .getSelection() + .getTextRanges(["."] /* Using the "." as delimiter */, false /*means without trimming spaces*/); + sentences.load("$none"); await context.sync(); - // Start new list using the second paragraph. - const list = paragraphs.items[1].startNewList(); - list.load("$none"); - + // Expand the range to the end of the paragraph to get all the complete sentences. + const sentencesToTheEndOfParagraph: Word.RangeCollection = sentences.items[0] + .getRange() + .expandTo( + context.document + .getSelection() + .paragraphs.getFirst() + .getRange(Word.RangeLocation.end) + ) + .getTextRanges(["."], false /* Don't trim spaces*/); + sentencesToTheEndOfParagraph.load("text"); await context.sync(); - // To add new items to the list, use Start or End on the insertLocation parameter. - list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); - - // Set up list level for the list item. - paragraph.listItem.level = 4; - - // To add paragraphs outside the list, use Before or After. - list.insertParagraph("New paragraph goes after (not part of the list)", "After"); - - await context.sync(); + for (let i = 0; i < sentencesToTheEndOfParagraph.items.length; i++) { + console.log(sentencesToTheEndOfParagraph.items[i].text); + } }); -'Word.ListBullet:enum': +Word.Range#getComments:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - // Inserts a list starting with the first paragraph then set numbering and - bullet types of the list items. + + // Gets the comments in the selected content. await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("$none"); + const comments: Word.CommentCollection = context.document.getSelection().getComments(); + // Load objects to log in the console. + comments.load(); await context.sync(); - // Use the first paragraph to start a new list. - const list = paragraphs.items[0].startNewList(); - list.load("$none"); + console.log("Comments:", comments); + }); +Word.Range#getContentControls:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml - await context.sync(); - // To add new items to the list, use Start or End on the insertLocation parameter. - list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + // Deletes the first checkbox content control found in the selection. - // Set numbering for list level 1. - list.setLevelNumbering(0, Word.ListNumbering.arabic); + await Word.run(async (context) => { + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.checkBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id"); - // Set bullet type for list level 5. - list.setLevelBullet(4, Word.ListBullet.arrow); + await context.sync(); - // Set list level for the last item in this list. - paragraph.listItem.level = 4; + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type"); + await context.sync(); - list.load("levelTypes"); + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.checkBox) { + console.warn("No checkbox content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + console.log(`About to delete checkbox content control with id: ${selectedContentControl.id}`); + selectedContentControl.delete(false); await context.sync(); - const levelTypes = list.levelTypes; - console.log("Level types of this list:"); - for (let i = 0; i < levelTypes.length; i++) { - console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); - } + console.log("Deleted checkbox content control."); }); -'Word.ListLevelType:enum': +Word.Range#getRange:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml - // Inserts a list starting with the first paragraph then set numbering and - bullet types of the list items. - await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("$none"); + // Places a dropdown list content control at the end of the selection. + await Word.run(async (context) => { + let selection = context.document.getSelection(); + selection.getRange(Word.RangeLocation.end).insertContentControl(Word.ContentControlType.dropDownList); await context.sync(); - // Use the first paragraph to start a new list. - const list = paragraphs.items[0].startNewList(); - list.load("$none"); + console.log("Dropdown list content control inserted at the end of the selection."); + }); +Word.Range#getReviewedText:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-change-tracking.yaml - await context.sync(); - // To add new items to the list, use Start or End on the insertLocation parameter. - list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + // Gets the reviewed text. - // Set numbering for list level 1. - list.setLevelNumbering(0, Word.ListNumbering.arabic); + await Word.run(async (context) => { + const range: Word.Range = context.document.getSelection(); + const before = range.getReviewedText(Word.ChangeTrackingVersion.original); + const after = range.getReviewedText(Word.ChangeTrackingVersion.current); - // Set bullet type for list level 5. - list.setLevelBullet(4, Word.ListBullet.arrow); + await context.sync(); - // Set list level for the last item in this list. - paragraph.listItem.level = 4; + console.log("Reviewed text (before):", before.value, "Reviewed text (after):", after.value); + }); +Word.Range#getTextRanges:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml - list.load("levelTypes"); + await Word.run(async (context) => { + // Get the complete sentence (as range) associated with the insertion point. + const sentences: Word.RangeCollection = context.document + .getSelection() + .getTextRanges(["."] /* Using the "." as delimiter */, false /*means without trimming spaces*/); + sentences.load("$none"); await context.sync(); - const levelTypes = list.levelTypes; - console.log("Level types of this list:"); - for (let i = 0; i < levelTypes.length; i++) { - console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); + // Expand the range to the end of the paragraph to get all the complete sentences. + const sentencesToTheEndOfParagraph: Word.RangeCollection = sentences.items[0] + .getRange() + .expandTo( + context.document + .getSelection() + .paragraphs.getFirst() + .getRange(Word.RangeLocation.end) + ) + .getTextRanges(["."], false /* Don't trim spaces*/); + sentencesToTheEndOfParagraph.load("text"); + await context.sync(); + + for (let i = 0; i < sentencesToTheEndOfParagraph.items.length; i++) { + console.log(sentencesToTheEndOfParagraph.items[i].text); } }); -'Word.ListNumbering:enum': +Word.Range#insertComment:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml - // Inserts a list starting with the first paragraph then set numbering and - bullet types of the list items. + + // Sets a comment on the selected content. await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("$none"); + const text = (document.getElementById("comment-text") as HTMLInputElement).value; + const comment: Word.Comment = context.document.getSelection().insertComment(text); + // Load object to log in the console. + comment.load(); await context.sync(); - // Use the first paragraph to start a new list. - const list = paragraphs.items[0].startNewList(); - list.load("$none"); + console.log("Comment inserted:", comment); + }); +Word.Range#insertContentControl:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/doc-assembly.yaml - await context.sync(); - // To add new items to the list, use Start or End on the insertLocation parameter. - list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + // Simulates creation of a template. First searches the document for + instances of the string "Contractor", - // Set numbering for list level 1. - list.setLevelNumbering(0, Word.ListNumbering.arabic); + // then changes the format of each search result, - // Set bullet type for list level 5. - list.setLevelBullet(4, Word.ListBullet.arrow); + // then wraps each search result within a content control, - // Set list level for the last item in this list. - paragraph.listItem.level = 4; + // finally sets a tag and title property on each content control. - list.load("levelTypes"); + await Word.run(async (context) => { + const results: Word.RangeCollection = context.document.body.search("Contractor"); + results.load("font/bold"); - await context.sync(); + // Check to make sure these content controls haven't been added yet. + const customerContentControls: Word.ContentControlCollection = context.document.contentControls.getByTag("customer"); + customerContentControls.load("text"); + await context.sync(); - const levelTypes = list.levelTypes; - console.log("Level types of this list:"); - for (let i = 0; i < levelTypes.length; i++) { - console.log(`- Level ${i + 1} (index ${i}): ${levelTypes[i]}`); + if (customerContentControls.items.length === 0) { + for (let i = 0; i < results.items.length; i++) { + results.items[i].font.bold = true; + let cc: Word.ContentControl = results.items[i].insertContentControl(); + cc.tag = "customer"; // This value is used in the next step of this sample. + cc.title = "Customer Name " + i; + } } + await context.sync(); }); -'Word.LocationRelation:enum': +Word.Range#insertField:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/compare-location.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml - // Compares the location of one paragraph in relation to another paragraph. + + // Inserts a Date field before selection. await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("items"); + const range: Word.Range = context.document.getSelection().getRange(); + + const field: Word.Field = range.insertField(Word.InsertLocation.before, Word.FieldType.date, '\\@ "M/d/yyyy h:mm am/pm"', true); + field.load("result,code"); await context.sync(); - const firstParagraphAsRange = paragraphs.items[0].getRange(); - const secondParagraphAsRange = paragraphs.items[1].getRange(); + if (field.isNullObject) { + console.log("There are no fields in this document."); + } else { + console.log("Code of the field: " + field.code, "Result of the field: " + JSON.stringify(field.result)); + } + }); +Word.Range#insertFootnote:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + - const comparedLocation = firstParagraphAsRange.compareLocationWith(secondParagraphAsRange); + // Sets a footnote on the selected content. + await Word.run(async (context) => { + const text = (document.getElementById("input-footnote") as HTMLInputElement).value; + const footnote: Word.NoteItem = context.document.getSelection().insertFootnote(text); await context.sync(); - console.log(`Location of the first paragraph in relation to the second paragraph: ${comparedLocation.value}`); + console.log("Inserted footnote."); }); -'Word.NoteItem#delete:member(1)': +Word.Range#insertInlinePictureFromBase64:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml - // Deletes this referenced footnote. await Word.run(async (context) => { - const footnotes = context.document.body.footnotes; - footnotes.load("items"); + // Inserts a picture at the start of the first text box. + const firstShapeWithTextBox: Word.Shape = context.document.body.shapes + .getByTypes([Word.ShapeType.textBox]) + .getFirst(); + firstShapeWithTextBox.load("type/body"); await context.sync(); - const referenceNumber = $("#input-reference").val(); - const mark = (referenceNumber as number) - 1; - footnotes.items[mark].delete(); + const startRange: Word.Range = firstShapeWithTextBox.body.getRange(Word.RangeLocation.start); + const newPic: Word.InlinePicture = startRange.insertInlinePictureFromBase64( + getPictureBase64(), + Word.InsertLocation.start + ); + newPic.load(); await context.sync(); - console.log("Footnote deleted."); + console.log("New inline picture properties:", newPic); }); -'Word.NoteItem#getNext:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml - // Selects the next footnote in the document body. - await Word.run(async (context) => { - const footnotes = context.document.body.footnotes; - footnotes.load("items/reference"); - await context.sync(); + // Returns Base64-encoded image data for a sample picture. - const referenceNumber = $("#input-reference").val(); - const mark = (referenceNumber as number) - 1; - const reference = footnotes.items[mark].getNext().reference; - reference.select(); - console.log("Selected is the next footnote: " + (mark + 2)); - }); -'Word.NoteItem#body:member': + const pictureBase64 = + "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"; + return pictureBase64; +Word.Range#insertTextBox:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml - // Gets the text of the referenced footnote. await Word.run(async (context) => { - const footnotes = context.document.body.footnotes; - footnotes.load("items/body"); - await context.sync(); + // Inserts a text box at the beginning of the selection. + const range: Word.Range = context.document.getSelection(); + const insertShapeOptions: Word.InsertShapeOptions = { + top: 0, + left: 0, + height: 100, + width: 100 + }; - const referenceNumber = $("#input-reference").val(); - const mark = (referenceNumber as number) - 1; - const footnoteBody = footnotes.items[mark].body.getRange(); - footnoteBody.load("text"); + const newTextBox: Word.Shape = range.insertTextBox("placeholder text", insertShapeOptions); await context.sync(); - console.log(`Text of footnote ${referenceNumber}: ${footnoteBody.text}`); + console.log("Inserted a text box at the beginning of the current selection."); }); -'Word.NoteItem#reference:member': +Word.Range#footnotes:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml - // Selects the footnote's reference mark in the document body. - await Word.run(async (context) => { - const footnotes = context.document.body.footnotes; - footnotes.load("items/reference"); - await context.sync(); + // Gets the footnotes in the selected document range. - const referenceNumber = $("#input-reference").val(); - const mark = (referenceNumber as number) - 1; - const item = footnotes.items[mark]; - const reference = item.reference; - reference.select(); + await Word.run(async (context) => { + const footnotes: Word.NoteItemCollection = context.document.getSelection().footnotes; + footnotes.load("length"); await context.sync(); - console.log(`Reference ${referenceNumber} is selected.`); + console.log("Number of footnotes in the selected range: " + footnotes.items.length); }); -'Word.NoteItem#type:member': +Word.Range#parentContentControl:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml - // Gets the referenced note's item type and body type, which are both - "Footnote". + + // Toggles the isChecked property of the first checkbox content control + found in the selection. await Word.run(async (context) => { - const footnotes = context.document.body.footnotes; - footnotes.load("items"); + const selectedRange: Word.Range = context.document.getSelection(); + let selectedContentControl = selectedRange + .getContentControls({ + types: [Word.ContentControlType.checkBox] + }) + .getFirstOrNullObject(); + selectedContentControl.load("id,checkboxContentControl/isChecked"); + await context.sync(); - const referenceNumber = $("#input-reference").val(); - const mark = (referenceNumber as number) - 1; - const item = footnotes.items[mark]; - console.log(`Note type of footnote ${referenceNumber}: ${item.type}`); + if (selectedContentControl.isNullObject) { + const parentContentControl: Word.ContentControl = selectedRange.parentContentControl; + parentContentControl.load("id,type,checkboxContentControl/isChecked"); + await context.sync(); - item.body.load("type"); + if (parentContentControl.isNullObject || parentContentControl.type !== Word.ContentControlType.checkBox) { + console.warn("No checkbox content control is currently selected."); + return; + } else { + selectedContentControl = parentContentControl; + } + } + + const isCheckedBefore = selectedContentControl.checkboxContentControl.isChecked; + console.log("isChecked state before:", `id: ${selectedContentControl.id} ... isChecked: ${isCheckedBefore}`); + selectedContentControl.checkboxContentControl.isChecked = !isCheckedBefore; + selectedContentControl.load("id,checkboxContentControl/isChecked"); await context.sync(); - console.log(`Body type of note: ${item.body.type}`); + console.log( + "isChecked state after:", + `id: ${selectedContentControl.id} ... isChecked: ${selectedContentControl.checkboxContentControl.isChecked}` + ); }); -'Word.NoteItemCollection#getFirst:member(1)': +Word.Range#styleBuiltIn:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/doc-assembly.yaml - // Gets the first footnote in the document body and select its reference - mark. await Word.run(async (context) => { - const reference = context.document.body.footnotes.getFirst().reference; - reference.select(); - console.log("The first footnote is selected."); + const header: Word.Range = context.document.body.insertText("This is a sample Heading 1 Title!!\n", + "Start" /*this means at the beginning of the body */); + header.styleBuiltIn = Word.BuiltInStyleName.heading1; + + await context.sync(); }); -'Word.NoteItemType:enum': +Word.RangeCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/search.yaml - // Gets the referenced note's item type and body type, which are both - "Footnote". + + // Does a basic text search and highlights matches in the document. await Word.run(async (context) => { - const footnotes = context.document.body.footnotes; - footnotes.load("items"); + const results : Word.RangeCollection = context.document.body.search("extend"); + results.load("length"); + await context.sync(); - const referenceNumber = $("#input-reference").val(); - const mark = (referenceNumber as number) - 1; - const item = footnotes.items[mark]; - console.log(`Note type of footnote ${referenceNumber}: ${item.type}`); + // Let's traverse the search results and highlight matches. + for (let i = 0; i < results.items.length; i++) { + results.items[i].font.highlightColor = "yellow"; + } - item.body.load("type"); await context.sync(); - - console.log(`Body type of note: ${item.body.type}`); }); -'Word.Paragraph#getRange:member(1)': +Word.RangeLocation:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml + await Word.run(async (context) => { // Get the complete sentence (as range) associated with the insertion point. - const sentences = context.document + const sentences: Word.RangeCollection = context.document .getSelection() .getTextRanges(["."] /* Using the "." as delimiter */, false /*means without trimming spaces*/); sentences.load("$none"); await context.sync(); // Expand the range to the end of the paragraph to get all the complete sentences. - const sentencesToTheEndOfParagraph = sentences.items[0] + const sentencesToTheEndOfParagraph: Word.RangeCollection = sentences.items[0] .getRange() .expandTo( context.document @@ -16304,1325 +27499,1721 @@ console.log(sentencesToTheEndOfParagraph.items[i].text); } }); -'Word.Paragraph#insertBreak:member(1)': +Word.SaveBehavior:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-line-and-page-breaks.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/save-close.yaml - Word.run(async (context) => { - context.document.body.paragraphs.getFirst().insertBreak(Word.BreakType.line, "After"); + + // If the document hasn't been saved before, prompts + + // user with options for if or how they want to save. + + await Word.run(async (context) => { + context.document.save(Word.SaveBehavior.prompt); + await context.sync(); + }); +Word.SaveConfiguration:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/close-document-window.yaml + + + await Word.run(async (context) => { + // Closes the document window, prompting to save if this is a new document. + const window: Word.Window = context.document.activeWindow; + const closeOptions: Word.WindowCloseOptions = { saveChanges: Word.SaveConfiguration.promptToSaveChanges }; + console.log("About to close the document window..."); + window.close(closeOptions); + }); +Word.Section#getFooter:member(2): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-header-and-footer.yaml + + + await Word.run(async (context) => { + context.document.sections + .getFirst() + .getFooter("Primary") + .insertParagraph("This is a primary footer.", "End"); + + await context.sync(); + }); +Word.Section#getHeader:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-header-and-footer.yaml + + + await Word.run(async (context) => { + context.document.sections + .getFirst() + .getHeader(Word.HeaderFooterType.primary) + .insertParagraph("This is a primary header.", "End"); await context.sync(); - console.log("success"); }); -'Word.Paragraph#insertText:member(1)': +Word.Section:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-in-different-locations.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-section-breaks.yaml + + + // Inserts a section break on the next page. await Word.run(async (context) => { - // Replace the last paragraph. - const range = context.document.body.paragraphs.getLast().insertText("Just replaced the last paragraph!", "Replace"); - range.font.highlightColor = "black"; - range.font.color = "white"; + const body: Word.Body = context.document.body; + body.insertBreak(Word.BreakType.sectionNext, Word.InsertLocation.end); await context.sync(); + + console.log("Inserted section break on next page."); }); -'Word.Paragraph#select:member(1)': +Word.SectionCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/scroll-to-range.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-section-breaks.yaml + + + // Inserts a section break on the next even page. await Word.run(async (context) => { - // If select is called with no parameters, it selects the object. - context.document.body.paragraphs.getLast().select(); + const body: Word.Body = context.document.body; + body.insertBreak(Word.BreakType.sectionEven, Word.InsertLocation.end); await context.sync(); + + console.log("Inserted section break on next even page."); }); +Word.SelectionMode:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/scroll-to-range.yaml + await Word.run(async (context) => { // Select can be at the start or end of a range; this by definition moves the insertion point without selecting the range. context.document.body.paragraphs.getLast().select(Word.SelectionMode.end); await context.sync(); }); -'Word.Paragraph#split:member(1)': +Word.Setting:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/split-words-of-first-paragraph.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-settings.yaml - await Word.run(async (context) => { - const paragraph = context.document.body.paragraphs.getFirst(); - const words = paragraph.split([" "], true /* trimDelimiters*/, true /* trimSpaces */); - words.load("text"); - await context.sync(); + // Adds a new custom setting or - for (let i = 0; i < words.items.length; i++) { - if (i >= 1) { - words.items[i - 1].font.highlightColor = "#FFFFFF"; - } - words.items[i].font.highlightColor = "#FFFF00"; + // edits the value of an existing one. - await context.sync(); - await pause(200); + await Word.run(async (context) => { + const key = (document.getElementById("key") as HTMLInputElement).value; + if (key == "") { + console.error("Key shouldn't be empty."); + return; } + + const value = (document.getElementById("value") as HTMLInputElement).value; + const settings: Word.SettingCollection = context.document.settings; + const setting: Word.Setting = settings.add(key, value); + setting.load(); + await context.sync(); + + console.log("Setting added or edited:", setting); }); -'Word.Paragraph#startNewList:member(1)': +Word.Setting#key:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/insert-list.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-settings.yaml - // This example starts a new list with the second paragraph. - await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("$none"); + // Adds a new custom setting or - await context.sync(); + // edits the value of an existing one. - // Start new list using the second paragraph. - const list = paragraphs.items[1].startNewList(); - list.load("$none"); + await Word.run(async (context) => { + const key = (document.getElementById("key") as HTMLInputElement).value; + if (key == "") { + console.error("Key shouldn't be empty."); + return; + } + const value = (document.getElementById("value") as HTMLInputElement).value; + const settings: Word.SettingCollection = context.document.settings; + const setting: Word.Setting = settings.add(key, value); + setting.load(); await context.sync(); - // To add new items to the list, use Start or End on the insertLocation parameter. - list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); - - // Set up list level for the list item. - paragraph.listItem.level = 4; - - // To add paragraphs outside the list, use Before or After. - list.insertParagraph("New paragraph goes after (not part of the list)", "After"); - - await context.sync(); + console.log("Setting added or edited:", setting); }); -'Word.Paragraph#set:member(1)': +Word.Setting#value:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/multiple-property-set.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-settings.yaml + + + // Adds a new custom setting or + + // edits the value of an existing one. await Word.run(async (context) => { - const paragraph = context.document.body.paragraphs.getFirst(); - paragraph.set({ - leftIndent: 30, - font: { - bold: true, - color: "red" - } - }); + const key = (document.getElementById("key") as HTMLInputElement).value; + if (key == "") { + console.error("Key shouldn't be empty."); + return; + } + const value = (document.getElementById("value") as HTMLInputElement).value; + const settings: Word.SettingCollection = context.document.settings; + const setting: Word.Setting = settings.add(key, value); + setting.load(); await context.sync(); + + console.log("Setting added or edited:", setting); }); +Word.SettingCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/multiple-property-set.yaml - - await Word.run(async (context) => { - const firstParagraph = context.document.body.paragraphs.getFirst(); - const secondParagraph = firstParagraph.getNext(); - firstParagraph.load("text, font/color, font/bold, leftIndent"); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-settings.yaml - await context.sync(); - secondParagraph.set(firstParagraph); + // Deletes all custom settings this add-in had set on this document. + await Word.run(async (context) => { + const settings: Word.SettingCollection = context.document.settings; + settings.deleteAll(); await context.sync(); + console.log("All settings deleted."); }); -'Word.Paragraph#alignment:member': +Word.SettingCollection#add:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-settings.yaml + + + // Adds a new custom setting or + + // edits the value of an existing one. await Word.run(async (context) => { - // Center last paragraph alignment. - context.document.body.paragraphs.getLast().alignment = "Centered"; + const key = (document.getElementById("key") as HTMLInputElement).value; + if (key == "") { + console.error("Key shouldn't be empty."); + return; + } + const value = (document.getElementById("value") as HTMLInputElement).value; + const settings: Word.SettingCollection = context.document.settings; + const setting: Word.Setting = settings.add(key, value); + setting.load(); await context.sync(); + + console.log("Setting added or edited:", setting); }); -'Word.Paragraph#leftIndent:member': +Word.SettingCollection#items:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-settings.yaml - await Word.run(async (context) => { - // Indent the first paragraph. - context.document.body.paragraphs.getFirst().leftIndent = 75; //units = points - return context.sync(); - }); -'Word.Paragraph#lineSpacing:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml + // Gets all custom settings this add-in set on this document. await Word.run(async (context) => { - // Adjust line spacing. - context.document.body.paragraphs.getFirst().lineSpacing = 20; - + const settings: Word.SettingCollection = context.document.settings; + settings.load("items"); await context.sync(); + + if (settings.items.length == 0) { + console.log("There are no settings."); + } else { + console.log("All settings:"); + for (let i = 0; i < settings.items.length; i++) { + console.log(settings.items[i]); + } + } }); -'Word.Paragraph#spaceAfter:member': +Word.Shading:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + + + // Updates shading properties (e.g., texture, pattern colors) of the + specified style. await Word.run(async (context) => { - // Adjust space between paragraphs. - context.document.body.paragraphs.getFirst().spaceAfter = 20; + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update shading properties."); + return; + } + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); await context.sync(); + + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + const shading: Word.Shading = style.shading; + shading.load(); + await context.sync(); + + shading.backgroundPatternColor = "blue"; + shading.foregroundPatternColor = "yellow"; + shading.texture = Word.ShadingTextureType.darkTrellis; + + console.log("Updated shading."); + } }); -'Word.Paragraph#style:member': +Word.ShadingTextureType:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Applies the specified style to a paragraph. + + // Updates shading properties (e.g., texture, pattern colors) of the + specified style. await Word.run(async (context) => { - const styleName = $("#style-name-to-use").val() as string; + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; if (styleName == "") { - console.warn("Enter a style name to apply."); + console.warn("Enter a style name to update shading properties."); return; } - const style = context.document.getStyles().getByNameOrNullObject(styleName); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); style.load(); await context.sync(); if (style.isNullObject) { console.warn(`There's no existing style with the name '${styleName}'.`); - } else if (style.type != Word.StyleType.paragraph) { - console.log(`The '${styleName}' style isn't a paragraph style.`); } else { - const body = context.document.body; - body.clear(); - body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", - "Start" - ); - const paragraph = body.paragraphs.getFirst(); - paragraph.style = style.nameLocal; - console.log(`'${styleName}' style applied to first paragraph.`); + const shading: Word.Shading = style.shading; + shading.load(); + await context.sync(); + + shading.backgroundPatternColor = "blue"; + shading.foregroundPatternColor = "yellow"; + shading.texture = Word.ShadingTextureType.darkTrellis; + + console.log("Updated shading."); } }); -'Word.Paragraph#styleBuiltIn:member': +Word.Shape:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/doc-assembly.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml + await Word.run(async (context) => { - const paragraph = context.document.body.insertParagraph("Timeline", "End"); - paragraph.styleBuiltIn = "Heading2"; - const paragraph2 = context.document.body.insertParagraph("The Services shall commence on July 31, 2015, and shall continue through July 29, 2015.", "End"); - paragraph2.styleBuiltIn = "Normal"; - const paragraph3 = context.document.body.insertParagraph("Project Costs by Phase", "End"); - paragraph3.styleBuiltIn = "Heading2"; - // Note a content control with the title of "ProjectCosts" is added. Content will be replaced later. - const paragraph4 = context.document.body.insertParagraph("", "End"); - paragraph4.styleBuiltIn = "Normal"; - paragraph4.font.highlightColor = "#FFFF00"; - const contentControl = paragraph4.insertContentControl(); - contentControl.title = "ProjectCosts"; - const paragraph5 = context.document.body.insertParagraph("Project Team", "End"); - paragraph5.styleBuiltIn = "Heading2"; - paragraph5.font.highlightColor = "#FFFFFF"; - const paragraph6 = context.document.body.insertParagraph("Terms of Work", "End"); - paragraph6.styleBuiltIn = "Heading1"; - const paragraph7 = context.document.body.insertParagraph("Contractor shall provide the Services and Deliverable(s) as follows:", "End"); - paragraph7.styleBuiltIn = "Normal"; - const paragraph8 = context.document.body.insertParagraph("Out-of-Pocket Expenses / Invoice Procedures", "End"); - paragraph8.styleBuiltIn = "Heading2"; - const paragraph9 = context.document.body.insertParagraph("Client will be invoiced monthly for the consulting services and T&L expenses. Standard Contractor invoicing is assumed to be acceptable. Invoices are due upon receipt. client will be invoiced all costs associated with out-of-pocket expenses (including, without limitation, costs and expenses associated with meals, lodging, local transportation and any other applicable business expenses) listed on the invoice as a separate line item. Reimbursement for out-of-pocket expenses in connection with performance of this SOW, when authorized and up to the limits set forth in this SOW, shall be in accordance with Client's then-current published policies governing travel and associated business expenses, which information shall be provided by the Client Project Manager.", "End"); - paragraph9.styleBuiltIn = "Normal"; - // Insert a page break at the end of the document. - context.document.body.insertBreak("Page", "End"); + // Sets the properties of the first text box. + const firstShapeWithTextBox: Word.Shape = context.document.body.shapes + .getByTypes([Word.ShapeType.textBox]) + .getFirst(); + firstShapeWithTextBox.top = 115; + firstShapeWithTextBox.left = 0; + firstShapeWithTextBox.width = 50; + firstShapeWithTextBox.height = 50; + await context.sync(); - await context.sync(); + console.log("The first text box's properties were updated:", firstShapeWithTextBox); }); -'Word.Paragraph#text:member': +Word.Shape#delete:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml - await Word.run(async (context) => { - // The collection of paragraphs of the current selection returns the full paragraphs contained in it. - const paragraph = context.document.getSelection().paragraphs.getFirst(); - paragraph.load("text"); + await Word.run(async (context) => { + // Deletes the first text box. + context.document.body.shapes.getByTypes([Word.ShapeType.textBox]).getFirst().delete(); await context.sync(); - console.log(paragraph.text); + + console.log("The first text box in document was deleted."); }); -'Word.ParagraphCollection#getLast:member(1)': +Word.Shape#body:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml - // Inserts an image anchored to the last paragraph. await Word.run(async (context) => { - context.document.body.paragraphs - .getLast() - .insertParagraph("", "After") - .insertInlinePictureFromBase64(base64Image, "End"); + // Inserts a content control into the first paragraph in the first text box. + const firstShapeWithTextBox: Word.Shape = context.document.body.shapes + .getByTypes([Word.ShapeType.textBox]) + .getFirst(); + firstShapeWithTextBox.load("type/body"); + await context.sync(); + const firstParagraphInTextBox: Word.Paragraph = firstShapeWithTextBox.body.paragraphs.getFirst(); + const newControl: Word.ContentControl = firstParagraphInTextBox.insertContentControl(); + newControl.load(); await context.sync(); + + console.log("New content control properties:", newControl); }); -'Word.ParagraphCollection#items:member': +Word.Shape#type:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/insert-list.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml - // This example starts a new list with the second paragraph. await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("$none"); + // Gets text boxes in main document. + const shapes: Word.ShapeCollection = context.document.body.shapes; + shapes.load(); + await context.sync(); + if (shapes.items.length > 0) { + shapes.items.forEach(function (shape, index) { + if (shape.type === Word.ShapeType.textBox) { + console.log(`Shape ${index} in the main document has a text box. Properties:`, shape); + } + }); + } else { + console.log("No shapes found in main document."); + } + }); +Word.ShapeCollection:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml + + + await Word.run(async (context) => { + // Gets text boxes in main document. + const shapes: Word.ShapeCollection = context.document.body.shapes; + shapes.load(); await context.sync(); - // Start new list using the second paragraph. - const list = paragraphs.items[1].startNewList(); - list.load("$none"); + if (shapes.items.length > 0) { + shapes.items.forEach(function (shape, index) { + if (shape.type === Word.ShapeType.textBox) { + console.log(`Shape ${index} in the main document has a text box. Properties:`, shape); + } + }); + } else { + console.log("No shapes found in main document."); + } + }); +Word.ShapeCollection#getByTypes:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml + + await Word.run(async (context) => { + // Sets the properties of the first text box. + const firstShapeWithTextBox: Word.Shape = context.document.body.shapes + .getByTypes([Word.ShapeType.textBox]) + .getFirst(); + firstShapeWithTextBox.top = 115; + firstShapeWithTextBox.left = 0; + firstShapeWithTextBox.width = 50; + firstShapeWithTextBox.height = 50; await context.sync(); - // To add new items to the list, use Start or End on the insertLocation parameter. - list.insertParagraph("New list item at the start of the list", "Start"); - const paragraph = list.insertParagraph("New list item at the end of the list (set to list level 5)", "End"); + console.log("The first text box's properties were updated:", firstShapeWithTextBox); + }); +Word.ShapeCollection#getFirst:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml - // Set up list level for the list item. - paragraph.listItem.level = 4; - // To add paragraphs outside the list, use Before or After. - list.insertParagraph("New paragraph goes after (not part of the list)", "After"); + await Word.run(async (context) => { + // Inserts a content control into the first paragraph in the first text box. + const firstShapeWithTextBox: Word.Shape = context.document.body.shapes + .getByTypes([Word.ShapeType.textBox]) + .getFirst(); + firstShapeWithTextBox.load("type/body"); + await context.sync(); + + const firstParagraphInTextBox: Word.Paragraph = firstShapeWithTextBox.body.paragraphs.getFirst(); + const newControl: Word.ContentControl = firstParagraphInTextBox.insertContentControl(); + newControl.load(); + await context.sync(); + + console.log("New content control properties:", newControl); + }); +Word.ShapeCollection#getFirstOrNullObject:member(1): + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml + + + await Word.run(async (context) => { + // Gets text from first text box in main document. + const shape: Word.Shape = context.document.body.shapes.getByTypes([Word.ShapeType.textBox]).getFirstOrNullObject(); + shape.load("body/text"); + await context.sync(); + + console.log( + shape.isNullObject + ? "No shapes with text boxes found in main document." + : `Text in first text box: ${shape.body.text}`, + ); + }); +Word.ShapeType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml + + await Word.run(async (context) => { + // Gets text boxes in main document. + const shapes: Word.ShapeCollection = context.document.body.shapes; + shapes.load(); await context.sync(); + + if (shapes.items.length > 0) { + shapes.items.forEach(function (shape, index) { + if (shape.type === Word.ShapeType.textBox) { + console.log(`Shape ${index} in the main document has a text box. Properties:`, shape); + } + }); + } else { + console.log("No shapes found in main document."); + } }); -'Word.ParagraphFormat#alignment:member': +Word.Style:class: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Sets certain aspects of the specified style's paragraph format e.g., the - left indent size and the alignment. + + // Applies the specified style to a paragraph. await Word.run(async (context) => { - const styleName = $("#style-name").val() as string; + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; if (styleName == "") { - console.warn("Enter a style name to update its paragraph format."); + console.warn("Enter a style name to apply."); return; } - const style = context.document.getStyles().getByNameOrNullObject(styleName); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); style.load(); await context.sync(); if (style.isNullObject) { console.warn(`There's no existing style with the name '${styleName}'.`); + } else if (style.type != Word.StyleType.paragraph) { + console.log(`The '${styleName}' style isn't a paragraph style.`); } else { - style.paragraphFormat.leftIndent = 30; - style.paragraphFormat.alignment = Word.Alignment.centered; - console.log(`Successfully the paragraph format of the '${styleName}' style.`); + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph( + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", + "Start" + ); + const paragraph: Word.Paragraph = body.paragraphs.getFirst(); + paragraph.style = style.nameLocal; + console.log(`'${styleName}' style applied to first paragraph.`); } }); -'Word.ParagraphFormat#leftIndent:member': +Word.Style#delete:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Sets certain aspects of the specified style's paragraph format e.g., the - left indent size and the alignment. + + // Deletes the custom style. await Word.run(async (context) => { - const styleName = $("#style-name").val() as string; + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; if (styleName == "") { - console.warn("Enter a style name to update its paragraph format."); + console.warn("Enter a style name to delete."); return; } - const style = context.document.getStyles().getByNameOrNullObject(styleName); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); style.load(); await context.sync(); if (style.isNullObject) { console.warn(`There's no existing style with the name '${styleName}'.`); } else { - style.paragraphFormat.leftIndent = 30; - style.paragraphFormat.alignment = Word.Alignment.centered; - console.log(`Successfully the paragraph format of the '${styleName}' style.`); + style.delete(); + console.log(`Successfully deleted custom style '${styleName}'.`); } }); -'Word.Range#compareLocationWith:member(1)': +Word.Style#borders:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/compare-location.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Compares the location of one paragraph in relation to another paragraph. + + // Updates border properties (e.g., type, width, color) of the specified + style. await Word.run(async (context) => { - const paragraphs = context.document.body.paragraphs; - paragraphs.load("items"); + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update border properties."); + return; + } + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); await context.sync(); - const firstParagraphAsRange = paragraphs.items[0].getRange(); - const secondParagraphAsRange = paragraphs.items[1].getRange(); - - const comparedLocation = firstParagraphAsRange.compareLocationWith(secondParagraphAsRange); - - await context.sync(); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + const borders: Word.BorderCollection = style.borders; + borders.load("items"); + await context.sync(); - console.log(`Location of the first paragraph in relation to the second paragraph: ${comparedLocation.value}`); + borders.outsideBorderType = Word.BorderType.dashed; + borders.outsideBorderWidth = Word.BorderWidth.pt025; + borders.outsideBorderColor = "green"; + console.log("Updated outside borders."); + } }); -'Word.Range#getComments:member(1)': +Word.Style#font:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Gets the comments in the selected content. + + // Updates font properties (e.g., color, size) of the specified style. await Word.run(async (context) => { - const comments = context.document.getSelection().getComments(); + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update font properties."); + return; + } - // Load objects for display in Script Lab console. - comments.load(); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); await context.sync(); - console.log("Comments:"); - console.log(comments); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + const font: Word.Font = style.font; + font.color = "#FF0000"; + font.size = 20; + console.log(`Successfully updated font properties of the '${styleName}' style.`); + } }); -'Word.Range#getReviewedText:member(1)': +Word.Style#listTemplate:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-change-tracking.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/manage-list-styles.yaml - // Gets the reviewed text. + + // Gets the properties of the specified style. await Word.run(async (context) => { - const range = context.document.getSelection(); - const before = range.getReviewedText(Word.ChangeTrackingVersion.original); - const after = range.getReviewedText(Word.ChangeTrackingVersion.current); + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to get properties."); + return; + } + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load("type"); await context.sync(); - console.log(`Reviewed text (before):\n${before.value}`); - console.log(`Reviewed text (after):\n${after.value}`); - }); -'Word.Range#getTextRanges:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml + if (style.isNullObject || style.type != Word.StyleType.list) { + console.warn(`There's no existing style with the name '${styleName}'. Or this isn't a list style.`); + } else { + // Load objects to log properties and their values in the console. + style.load(); + style.listTemplate.load(); + await context.sync(); - await Word.run(async (context) => { - // Get the complete sentence (as range) associated with the insertion point. - const sentences = context.document - .getSelection() - .getTextRanges(["."] /* Using the "." as delimiter */, false /*means without trimming spaces*/); - sentences.load("$none"); - await context.sync(); + console.log(`Properties of the '${styleName}' style:`, style); - // Expand the range to the end of the paragraph to get all the complete sentences. - const sentencesToTheEndOfParagraph = sentences.items[0] - .getRange() - .expandTo( - context.document - .getSelection() - .paragraphs.getFirst() - .getRange(Word.RangeLocation.end) - ) - .getTextRanges(["."], false /* Don't trim spaces*/); - sentencesToTheEndOfParagraph.load("text"); - await context.sync(); + const listLevels = style.listTemplate.listLevels; + listLevels.load("items"); + await context.sync(); - for (let i = 0; i < sentencesToTheEndOfParagraph.items.length; i++) { - console.log(sentencesToTheEndOfParagraph.items[i].text); + console.log(`List levels of the '${styleName}' style:`, listLevels); } }); -'Word.Range#insertComment:member(1)': +Word.Style#nameLocal:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Sets a comment on the selected content. + + // Applies the specified style to a paragraph. await Word.run(async (context) => { - const text = $("#comment-text") - .val() - .toString(); - const comment = context.document.getSelection().insertComment(text); + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to apply."); + return; + } - // Load object for display in Script Lab console. - comment.load(); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); await context.sync(); - console.log("Comment inserted:"); - console.log(comment); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else if (style.type != Word.StyleType.paragraph) { + console.log(`The '${styleName}' style isn't a paragraph style.`); + } else { + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph( + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", + "Start" + ); + const paragraph: Word.Paragraph = body.paragraphs.getFirst(); + paragraph.style = style.nameLocal; + console.log(`'${styleName}' style applied to first paragraph.`); + } }); -'Word.Range#insertContentControl:member(1)': +Word.Style#paragraphFormat:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/doc-assembly.yaml - - // Simulates creation of a template. First searches the document for - instances of the string "Contractor", - - // then changes the format of each search result, + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // then wraps each search result within a content control, - // finally sets a tag and title property on each content control. + // Sets certain aspects of the specified style's paragraph format e.g., the + left indent size and the alignment. await Word.run(async (context) => { - const results = context.document.body.search("Contractor"); - results.load("font/bold"); + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update its paragraph format."); + return; + } - // Check to make sure these content controls haven't been added yet. - const customerContentControls = context.document.contentControls.getByTag("customer"); - customerContentControls.load("text"); - await context.sync(); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); + await context.sync(); - if (customerContentControls.items.length === 0) { - for (let i = 0; i < results.items.length; i++) { - results.items[i].font.bold = true; - let cc = results.items[i].insertContentControl(); - cc.tag = "customer"; // This value is used in the next step of this sample. - cc.title = "Customer Name " + i; - } + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else { + style.paragraphFormat.leftIndent = 30; + style.paragraphFormat.alignment = Word.Alignment.centered; + console.log(`Successfully the paragraph format of the '${styleName}' style.`); } - await context.sync(); }); -'Word.Range#insertField:member(1)': +Word.Style#shading:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Inserts a Date field before selection. - await Word.run(async (context) => { - var range = context.document.getSelection().getRange(); + // Updates shading properties (e.g., texture, pattern colors) of the + specified style. - const field = range.insertField(Word.InsertLocation.before, Word.FieldType.date, '\\@ "M/d/yyyy h:mm am/pm"', true); + await Word.run(async (context) => { + const styleName = (document.getElementById("style-name") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to update shading properties."); + return; + } - field.load("result,code"); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); await context.sync(); - if (field.isNullObject) { - console.log("There are no fields in this document."); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); } else { - console.log("Code of the field: " + field.code); - console.log("Result of the field: " + JSON.stringify(field.result)); + const shading: Word.Shading = style.shading; + shading.load(); + await context.sync(); + + shading.backgroundPatternColor = "blue"; + shading.foregroundPatternColor = "yellow"; + shading.texture = Word.ShadingTextureType.darkTrellis; + + console.log("Updated shading."); } }); -'Word.Range#insertFootnote:member(1)': +Word.StyleCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Sets a footnote on the selected content. + + // Gets the number of available styles stored with the document. await Word.run(async (context) => { - const text = $("#input-footnote") - .val() - .toString(); - const footnote = context.document.getSelection().insertFootnote(text); + const styles: Word.StyleCollection = context.document.getStyles(); + const count = styles.getCount(); await context.sync(); - console.log("Inserted footnote."); + console.log(`Number of styles: ${count.value}`); }); -'Word.Range#footnotes:member': +Word.StyleCollection#getByNameOrNullObject:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml - // Gets the footnotes in the selected document range. + + // Adds a new style. await Word.run(async (context) => { - const footnotes = context.document.getSelection().footnotes; - footnotes.load("length"); + const newStyleName = (document.getElementById("new-style-name") as HTMLInputElement).value; + if (newStyleName == "") { + console.warn("Enter a style name to add."); + return; + } + + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(newStyleName); + style.load(); await context.sync(); - console.log("Number of footnotes in the selected range: " + footnotes.items.length); + if (!style.isNullObject) { + console.warn( + `There's an existing style with the same name '${newStyleName}'! Please provide another style name.` + ); + return; + } + + const newStyleType = ((document.getElementById("new-style-type") as HTMLSelectElement).value as unknown) as Word.StyleType; + context.document.addStyle(newStyleName, newStyleType); + await context.sync(); + + console.log(newStyleName + " has been added to the style list."); }); -'Word.Range#styleBuiltIn:member': +Word.StyleCollection#getCount:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/doc-assembly.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + + + // Gets the number of available styles stored with the document. await Word.run(async (context) => { - const header = context.document.body.insertText("This is a sample Heading 1 Title!!\n", - "Start" /*this means at the beginning of the body */); - header.styleBuiltIn = Word.BuiltInStyleName.heading1; + const styles: Word.StyleCollection = context.document.getStyles(); + const count = styles.getCount(); + await context.sync(); - await context.sync(); + console.log(`Number of styles: ${count.value}`); }); -'Word.RangeLocation:enum': +Word.StyleType:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + + + // Applies the specified style to a paragraph. await Word.run(async (context) => { - // Get the complete sentence (as range) associated with the insertion point. - const sentences = context.document - .getSelection() - .getTextRanges(["."] /* Using the "." as delimiter */, false /*means without trimming spaces*/); - sentences.load("$none"); - await context.sync(); + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to apply."); + return; + } - // Expand the range to the end of the paragraph to get all the complete sentences. - const sentencesToTheEndOfParagraph = sentences.items[0] - .getRange() - .expandTo( - context.document - .getSelection() - .paragraphs.getFirst() - .getRange(Word.RangeLocation.end) - ) - .getTextRanges(["."], false /* Don't trim spaces*/); - sentencesToTheEndOfParagraph.load("text"); + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load(); await context.sync(); - for (let i = 0; i < sentencesToTheEndOfParagraph.items.length; i++) { - console.log(sentencesToTheEndOfParagraph.items[i].text); + if (style.isNullObject) { + console.warn(`There's no existing style with the name '${styleName}'.`); + } else if (style.type != Word.StyleType.paragraph) { + console.log(`The '${styleName}' style isn't a paragraph style.`); + } else { + const body: Word.Body = context.document.body; + body.clear(); + body.insertParagraph( + "Do you want to create a solution that extends the functionality of Word? You can use the Office Add-ins platform to extend Word clients running on the web, on a Windows desktop, or on a Mac.", + "Start" + ); + const paragraph: Word.Paragraph = body.paragraphs.getFirst(); + paragraph.style = style.nameLocal; + console.log(`'${styleName}' style applied to first paragraph.`); } }); -'Word.Section:class': +Word.Table#getBorder:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-section-breaks.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Inserts a section break on the next page. - await Word.run(async (context) => { - const body = context.document.body; - body.insertBreak(Word.BreakType.sectionNext, Word.InsertLocation.end); + // Gets border details about the first table in the document. + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const borderLocation = Word.BorderLocation.top; + const border: Word.TableBorder = firstTable.getBorder(borderLocation); + border.load(["type", "color", "width"]); await context.sync(); - console.log("Inserted section break on next page"); + console.log(`Details about the ${borderLocation} border of the first table:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); -'Word.Section#getHeader:member(1)': +Word.Table#getCell:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-header-and-footer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/table-cell-access.yaml + + + // Gets the content of the first cell in the first table. await Word.run(async (context) => { - context.document.sections - .getFirst() - .getHeader(Word.HeaderFooterType.primary) - .insertParagraph("This is a primary header.", "End"); + const firstCell: Word.Body = context.document.body.tables.getFirst().getCell(0, 0).body; + firstCell.load("text"); await context.sync(); + console.log("First cell's text is: " + firstCell.text); }); -'Word.Section#getFooter:member(2)': +Word.Table#getCellPadding:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-header-and-footer.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - await Word.run(async (context) => { - context.document.sections - .getFirst() - .getFooter("Primary") - .insertParagraph("This is a primary footer.", "End"); + // Gets cell padding details about the first table in the document. + + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const cellPaddingLocation = Word.CellPaddingLocation.right; + const cellPadding = firstTable.getCellPadding(cellPaddingLocation); await context.sync(); + + console.log( + `Cell padding details about the ${cellPaddingLocation} border of the first table: ${cellPadding.value} points` + ); }); -'Word.SectionCollection:class': +Word.Table#alignment:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-section-breaks.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Inserts a section break on the next even page. - await Word.run(async (context) => { - const body = context.document.body; - body.insertBreak(Word.BreakType.sectionEven, Word.InsertLocation.end); + // Gets alignment details about the first table in the document. + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + firstTable.load(["alignment", "horizontalAlignment", "verticalAlignment"]); await context.sync(); - console.log("Inserted section break on next even page"); + console.log(`Details about the alignment of the first table:`, `- Alignment of the table within the containing page column: ${firstTable.alignment}`, `- Horizontal alignment of every cell in the table: ${firstTable.horizontalAlignment}`, `- Vertical alignment of every cell in the table: ${firstTable.verticalAlignment}`); }); -'Word.SelectionMode:enum': +Word.Table#horizontalAlignment:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/scroll-to-range.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - await Word.run(async (context) => { - // Select can be at the start or end of a range; this by definition moves the insertion point without selecting the range. - context.document.body.paragraphs.getLast().select(Word.SelectionMode.end); + // Gets alignment details about the first table in the document. + + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + firstTable.load(["alignment", "horizontalAlignment", "verticalAlignment"]); await context.sync(); + + console.log(`Details about the alignment of the first table:`, `- Alignment of the table within the containing page column: ${firstTable.alignment}`, `- Horizontal alignment of every cell in the table: ${firstTable.horizontalAlignment}`, `- Vertical alignment of every cell in the table: ${firstTable.verticalAlignment}`); }); -'Word.SettingCollection:class': +Word.Table#rows:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-settings.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Deletes all custom settings this add-in had set on this document. + + // Gets content alignment details about the first row of the first table in + the document. await Word.run(async (context) => { - const settings = context.document.settings; - settings.deleteAll(); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + firstTableRow.load(["horizontalAlignment", "verticalAlignment"]); await context.sync(); - console.log("All settings deleted"); + + console.log(`Details about the alignment of the first table's first row:`, `- Horizontal alignment of every cell in the row: ${firstTableRow.horizontalAlignment}`, `- Vertical alignment of every cell in the row: ${firstTableRow.verticalAlignment}`); }); -'Word.SettingCollection#add:member(1)': +Word.Table#verticalAlignment:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-settings.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Adds a new custom setting or - // edits the value of an existing one. + // Gets alignment details about the first table in the document. await Word.run(async (context) => { - const key = $("#key") - .val() - .toString(); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + firstTable.load(["alignment", "horizontalAlignment", "verticalAlignment"]); + await context.sync(); - if (key == "") { - console.error("Key shouldn't be empty"); - return; - } + console.log(`Details about the alignment of the first table:`, `- Alignment of the table within the containing page column: ${firstTable.alignment}`, `- Horizontal alignment of every cell in the table: ${firstTable.horizontalAlignment}`, `- Vertical alignment of every cell in the table: ${firstTable.verticalAlignment}`); + }); +Word.Table:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/table-cell-access.yaml - const value = $("#value") - .val() - .toString(); - const settings = context.document.settings; - const setting = settings.add(key, value); - setting.load(); - await context.sync(); + await Word.run(async (context) => { + // Use a two-dimensional array to hold the initial table values. + const data = [ + ["Tokyo", "Beijing", "Seattle"], + ["Apple", "Orange", "Pineapple"] + ]; + const table: Word.Table = context.document.body.insertTable(2, 3, "Start", data); + table.styleBuiltIn = Word.BuiltInStyleName.gridTable5Dark_Accent2; + table.styleFirstColumn = false; - console.log("Setting added or edited:"); - console.log(setting); + await context.sync(); }); -'Word.SettingCollection#items:member': +Word.TableBorder:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-settings.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Gets all custom settings this add-in set on this document. + + // Gets border details about the first table in the document. await Word.run(async (context) => { - const settings = context.document.settings; - settings.load("items"); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const borderLocation = Word.BorderLocation.top; + const border: Word.TableBorder = firstTable.getBorder(borderLocation); + border.load(["type", "color", "width"]); await context.sync(); - if (settings.items.length == 0) { - console.log("There are no settings"); - } else { - console.log("All settings:"); - for (let i = 0; i < settings.items.length; i++) { - console.log(settings.items[i]); - } - } + console.log(`Details about the ${borderLocation} border of the first table:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); -'Word.Style#delete:member(1)': +Word.TableBorder#color:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Deletes the custom style. - await Word.run(async (context) => { - const styleName = $("#style-name-to-delete").val() as string; - if (styleName == "") { - console.warn("Enter a style name to delete."); - return; - } + // Gets border details about the first table in the document. - const style = context.document.getStyles().getByNameOrNullObject(styleName); - style.load(); + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const borderLocation = Word.BorderLocation.top; + const border: Word.TableBorder = firstTable.getBorder(borderLocation); + border.load(["type", "color", "width"]); await context.sync(); - if (style.isNullObject) { - console.warn(`There's no existing style with the name '${styleName}'.`); - } else { - style.delete(); - console.log(`Successfully deleted custom style '${styleName}'.`); - } + console.log(`Details about the ${borderLocation} border of the first table:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); -'Word.Style#font:member': +Word.TableBorder#type:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Updates font properties (e.g., color, size) of the specified style. - await Word.run(async (context) => { - const styleName = $("#style-name").val() as string; - if (styleName == "") { - console.warn("Enter a style name to update font properties."); - return; - } + // Gets border details about the first table in the document. - const style = context.document.getStyles().getByNameOrNullObject(styleName); - style.load(); + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const borderLocation = Word.BorderLocation.top; + const border: Word.TableBorder = firstTable.getBorder(borderLocation); + border.load(["type", "color", "width"]); await context.sync(); - if (style.isNullObject) { - console.warn(`There's no existing style with the name '${styleName}'.`); - } else { - const font = style.font; - font.color = "#FF0000"; - font.size = 20; - console.log(`Successfully updated font properties of the '${styleName}' style.`); - } + console.log(`Details about the ${borderLocation} border of the first table:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); -'Word.Style#nameLocal:member': +Word.TableBorder#width:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Applies the specified style to a paragraph. - await Word.run(async (context) => { - const styleName = $("#style-name-to-use").val() as string; - if (styleName == "") { - console.warn("Enter a style name to apply."); - return; - } + // Gets border details about the first table in the document. - const style = context.document.getStyles().getByNameOrNullObject(styleName); - style.load(); + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const borderLocation = Word.BorderLocation.top; + const border: Word.TableBorder = firstTable.getBorder(borderLocation); + border.load(["type", "color", "width"]); await context.sync(); - if (style.isNullObject) { - console.warn(`There's no existing style with the name '${styleName}'.`); - } else if (style.type != Word.StyleType.paragraph) { - console.log(`The '${styleName}' style isn't a paragraph style.`); - } else { - const body = context.document.body; - body.clear(); - body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", - "Start" - ); - const paragraph = body.paragraphs.getFirst(); - paragraph.style = style.nameLocal; - console.log(`'${styleName}' style applied to first paragraph.`); - } + console.log(`Details about the ${borderLocation} border of the first table:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); -'Word.Style#paragraphFormat:member': +Word.TableCell:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Sets certain aspects of the specified style's paragraph format e.g., the - left indent size and the alignment. - await Word.run(async (context) => { - const styleName = $("#style-name").val() as string; - if (styleName == "") { - console.warn("Enter a style name to update its paragraph format."); - return; - } + // Gets content alignment details about the first cell of the first table in + the document. - const style = context.document.getStyles().getByNameOrNullObject(styleName); - style.load(); + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + const firstCell: Word.TableCell = firstTableRow.cells.getFirst(); + firstCell.load(["horizontalAlignment", "verticalAlignment"]); await context.sync(); - if (style.isNullObject) { - console.warn(`There's no existing style with the name '${styleName}'.`); - } else { - style.paragraphFormat.leftIndent = 30; - style.paragraphFormat.alignment = Word.Alignment.centered; - console.log(`Successfully the paragraph format of the '${styleName}' style.`); - } + console.log(`Details about the alignment of the first table's first cell:`, `- Horizontal alignment of the cell's content: ${firstCell.horizontalAlignment}`, `- Vertical alignment of the cell's content: ${firstCell.verticalAlignment}`); }); -'Word.StyleCollection#getByNameOrNullObject:member(1)': +Word.TableCell#getBorder:member(2): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Adds a new style. - await Word.run(async (context) => { - const newStyleName = $("#new-style-name").val() as string; - if (newStyleName == "") { - console.warn("Enter a style name to add."); - return; - } + // Gets border details about the first of the first table in the document. - const style = context.document.getStyles().getByNameOrNullObject(newStyleName); - style.load(); + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstCell: Word.TableCell = firstTable.getCell(0, 0); + const borderLocation = "Left"; + const border: Word.TableBorder = firstCell.getBorder(borderLocation); + border.load(["type", "color", "width"]); await context.sync(); - if (!style.isNullObject) { - console.warn( - `There's an existing style with the same name '${newStyleName}'! Please provide another style name.` - ); - return; - } - - const newStyleType = ($("#new-style-type").val() as unknown) as Word.StyleType; - context.document.addStyle(newStyleName, newStyleType); - await context.sync(); - - console.log(newStyleName + " has been added to the style list."); + console.log(`Details about the ${borderLocation} border of the first table's first cell:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); -'Word.StyleCollection#getCount:member(1)': +Word.TableCell#getCellPadding:member(2): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Gets the number of styles. + + // Gets cell padding details about the first cell of the first table in the + document. await Word.run(async (context) => { - const styles = context.document.getStyles(); - const count = styles.getCount(); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstCell: Word.TableCell = firstTable.getCell(0, 0); + const cellPaddingLocation = "Left"; + const cellPadding = firstCell.getCellPadding(cellPaddingLocation); await context.sync(); - console.log(`Number of styles: ${count.value}`); + console.log( + `Cell padding details about the ${cellPaddingLocation} border of the first table's first cell: ${cellPadding.value} points` + ); }); -'Word.StyleType:enum': +Word.TableCell#horizontalAlignment:member: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Applies the specified style to a paragraph. - await Word.run(async (context) => { - const styleName = $("#style-name-to-use").val() as string; - if (styleName == "") { - console.warn("Enter a style name to apply."); - return; - } + // Gets content alignment details about the first cell of the first table in + the document. - const style = context.document.getStyles().getByNameOrNullObject(styleName); - style.load(); + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + const firstCell: Word.TableCell = firstTableRow.cells.getFirst(); + firstCell.load(["horizontalAlignment", "verticalAlignment"]); await context.sync(); - if (style.isNullObject) { - console.warn(`There's no existing style with the name '${styleName}'.`); - } else if (style.type != Word.StyleType.paragraph) { - console.log(`The '${styleName}' style isn't a paragraph style.`); - } else { - const body = context.document.body; - body.clear(); - body.insertParagraph( - "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document.", - "Start" - ); - const paragraph = body.paragraphs.getFirst(); - paragraph.style = style.nameLocal; - console.log(`'${styleName}' style applied to first paragraph.`); - } + console.log(`Details about the alignment of the first table's first cell:`, `- Horizontal alignment of the cell's content: ${firstCell.horizontalAlignment}`, `- Vertical alignment of the cell's content: ${firstCell.verticalAlignment}`); + }); +Word.TableCell#verticalAlignment:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + + + // Gets content alignment details about the first cell of the first table in + the document. + + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + const firstCell: Word.TableCell = firstTableRow.cells.getFirst(); + firstCell.load(["horizontalAlignment", "verticalAlignment"]); + await context.sync(); + + console.log(`Details about the alignment of the first table's first cell:`, `- Horizontal alignment of the cell's content: ${firstCell.horizontalAlignment}`, `- Vertical alignment of the cell's content: ${firstCell.verticalAlignment}`); }); -'Word.Table:class': +Word.TableCellCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/table-cell-access.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - await Word.run(async (context) => { - // Use a two-dimensional array to hold the initial table values. - const data = [ - ["Tokyo", "Beijing", "Seattle"], - ["Apple", "Orange", "Pineapple"] - ]; - const table = context.document.body.insertTable(2, 3, "Start", data); - table.styleBuiltIn = Word.BuiltInStyleName.gridTable5Dark_Accent2; - table.styleFirstColumn = false; + // Gets content alignment details about the first cell of the first table in + the document. + + await Word.run(async (context) => { + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + const firstCell: Word.TableCell = firstTableRow.cells.getFirst(); + firstCell.load(["horizontalAlignment", "verticalAlignment"]); await context.sync(); + + console.log(`Details about the alignment of the first table's first cell:`, `- Horizontal alignment of the cell's content: ${firstCell.horizontalAlignment}`, `- Vertical alignment of the cell's content: ${firstCell.verticalAlignment}`); }); -'Word.Table#getBorder:member(1)': +Word.TableCollection:class: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Gets border details about the first table in the document. + + // Gets alignment details about the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const borderLocation = Word.BorderLocation.top; - const border = firstTable.getBorder(borderLocation); - border.load(["type", "color", "width"]); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + firstTable.load(["alignment", "horizontalAlignment", "verticalAlignment"]); await context.sync(); - console.log(`Details about the ${borderLocation} border of the first table:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + console.log(`Details about the alignment of the first table:`, `- Alignment of the table within the containing page column: ${firstTable.alignment}`, `- Horizontal alignment of every cell in the table: ${firstTable.horizontalAlignment}`, `- Vertical alignment of every cell in the table: ${firstTable.verticalAlignment}`); }); -'Word.Table#getCell:member(1)': +Word.TableCollection#getFirst:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/table-cell-access.yaml + // Gets the content of the first cell in the first table. await Word.run(async (context) => { - const firstCell = context.document.body.tables.getFirst().getCell(0, 0).body; + const firstCell: Word.Body = context.document.body.tables.getFirst().getCell(0, 0).body; firstCell.load("text"); await context.sync(); console.log("First cell's text is: " + firstCell.text); }); -'Word.Table#getCellPadding:member(1)': +Word.TableRow:class: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Gets cell padding details about the first table in the document. + + // Gets content alignment details about the first cell of the first table in + the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const cellPaddingLocation = Word.CellPaddingLocation.right; - const cellPadding = firstTable.getCellPadding(cellPaddingLocation); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + const firstCell: Word.TableCell = firstTableRow.cells.getFirst(); + firstCell.load(["horizontalAlignment", "verticalAlignment"]); await context.sync(); - console.log( - `Cell padding details about the ${cellPaddingLocation} border of the first table: ${cellPadding.value} points` - ); + console.log(`Details about the alignment of the first table's first cell:`, `- Horizontal alignment of the cell's content: ${firstCell.horizontalAlignment}`, `- Vertical alignment of the cell's content: ${firstCell.verticalAlignment}`); }); -'Word.Table#alignment:member': +Word.TableRow#getBorder:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Gets alignment details about the first table in the document. + + // Gets border details about the first row of the first table in the + document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - firstTable.load(["alignment", "horizontalAlignment", "verticalAlignment"]); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + const borderLocation = Word.BorderLocation.bottom; + const border: Word.TableBorder = firstTableRow.getBorder(borderLocation); + border.load(["type", "color", "width"]); await context.sync(); - console.log(`Details about the alignment of the first table:`); - console.log(`- Alignment of the table within the containing page column: ${firstTable.alignment}`); - console.log(`- Horizontal alignment of every cell in the table: ${firstTable.horizontalAlignment}`); - console.log(`- Vertical alignment of every cell in the table: ${firstTable.verticalAlignment}`); + console.log(`Details about the ${borderLocation} border of the first table's first row:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); -'Word.Table#horizontalAlignment:member': +Word.TableRow#getCellPadding:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Gets alignment details about the first table in the document. + + // Gets cell padding details about the first row of the first table in the + document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - firstTable.load(["alignment", "horizontalAlignment", "verticalAlignment"]); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + const cellPaddingLocation = Word.CellPaddingLocation.bottom; + const cellPadding = firstTableRow.getCellPadding(cellPaddingLocation); await context.sync(); - console.log(`Details about the alignment of the first table:`); - console.log(`- Alignment of the table within the containing page column: ${firstTable.alignment}`); - console.log(`- Horizontal alignment of every cell in the table: ${firstTable.horizontalAlignment}`); - console.log(`- Vertical alignment of every cell in the table: ${firstTable.verticalAlignment}`); + console.log( + `Cell padding details about the ${cellPaddingLocation} border of the first table's first row: ${cellPadding.value} points` + ); }); -'Word.Table#rows:member': +Word.TableRow#cells:member: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Gets content alignment details about the first row of the first table in + + // Gets content alignment details about the first cell of the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstTableRow = firstTable.rows.getFirst(); - firstTableRow.load(["horizontalAlignment", "verticalAlignment"]); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + const firstCell: Word.TableCell = firstTableRow.cells.getFirst(); + firstCell.load(["horizontalAlignment", "verticalAlignment"]); await context.sync(); - console.log(`Details about the alignment of the first table's first row:`); - console.log(`- Horizontal alignment of every cell in the row: ${firstTableRow.horizontalAlignment}`); - console.log(`- Vertical alignment of every cell in the row: ${firstTableRow.verticalAlignment}`); + console.log(`Details about the alignment of the first table's first cell:`, `- Horizontal alignment of the cell's content: ${firstCell.horizontalAlignment}`, `- Vertical alignment of the cell's content: ${firstCell.verticalAlignment}`); }); -'Word.Table#verticalAlignment:member': +Word.TableRowCollection:class: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Gets alignment details about the first table in the document. + + // Gets content alignment details about the first row of the first table in + the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - firstTable.load(["alignment", "horizontalAlignment", "verticalAlignment"]); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + firstTableRow.load(["horizontalAlignment", "verticalAlignment"]); await context.sync(); - console.log(`Details about the alignment of the first table:`); - console.log(`- Alignment of the table within the containing page column: ${firstTable.alignment}`); - console.log(`- Horizontal alignment of every cell in the table: ${firstTable.horizontalAlignment}`); - console.log(`- Vertical alignment of every cell in the table: ${firstTable.verticalAlignment}`); + console.log(`Details about the alignment of the first table's first row:`, `- Horizontal alignment of every cell in the row: ${firstTableRow.horizontalAlignment}`, `- Vertical alignment of every cell in the row: ${firstTableRow.verticalAlignment}`); }); -'Word.TableBorder#color:member': +Word.TableRowCollection#getFirst:member(1): - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml - // Gets border details about the first table in the document. + + // Gets border details about the first row of the first table in the + document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const borderLocation = Word.BorderLocation.top; - const border = firstTable.getBorder(borderLocation); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); + const borderLocation = Word.BorderLocation.bottom; + const border: Word.TableBorder = firstTableRow.getBorder(borderLocation); border.load(["type", "color", "width"]); await context.sync(); - console.log(`Details about the ${borderLocation} border of the first table:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + console.log(`Details about the ${borderLocation} border of the first table's first row:`, `- Color: ${border.color}`, `- Type: ${border.type}`, `- Width: ${border.width} points`); }); -'Word.TableBorder#type:member': +Word.TableStyle:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-custom-style.yaml + + + // Gets the table style properties and displays them in the form. + + const styleName = (document.getElementById("style-name") as + HTMLInputElement).value; + + if (styleName == "") { + console.warn("Please input a table style name."); + return; + } - // Gets border details about the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const borderLocation = Word.BorderLocation.top; - const border = firstTable.getBorder(borderLocation); - border.load(["type", "color", "width"]); + const tableStyle: Word.TableStyle = context.document.getStyles().getByName(styleName).tableStyle; + tableStyle.load(); await context.sync(); - console.log(`Details about the ${borderLocation} border of the first table:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + if (tableStyle.isNullObject) { + console.warn(`There's no existing table style with the name '${styleName}'.`); + return; + } + + console.log(tableStyle); + (document.getElementById("alignment") as HTMLInputElement).value = tableStyle.alignment; + (document.getElementById("allow-break-across-page") as HTMLInputElement).value = tableStyle.allowBreakAcrossPage.toString(); + (document.getElementById("top-cell-margin") as HTMLInputElement).value = tableStyle.topCellMargin; + (document.getElementById("bottom-cell-margin") as HTMLInputElement).value = tableStyle.bottomCellMargin; + (document.getElementById("left-cell-margin") as HTMLInputElement).value = tableStyle.leftCellMargin; + (document.getElementById("right-cell-margin") as HTMLInputElement).value = tableStyle.rightCellMargin; + (document.getElementById("cell-spacing") as HTMLInputElement).value = tableStyle.cellSpacing; }); -'Word.TableBorder#width:member': +Word.TrackedChange:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml - // Gets border details about the first table in the document. + + // Gets the next (second) tracked change. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const borderLocation = Word.BorderLocation.top; - const border = firstTable.getBorder(borderLocation); - border.load(["type", "color", "width"]); + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + await context.sync(); + + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); + await context.sync(); + + const nextTrackedChange: Word.TrackedChange = trackedChange.getNext(); + await context.sync(); + + nextTrackedChange.load(["author", "date", "text", "type"]); await context.sync(); - console.log(`Details about the ${borderLocation} border of the first table:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + console.log(nextTrackedChange); }); -'Word.TableCell:class': +Word.TrackedChange#accept:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/table-cell-access.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml - // Gets the content of the first cell in the first table. - await Word.run(async (context) => { - const firstCell = context.document.body.tables.getFirst().getCell(0, 0).body; - firstCell.load("text"); + // Accepts the first tracked change. + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); + trackedChange.load(); await context.sync(); - console.log("First cell's text is: " + firstCell.text); + + console.log("First tracked change:", trackedChange); + trackedChange.accept(); + console.log("Accepted the first tracked change."); }); -'Word.TableCell#getBorder:member(2)': +Word.TrackedChange#getNext:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml - // Gets border details about the first of the first table in the document. + + // Gets the next (second) tracked change. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstCell = firstTable.getCell(0, 0); - const borderLocation = "Left"; - const border = firstCell.getBorder(borderLocation); - border.load(["type", "color", "width"]); + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + await context.sync(); + + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); + await context.sync(); + + const nextTrackedChange: Word.TrackedChange = trackedChange.getNext(); + await context.sync(); + + nextTrackedChange.load(["author", "date", "text", "type"]); await context.sync(); - console.log(`Details about the ${borderLocation} border of the first table's first cell:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + console.log(nextTrackedChange); }); -'Word.TableCell#getCellPadding:member(2)': +Word.TrackedChange#getRange:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml - // Gets cell padding details about the first cell of the first table in the - document. + + // Gets the range of the first tracked change. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstCell = firstTable.getCell(0, 0); - const cellPaddingLocation = "Left"; - const cellPadding = firstCell.getCellPadding(cellPaddingLocation); + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); await context.sync(); - console.log( - `Cell padding details about the ${cellPaddingLocation} border of the first table's first cell: ${cellPadding.value} points` - ); + const range: Word.Range = trackedChange.getRange(); + range.load(); + await context.sync(); + + console.log("range.text: " + range.text); }); -'Word.TableCell#horizontalAlignment:member': +Word.TrackedChange#reject:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml - // Gets content alignment details about the first cell of the first table in - the document. + + // Rejects the first tracked change. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstCell = firstTable.getCell(0, 0); - firstCell.load(["horizontalAlignment", "verticalAlignment"]); + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); + trackedChange.load(); await context.sync(); - console.log(`Details about the alignment of the first table's first cell:`); - console.log(`- Horizontal alignment of the cell's content: ${firstCell.horizontalAlignment}`); - console.log(`- Vertical alignment of the cell's content: ${firstCell.verticalAlignment}`); + console.log("First tracked change:", trackedChange); + trackedChange.reject(); + console.log("Rejected the first tracked change."); }); -'Word.TableCell#verticalAlignment:member': +Word.TrackedChangeCollection:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml - // Gets content alignment details about the first cell of the first table in - the document. + + // Gets the range of the first tracked change. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstCell = firstTable.getCell(0, 0); - firstCell.load(["horizontalAlignment", "verticalAlignment"]); + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); await context.sync(); - console.log(`Details about the alignment of the first table's first cell:`); - console.log(`- Horizontal alignment of the cell's content: ${firstCell.horizontalAlignment}`); - console.log(`- Vertical alignment of the cell's content: ${firstCell.verticalAlignment}`); + const range: Word.Range = trackedChange.getRange(); + range.load(); + await context.sync(); + + console.log("range.text: " + range.text); }); -'Word.TableCollection:class': +Word.TrackedChangeCollection#acceptAll:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml - // Gets alignment details about the first table in the document. - await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - firstTable.load(["alignment", "horizontalAlignment", "verticalAlignment"]); - await context.sync(); + // Accepts all tracked changes. - console.log(`Details about the alignment of the first table:`); - console.log(`- Alignment of the table within the containing page column: ${firstTable.alignment}`); - console.log(`- Horizontal alignment of every cell in the table: ${firstTable.horizontalAlignment}`); - console.log(`- Vertical alignment of every cell in the table: ${firstTable.verticalAlignment}`); + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + trackedChanges.acceptAll(); + console.log("Accepted all tracked changes."); }); -'Word.TableCollection#getFirst:member(1)': +Word.TrackedChangeCollection#getFirst:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/table-cell-access.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml - // Gets the content of the first cell in the first table. + + // Gets the range of the first tracked change. await Word.run(async (context) => { - const firstCell = context.document.body.tables.getFirst().getCell(0, 0).body; - firstCell.load("text"); + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); + await context.sync(); + const range: Word.Range = trackedChange.getRange(); + range.load(); await context.sync(); - console.log("First cell's text is: " + firstCell.text); + + console.log("range.text: " + range.text); }); -'Word.TableRow#getBorder:member(1)': +Word.TrackedChangeCollection#rejectAll:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml - // Gets border details about the first row of the first table in the - document. + + // Rejects all tracked changes. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstTableRow = firstTable.rows.getFirst(); - const borderLocation = Word.BorderLocation.bottom; - const border = firstTableRow.getBorder(borderLocation); - border.load(["type", "color", "width"]); + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); + trackedChanges.rejectAll(); + console.log("Rejected all tracked changes."); + }); +Word.TrackedChangeType:enum: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml + + + // Gets the next (second) tracked change. + + await Word.run(async (context) => { + const body: Word.Body = context.document.body; + const trackedChanges: Word.TrackedChangeCollection = body.getTrackedChanges(); await context.sync(); - console.log(`Details about the ${borderLocation} border of the first table's first row:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + const trackedChange: Word.TrackedChange = trackedChanges.getFirst(); + await context.sync(); + + const nextTrackedChange: Word.TrackedChange = trackedChange.getNext(); + await context.sync(); + + nextTrackedChange.load(["author", "date", "text", "type"]); + await context.sync(); + + console.log(nextTrackedChange); }); -'Word.TableRow#getCellPadding:member(1)': +Word.TrailingCharacter:enum: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/manage-list-styles.yaml - // Gets cell padding details about the first row of the first table in the - document. + + // Gets the properties of the specified style. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstTableRow = firstTable.rows.getFirst(); - const cellPaddingLocation = Word.CellPaddingLocation.bottom; - const cellPadding = firstTableRow.getCellPadding(cellPaddingLocation); + const styleName = (document.getElementById("style-name-to-use") as HTMLInputElement).value; + if (styleName == "") { + console.warn("Enter a style name to get properties."); + return; + } + + const style: Word.Style = context.document.getStyles().getByNameOrNullObject(styleName); + style.load("type"); await context.sync(); - console.log( - `Cell padding details about the ${cellPaddingLocation} border of the first table's first row: ${cellPadding.value} points` - ); + if (style.isNullObject || style.type != Word.StyleType.list) { + console.warn(`There's no existing style with the name '${styleName}'. Or this isn't a list style.`); + } else { + // Load objects to log properties and their values in the console. + style.load(); + style.listTemplate.load(); + await context.sync(); + + console.log(`Properties of the '${styleName}' style:`, style); + + const listLevels = style.listTemplate.listLevels; + listLevels.load("items"); + await context.sync(); + + console.log(`List levels of the '${styleName}' style:`, listLevels); + } }); -'Word.TableRowCollection:class': +Word.VerticalAlignment:enum: - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + // Gets content alignment details about the first row of the first table in the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstTableRow = firstTable.rows.getFirst(); + const firstTable: Word.Table = context.document.body.tables.getFirst(); + const firstTableRow: Word.TableRow = firstTable.rows.getFirst(); firstTableRow.load(["horizontalAlignment", "verticalAlignment"]); await context.sync(); - console.log(`Details about the alignment of the first table's first row:`); - console.log(`- Horizontal alignment of every cell in the row: ${firstTableRow.horizontalAlignment}`); - console.log(`- Vertical alignment of every cell in the row: ${firstTableRow.verticalAlignment}`); + console.log(`Details about the alignment of the first table's first row:`, `- Horizontal alignment of every cell in the row: ${firstTableRow.horizontalAlignment}`, `- Vertical alignment of every cell in the row: ${firstTableRow.verticalAlignment}`); }); -'Word.TableRowCollection#getFirst:member(1)': +Word.Window:class: - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml - // Gets border details about the first row of the first table in the - document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstTableRow = firstTable.rows.getFirst(); - const borderLocation = Word.BorderLocation.bottom; - const border = firstTableRow.getBorder(borderLocation); - border.load(["type", "color", "width"]); + // Gets the first paragraph of each page. + console.log("Getting first paragraph of each page..."); + + // Get the active window. + const activeWindow: Word.Window = context.document.activeWindow; + activeWindow.load(); + + // Get the active pane. + const activePane: Word.Pane = activeWindow.activePane; + activePane.load(); + + // Get all pages. + const pages: Word.PageCollection = activePane.pages; + pages.load(); + + await context.sync(); + + // Get page index and paragraphs of each page. + const pagesIndexes = []; + const pagesNumberOfParagraphs = []; + const pagesFirstParagraphText = []; + for (let i = 0; i < pages.items.length; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); + + const paragraphs = page.getRange().paragraphs; + paragraphs.load("items/length"); + pagesNumberOfParagraphs.push(paragraphs); + + const firstParagraph = paragraphs.getFirst(); + firstParagraph.load("text"); + pagesFirstParagraphText.push(firstParagraph); + } + await context.sync(); - console.log(`Details about the ${borderLocation} border of the first table's first row:`); - console.log(`- Color: ${border.color}`); - console.log(`- Type: ${border.type}`); - console.log(`- Width: ${border.width} points`); + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Page index: ${pagesIndexes[i].index}`); + console.log(`Number of paragraphs: ${pagesNumberOfParagraphs[i].items.length}`); + console.log("First paragraph's text:", pagesFirstParagraphText[i].text); + } }); -'Word.VerticalAlignment:enum': +Word.Window#close:member(1): - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/close-document-window.yaml - // Gets content alignment details about the first row of the first table in - the document. await Word.run(async (context) => { - const firstTable = context.document.body.tables.getFirst(); - const firstTableRow = firstTable.rows.getFirst(); - firstTableRow.load(["horizontalAlignment", "verticalAlignment"]); + // Closes the document window, prompting to save if this is a new document. + const window: Word.Window = context.document.activeWindow; + const closeOptions: Word.WindowCloseOptions = { saveChanges: Word.SaveConfiguration.promptToSaveChanges }; + console.log("About to close the document window..."); + window.close(closeOptions); + }); +Word.Window#activePane:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml + + + await Word.run(async (context) => { + // Gets the pages enclosing the viewport. + + // Get the active window. + const activeWindow: Word.Window = context.document.activeWindow; + activeWindow.load(); + + // Get the active pane. + const activePane: Word.Pane = activeWindow.activePane; + activePane.load(); + + // Get pages enclosing the viewport. + const pages: Word.PageCollection = activePane.pagesEnclosingViewport; + pages.load(); + + await context.sync(); + + // Log the number of pages. + const pageCount = pages.items.length; + console.log(`Number of pages enclosing the viewport: ${pageCount}`); + + // Log index info of these pages. + const pagesIndexes = []; + for (let i = 0; i < pageCount; i++) { + const page = pages.items[i]; + page.load("index"); + pagesIndexes.push(page); + } + + await context.sync(); + + for (let i = 0; i < pagesIndexes.length; i++) { + console.log(`Page index: ${pagesIndexes[i].index}`); + } + }); +Word.Window#panes:member: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml + + + await Word.run(async (context) => { + // Gets all the panes in the active document window. + + // Get the active window. + const activeWindow: Word.Window = context.document.activeWindow; + activeWindow.load("panes/items/length"); + + await context.sync(); + + const panes: Word.PaneCollection = activeWindow.panes; + console.log(`Number of panes in the current document window: ${panes.items.length}`); + }); +Word.WindowCloseOptions:interface: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/close-document-window.yaml + + + await Word.run(async (context) => { + // Closes the document window, prompting to save if this is a new document. + const window: Word.Window = context.document.activeWindow; + const closeOptions: Word.WindowCloseOptions = { saveChanges: Word.SaveConfiguration.promptToSaveChanges }; + console.log("About to close the document window..."); + window.close(closeOptions); + }); +Word.WindowCollection:class: + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml + + + await Word.run(async (context) => { + // Gets the document windows. + const windows: Word.WindowCollection = context.document.windows; + windows.load("windows/items/length"); + await context.sync(); - console.log(`Details about the alignment of the first table's first row:`); - console.log(`- Horizontal alignment of every cell in the row: ${firstTableRow.horizontalAlignment}`); - console.log(`- Vertical alignment of every cell in the row: ${firstTableRow.verticalAlignment}`); + console.log(`Number of windows for this document: ${windows.items.length}`); }); diff --git a/tsconfig.json b/tsconfig.json index 0fd566d63..a3ff66e69 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,13 @@ { "compilerOptions": { - "target": "es6", + "target": "es2018", "module": "commonjs", "moduleResolution": "node", "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "allowSyntheticDefaultImports": true, + "esModuleInterop": true, "removeComments": false, "noImplicitAny": false, "noEmitOnError": true, @@ -17,8 +18,10 @@ "rootDir": "config", "lib": [ "dom", - "es2015" + "es2018" ], - "pretty": true + "pretty": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true } } \ No newline at end of file diff --git a/view-prod/excel.json b/view-prod/excel.json index 303a72725..38e8b6628 100644 --- a/view-prod/excel.json +++ b/view-prod/excel.json @@ -17,10 +17,13 @@ "excel-chart-title-format": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-title-format.yaml", "excel-chart-data-source": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-source.yaml", "excel-chart-trendlines": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-trendlines.yaml", - "excel-comment-basics": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-basics.yaml", - "excel-comment-mentions": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-mentions.yaml", - "excel-comment-replies": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-replies.yaml", - "excel-comment-resolution": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comment/comment-resolution.yaml", + "excel-chart-data-labels": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-labels.yaml", + "excel-chart-leader-lines": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml", + "excel-comment-basics": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-basics.yaml", + "excel-comment-mentions": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-mentions.yaml", + "excel-comment-replies": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-replies.yaml", + "excel-comment-resolution": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/comment-resolution.yaml", + "excel-note-basics": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/12-comments-and-notes/excel-note-basics.yaml", "excel-range-conditional-formatting-basic": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml", "excel-range-conditional-formatting-advanced": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/14-conditional-formatting/conditional-formatting-advanced.yaml", "excel-custom-functions-basic": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/16-custom-functions/basic-function.yaml", @@ -29,16 +32,18 @@ "excel-custom-functions-web-call": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/16-custom-functions/web-call-function.yaml", "excel-custom-functions-errors": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/16-custom-functions/custom-functions-errors.yaml", "excel-data-types-custom-functions": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/16-custom-functions/data-types-custom-functions.yaml", + "excel-custom-functions-custom-enum": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/16-custom-functions/custom-enum.yaml", "excel-custom-xml-parts-create-set-get-and-delete-custom-xml-parts": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/create-set-get-and-delete-custom-xml-parts.yaml", "excel-custom-xml-parts-test-xml-for-unique-namespace": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/18-custom-xml-parts/test-xml-for-unique-namespace.yaml", "excel-chart-chart-title-ts": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/private-samples/excel/20-chart/chart-title-ts.yaml", - "excel-data-types-formatted-number": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-formatted-number.yaml", + "excel-data-types-doubles": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-formatted-number.yaml", "excel-data-types-web-image": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-web-image.yaml", "excel-data-types-entity-values": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-entity-values.yaml", "excel-data-types-error-values": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-error-values.yaml", "excel-data-types-icons": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-entity-icons.yaml", "excel-data-types-entity-attribution": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-entity-attribution.yaml", "excel-data-types-references": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-references.yaml", + "excel-data-types-basic-types": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-basic-types.yaml", "excel-data-validation": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/22-data-validation/data-validation.yaml", "excel-document-get-file-in-slices-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/26-document/get-file-in-slices-async.yaml", "excel-document-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/26-document/properties.yaml", @@ -92,12 +97,14 @@ "excel-range-get-range-edge": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-get-range-edge.yaml", "excel-direct-dependents": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-direct-dependents.yaml", "excel-range-dependents": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-dependents.yaml", + "excel-cell-controls": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml", "excel-shape-create-and-delete": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-create-and-delete.yaml", "excel-shape-images": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-images.yaml", "excel-shape-lines": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-lines.yaml", "excel-shape-move-and-order": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-move-and-order.yaml", "excel-shape-groups": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-groups.yaml", "excel-shape-textboxes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-textboxes.yaml", + "excel-shape-get-active": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/44-shape/shape-get-active.yaml", "excel-table-add-rows-and-columns-to-a-table": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/46-table/add-rows-and-columns-to-a-table.yaml", "excel-table-convert-range-to-table": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/46-table/convert-range-to-table.yaml", "excel-table-create-table": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/46-table/create-table.yaml", @@ -117,6 +124,7 @@ "excel-workbook-data-protection": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/data-protection.yaml", "excel-workbook-save-and-close": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-save-and-close.yaml", "excel-workbook-insert-external-worksheets": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-insert-external-worksheets.yaml", + "excel-workbook-built-in-function": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/50-workbook/workbook-built-in-functions.yaml", "excel-worksheet-active-worksheet": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/active-worksheet.yaml", "excel-worksheet-add-delete-rename-move-worksheet": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/add-delete-rename-move-worksheet.yaml", "excel-worksheet-auto-filter": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/54-worksheet/worksheet-auto-filter.yaml", diff --git a/view-prod/outlook.json b/view-prod/outlook.json index 83e0bc2ac..3eeda67db 100644 --- a/view-prod/outlook.json +++ b/view-prod/outlook.json @@ -9,6 +9,7 @@ "outlook-item-body-prepend-text-to-item-body": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/prepend-text-to-item-body.yaml", "outlook-item-body-prepend-text-on-send": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/20-item-body/prepend-text-on-send.yaml", "outlook-item-save-and-close-close": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/25-item-save-and-close/close.yaml", + "outlook-close-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/25-item-save-and-close/close-async.yaml", "outlook-item-save-and-close-save": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/25-item-save-and-close/save.yaml", "outlook-recipients-and-attendees-get-from-message-read": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-from-message-read.yaml", "outlook-recipients-and-attendees-get-from-message-compose": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/30-recipients-and-attendees/get-from-message-compose.yaml", @@ -45,18 +46,15 @@ "outlook-delegates-and-shared-folders-get-shared-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml", "outlook-mime-headers-get-internet-headers-message-read": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/get-internet-headers-message-read.yaml", "outlook-mime-headers-manage-custom-internet-headers-message-compose": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml", - "outlook-entities-and-regex-matches-basic-entities": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/basic-entities.yaml", - "outlook-entities-and-regex-matches-contextual": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/contextual.yaml", - "outlook-entities-and-regex-matches-selected": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-entities-and-regex-matches/selected.yaml", - "outlook-tokens-and-service-calls-ids-and-urls": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/ids-and-urls.yaml", - "outlook-tokens-and-service-calls-user-identity-token": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/user-identity-token.yaml", - "outlook-tokens-and-service-calls-user-callback-token": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/user-callback-token.yaml", - "outlook-tokens-and-service-calls-basic-rest-cors": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/basic-rest-cors.yaml", - "outlook-tokens-and-service-calls-make-ews-request-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/make-ews-request-async.yaml", - "outlook-tokens-and-service-calls-send-message-using-make-ews-request-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/send-message-using-make-ews-request-async.yaml", - "outlook-tokens-and-service-calls-get-icaluid-as-organizer": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-organizer.yaml", - "outlook-tokens-and-service-calls-get-icaluid-as-attendee": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-attendee.yaml", - "outlook-tokens-and-service-calls-item-id-compose": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-and-service-calls/item-id-compose.yaml", + "outlook-regex-matches-contextual": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/75-regex-matches/contextual.yaml", + "outlook-events-drag-drop-item": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/80-events/drag-drop-item.yaml", + "outlook-tokens-and-service-calls-ids-and-urls": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/ids-and-urls.yaml", + "outlook-tokens-and-service-calls-user-identity-token": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/user-identity-token.yaml", + "outlook-tokens-and-service-calls-user-callback-token": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/user-callback-token.yaml", + "outlook-tokens-and-service-calls-make-ews-request-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/make-ews-request-async.yaml", + "outlook-tokens-and-service-calls-send-message-using-make-ews-request-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/send-message-using-make-ews-request-async.yaml", + "outlook-tokens-and-service-calls-get-icaluid-as-organizer": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-organizer.yaml", + "outlook-tokens-and-service-calls-get-icaluid-as-attendee": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-attendee.yaml", "outlook-other-item-apis-get-subject-read": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-subject-read.yaml", "outlook-other-item-apis-get-set-subject-compose": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-subject-compose.yaml", "outlook-item-body-set-selected-data": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/set-selected-data.yaml", @@ -78,7 +76,15 @@ "outlook-other-item-apis-work-with-client-signatures": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml", "outlook-other-item-apis-session-data-apis": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/session-data-apis.yaml", "outlook-delay-message-delivery": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/delay-message-delivery.yaml", - "outlook-calendar-properties-apis": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/calendar-properties-apis.yaml", - "outlook-close-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/close-async.yaml", + "outlook-other-item-apis-get-message-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-message-properties.yaml", + "outlook-other-item-apis-get-set-sensitivity-level": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-set-sensitivity-level.yaml", + "outlook-get-eml-format": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-eml-format.yaml", + "outlook-get-in-reply-to": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-in-reply-to.yaml", + "outlook-get-conversation-index": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-conversation-index.yaml", + "outlook-get-item-class-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-item-class-async.yaml", + "outlook-other-item-apis-item-id-compose": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/item-id-compose.yaml", + "outlook-send-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/send-async.yaml", + "outlook-other-item-apis-get-loaded-message-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/90-other-item-apis/get-loaded-message-properties.yaml", + "outlook-get-set-isalldayevent": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/get-set-isalldayevent.yaml", "outlook-set-displayed-body-subject": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml" } \ No newline at end of file diff --git a/view-prod/powerpoint.json b/view-prod/powerpoint.json index b5321196c..3174b1a57 100644 --- a/view-prod/powerpoint.json +++ b/view-prod/powerpoint.json @@ -3,15 +3,21 @@ "powerpoint-basics-basic-api-call-js": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/basics/basic-api-call-js.yaml", "powerpoint-basics-basic-common-api-call": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/basics/basic-common-api-call.yaml", "powerpoint-create-presentation": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/document/create-presentation.yaml", + "powerpoint-hyperlinks-manage-hyperlinks": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/hyperlinks/manage-hyperlinks.yaml", "powerpoint-basics-insert-image": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/images/insert-image.yaml", "powerpoint-basics-insert-svg": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/images/insert-svg.yaml", "powerpoint-scenarios-searches-wikipedia-api": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/scenarios/searches-wikipedia-api.yaml", - "powerpoint-shapes-get-set-shapes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml", "powerpoint-shapes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/shapes.yaml", + "powerpoint-shapes-get-set-shapes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-set-shapes.yaml", + "powerpoint-shapes-get-shapes-by-type": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/get-shapes-by-type.yaml", + "powerpoint-shapes-add-modify-tables": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/add-modify-tables.yaml", + "powerpoint-shapes-binding-to-shapes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/binding-to-shapes.yaml", + "powerpoint-shapes-group-ungroup-shapes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/shapes/group-ungroup-shapes.yaml", "powerpoint-add-slides": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/add-slides.yaml", "powerpoint-insert-slides": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/insert-slides.yaml", "powerpoint-basics-get-slide-metadata": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-slide-metadata.yaml", "powerpoint-slide-management-get-set-slides": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/get-set-slides.yaml", + "powerpoint-slide-management-export-import-slide": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/slide-management/export-import-slide.yaml", "powerpoint-tags": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/tags/tags.yaml", "powerpoint-text-get-set-textrange": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/powerpoint/text/get-set-textrange.yaml" } \ No newline at end of file diff --git a/view-prod/word.json b/view-prod/word.json index b1cb5ebf6..f91bdf5ba 100644 --- a/view-prod/word.json +++ b/view-prod/word.json @@ -9,8 +9,13 @@ "word-content-controls-content-control-ondatachanged-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondatachanged-event.yaml", "word-content-controls-content-control-onexited-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-onexited-event.yaml", "word-content-controls-content-control-ondeleted-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/content-control-ondeleted-event.yaml", + "word-content-controls-insert-and-change-checkbox-content-control": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml", + "word-content-controls-insert-and-change-combo-box-content-control": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml", + "word-content-controls-insert-and-change-dropdown-list-content-control": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml", + "word-content-controls-get-change-tracking-states": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/10-content-controls/get-change-tracking-states.yaml", "word-images-insert-and-get-pictures": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/15-images/insert-and-get-pictures.yaml", "word-lists-insert-list": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/insert-list.yaml", + "word-lists-manage-styles": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/manage-list-styles.yaml", "word-lists-organize-list": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/20-lists/organize-list.yaml", "word-paragraph-get-paragraph-on-insertion-point": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml", "word-paragraph-insert-line-and-page-breaks": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/insert-line-and-page-breaks.yaml", @@ -20,16 +25,25 @@ "word-paragraph-paragraph-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/paragraph-properties.yaml", "word-paragraph-search": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/search.yaml", "word-paragraph-get-word-count": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-word-count.yaml", + "word-paragraph-get-text": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/get-text.yaml", + "word-paragraph-onadded-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onadded-event.yaml", + "word-paragraph-onchanged-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/onchanged-event.yaml", + "word-paragraph-ondeleted-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/25-paragraph/ondeleted-event.yaml", "word-properties-get-built-in-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/get-built-in-properties.yaml", "word-properties-read-write-custom-document-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/30-properties/read-write-custom-document-properties.yaml", "word-ranges-scroll-to-range": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/scroll-to-range.yaml", "word-ranges-split-words-of-first-paragraph": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/split-words-of-first-paragraph.yaml", "word-ranges-compare-location": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/compare-location.yaml", + "word-ranges-get-pages": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/35-ranges/get-pages.yaml", "word-tables-table-cell-access": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/table-cell-access.yaml", "word-tables-manage-formatting": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-formatting.yaml", + "word-tables-manage-custom-style": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/40-tables/manage-custom-style.yaml", + "word-shapes-manage-shapes-text-boxes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/45-shapes/manage-shapes-text-boxes.yaml", + "word-document-manage-body": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-body.yaml", "word-document-insert-section-breaks": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-section-breaks.yaml", "word-document-insert-external-document": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/insert-external-document.yaml", "word-document-manage-change-tracking": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-change-tracking.yaml", + "word-document-manage-tracked-changes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-tracked-changes.yaml", "word-document-manage-comments": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-comments.yaml", "word-document-manage-footnotes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-footnotes.yaml", "word-document-manage-fields": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-fields.yaml", @@ -37,8 +51,14 @@ "word-document-manage-custom-xml-part-ns": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part-ns.yaml", "word-document-manage-custom-xml-part": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-custom-xml-part.yaml", "word-document-manage-styles": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-styles.yaml", + "word-document-get-external-styles": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/get-external-styles.yaml", "word-document-save-close": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/save-close.yaml", + "word-document-manage-annotations": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/manage-annotations.yaml", + "word-document-compare-documents": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/compare-documents.yaml", "word-scenarios-doc-assembly": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/doc-assembly.yaml", "word-scenarios-multiple-property-set": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/multiple-property-set.yaml", - "word-insert-and-get-pictures": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/insert-and-get-pictures.yaml" + "word-scenarios-correlated-objects-pattern": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/correlated-objects-pattern.yaml", + "word-close-document-window": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/close-document-window.yaml", + "word-insert-and-change-content-controls": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/insert-and-change-content-controls.yaml", + "word-manage-comments": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml" } \ No newline at end of file diff --git a/view/excel.json b/view/excel.json index ddc6200cd..6c50b9c80 100644 --- a/view/excel.json +++ b/view/excel.json @@ -17,10 +17,13 @@ "excel-chart-title-format": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/10-chart/chart-title-format.yaml", "excel-chart-data-source": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/10-chart/chart-data-source.yaml", "excel-chart-trendlines": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/10-chart/chart-trendlines.yaml", - "excel-comment-basics": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comment/comment-basics.yaml", - "excel-comment-mentions": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comment/comment-mentions.yaml", - "excel-comment-replies": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comment/comment-replies.yaml", - "excel-comment-resolution": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comment/comment-resolution.yaml", + "excel-chart-data-labels": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/10-chart/chart-data-labels.yaml", + "excel-chart-leader-lines": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/10-chart/chart-leader-lines.yaml", + "excel-comment-basics": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comments-and-notes/comment-basics.yaml", + "excel-comment-mentions": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comments-and-notes/comment-mentions.yaml", + "excel-comment-replies": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comments-and-notes/comment-replies.yaml", + "excel-comment-resolution": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comments-and-notes/comment-resolution.yaml", + "excel-note-basics": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/12-comments-and-notes/excel-note-basics.yaml", "excel-range-conditional-formatting-basic": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/14-conditional-formatting/conditional-formatting-basic.yaml", "excel-range-conditional-formatting-advanced": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/14-conditional-formatting/conditional-formatting-advanced.yaml", "excel-custom-functions-basic": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/16-custom-functions/basic-function.yaml", @@ -29,16 +32,18 @@ "excel-custom-functions-web-call": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/16-custom-functions/web-call-function.yaml", "excel-custom-functions-errors": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/16-custom-functions/custom-functions-errors.yaml", "excel-data-types-custom-functions": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/16-custom-functions/data-types-custom-functions.yaml", + "excel-custom-functions-custom-enum": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/16-custom-functions/custom-enum.yaml", "excel-custom-xml-parts-create-set-get-and-delete-custom-xml-parts": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/18-custom-xml-parts/create-set-get-and-delete-custom-xml-parts.yaml", "excel-custom-xml-parts-test-xml-for-unique-namespace": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/18-custom-xml-parts/test-xml-for-unique-namespace.yaml", "excel-chart-chart-title-ts": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/private-samples/excel/20-chart/chart-title-ts.yaml", - "excel-data-types-formatted-number": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-formatted-number.yaml", + "excel-data-types-doubles": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-formatted-number.yaml", "excel-data-types-web-image": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-web-image.yaml", "excel-data-types-entity-values": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-entity-values.yaml", "excel-data-types-error-values": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-error-values.yaml", "excel-data-types-icons": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-entity-icons.yaml", "excel-data-types-entity-attribution": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-entity-attribution.yaml", "excel-data-types-references": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-references.yaml", + "excel-data-types-basic-types": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/20-data-types/data-types-basic-types.yaml", "excel-data-validation": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/22-data-validation/data-validation.yaml", "excel-document-get-file-in-slices-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/26-document/get-file-in-slices-async.yaml", "excel-document-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/26-document/properties.yaml", @@ -92,12 +97,14 @@ "excel-range-get-range-edge": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/42-range/range-get-range-edge.yaml", "excel-direct-dependents": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/42-range/range-direct-dependents.yaml", "excel-range-dependents": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/42-range/range-dependents.yaml", + "excel-cell-controls": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/42-range/range-cell-control.yaml", "excel-shape-create-and-delete": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/44-shape/shape-create-and-delete.yaml", "excel-shape-images": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/44-shape/shape-images.yaml", "excel-shape-lines": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/44-shape/shape-lines.yaml", "excel-shape-move-and-order": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/44-shape/shape-move-and-order.yaml", "excel-shape-groups": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/44-shape/shape-groups.yaml", "excel-shape-textboxes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/44-shape/shape-textboxes.yaml", + "excel-shape-get-active": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/44-shape/shape-get-active.yaml", "excel-table-add-rows-and-columns-to-a-table": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/46-table/add-rows-and-columns-to-a-table.yaml", "excel-table-convert-range-to-table": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/46-table/convert-range-to-table.yaml", "excel-table-create-table": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/46-table/create-table.yaml", @@ -117,6 +124,7 @@ "excel-workbook-data-protection": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/50-workbook/data-protection.yaml", "excel-workbook-save-and-close": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/50-workbook/workbook-save-and-close.yaml", "excel-workbook-insert-external-worksheets": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/50-workbook/workbook-insert-external-worksheets.yaml", + "excel-workbook-built-in-function": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/50-workbook/workbook-built-in-functions.yaml", "excel-worksheet-active-worksheet": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/54-worksheet/active-worksheet.yaml", "excel-worksheet-add-delete-rename-move-worksheet": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/54-worksheet/add-delete-rename-move-worksheet.yaml", "excel-worksheet-auto-filter": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/excel/54-worksheet/worksheet-auto-filter.yaml", diff --git a/view/outlook.json b/view/outlook.json index 83c8738c3..6e7f14ee6 100644 --- a/view/outlook.json +++ b/view/outlook.json @@ -9,6 +9,7 @@ "outlook-item-body-prepend-text-to-item-body": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/20-item-body/prepend-text-to-item-body.yaml", "outlook-item-body-prepend-text-on-send": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/20-item-body/prepend-text-on-send.yaml", "outlook-item-save-and-close-close": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/25-item-save-and-close/close.yaml", + "outlook-close-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/25-item-save-and-close/close-async.yaml", "outlook-item-save-and-close-save": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/25-item-save-and-close/save.yaml", "outlook-recipients-and-attendees-get-from-message-read": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/30-recipients-and-attendees/get-from-message-read.yaml", "outlook-recipients-and-attendees-get-from-message-compose": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/30-recipients-and-attendees/get-from-message-compose.yaml", @@ -45,18 +46,15 @@ "outlook-delegates-and-shared-folders-get-shared-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/65-delegates-and-shared-folders/get-shared-properties.yaml", "outlook-mime-headers-get-internet-headers-message-read": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/70-mime-headers/get-internet-headers-message-read.yaml", "outlook-mime-headers-manage-custom-internet-headers-message-compose": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/70-mime-headers/manage-custom-internet-headers-message-compose.yaml", - "outlook-entities-and-regex-matches-basic-entities": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/75-entities-and-regex-matches/basic-entities.yaml", - "outlook-entities-and-regex-matches-contextual": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/75-entities-and-regex-matches/contextual.yaml", - "outlook-entities-and-regex-matches-selected": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/75-entities-and-regex-matches/selected.yaml", - "outlook-tokens-and-service-calls-ids-and-urls": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/ids-and-urls.yaml", - "outlook-tokens-and-service-calls-user-identity-token": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/user-identity-token.yaml", - "outlook-tokens-and-service-calls-user-callback-token": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/user-callback-token.yaml", - "outlook-tokens-and-service-calls-basic-rest-cors": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/basic-rest-cors.yaml", - "outlook-tokens-and-service-calls-make-ews-request-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/make-ews-request-async.yaml", - "outlook-tokens-and-service-calls-send-message-using-make-ews-request-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/send-message-using-make-ews-request-async.yaml", - "outlook-tokens-and-service-calls-get-icaluid-as-organizer": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-organizer.yaml", - "outlook-tokens-and-service-calls-get-icaluid-as-attendee": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/get-icaluid-as-attendee.yaml", - "outlook-tokens-and-service-calls-item-id-compose": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-and-service-calls/item-id-compose.yaml", + "outlook-regex-matches-contextual": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/75-regex-matches/contextual.yaml", + "outlook-events-drag-drop-item": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/80-events/drag-drop-item.yaml", + "outlook-tokens-and-service-calls-ids-and-urls": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/ids-and-urls.yaml", + "outlook-tokens-and-service-calls-user-identity-token": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/user-identity-token.yaml", + "outlook-tokens-and-service-calls-user-callback-token": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/user-callback-token.yaml", + "outlook-tokens-and-service-calls-make-ews-request-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/make-ews-request-async.yaml", + "outlook-tokens-and-service-calls-send-message-using-make-ews-request-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/send-message-using-make-ews-request-async.yaml", + "outlook-tokens-and-service-calls-get-icaluid-as-organizer": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-organizer.yaml", + "outlook-tokens-and-service-calls-get-icaluid-as-attendee": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/85-tokens-for-exchange-on-premises/get-icaluid-as-attendee.yaml", "outlook-other-item-apis-get-subject-read": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-subject-read.yaml", "outlook-other-item-apis-get-set-subject-compose": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-set-subject-compose.yaml", "outlook-item-body-set-selected-data": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/set-selected-data.yaml", @@ -78,7 +76,15 @@ "outlook-other-item-apis-work-with-client-signatures": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/work-with-client-signatures.yaml", "outlook-other-item-apis-session-data-apis": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/session-data-apis.yaml", "outlook-delay-message-delivery": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/delay-message-delivery.yaml", - "outlook-calendar-properties-apis": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/99-preview-apis/calendar-properties-apis.yaml", - "outlook-close-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/99-preview-apis/close-async.yaml", + "outlook-other-item-apis-get-message-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-message-properties.yaml", + "outlook-other-item-apis-get-set-sensitivity-level": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-set-sensitivity-level.yaml", + "outlook-get-eml-format": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-eml-format.yaml", + "outlook-get-in-reply-to": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-in-reply-to.yaml", + "outlook-get-conversation-index": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-conversation-index.yaml", + "outlook-get-item-class-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-item-class-async.yaml", + "outlook-other-item-apis-item-id-compose": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/item-id-compose.yaml", + "outlook-send-async": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/send-async.yaml", + "outlook-other-item-apis-get-loaded-message-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/90-other-item-apis/get-loaded-message-properties.yaml", + "outlook-get-set-isalldayevent": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/99-preview-apis/get-set-isalldayevent.yaml", "outlook-set-displayed-body-subject": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/outlook/99-preview-apis/set-displayed-body-subject.yaml" } \ No newline at end of file diff --git a/view/powerpoint.json b/view/powerpoint.json index 2dddac939..76e7bddc5 100644 --- a/view/powerpoint.json +++ b/view/powerpoint.json @@ -3,15 +3,21 @@ "powerpoint-basics-basic-api-call-js": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/basics/basic-api-call-js.yaml", "powerpoint-basics-basic-common-api-call": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/basics/basic-common-api-call.yaml", "powerpoint-create-presentation": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/document/create-presentation.yaml", + "powerpoint-hyperlinks-manage-hyperlinks": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/hyperlinks/manage-hyperlinks.yaml", "powerpoint-basics-insert-image": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/images/insert-image.yaml", "powerpoint-basics-insert-svg": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/images/insert-svg.yaml", "powerpoint-scenarios-searches-wikipedia-api": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/scenarios/searches-wikipedia-api.yaml", - "powerpoint-shapes-get-set-shapes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/get-set-shapes.yaml", "powerpoint-shapes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/shapes.yaml", + "powerpoint-shapes-get-set-shapes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/get-set-shapes.yaml", + "powerpoint-shapes-get-shapes-by-type": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/get-shapes-by-type.yaml", + "powerpoint-shapes-add-modify-tables": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/add-modify-tables.yaml", + "powerpoint-shapes-binding-to-shapes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/binding-to-shapes.yaml", + "powerpoint-shapes-group-ungroup-shapes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/shapes/group-ungroup-shapes.yaml", "powerpoint-add-slides": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/slide-management/add-slides.yaml", "powerpoint-insert-slides": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/slide-management/insert-slides.yaml", "powerpoint-basics-get-slide-metadata": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/slide-management/get-slide-metadata.yaml", "powerpoint-slide-management-get-set-slides": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/slide-management/get-set-slides.yaml", + "powerpoint-slide-management-export-import-slide": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/slide-management/export-import-slide.yaml", "powerpoint-tags": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/tags/tags.yaml", "powerpoint-text-get-set-textrange": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/powerpoint/text/get-set-textrange.yaml" } \ No newline at end of file diff --git a/view/word.json b/view/word.json index 6d7009305..ebef6fc8f 100644 --- a/view/word.json +++ b/view/word.json @@ -9,8 +9,13 @@ "word-content-controls-content-control-ondatachanged-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/content-control-ondatachanged-event.yaml", "word-content-controls-content-control-onexited-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/content-control-onexited-event.yaml", "word-content-controls-content-control-ondeleted-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/content-control-ondeleted-event.yaml", + "word-content-controls-insert-and-change-checkbox-content-control": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/insert-and-change-checkbox-content-control.yaml", + "word-content-controls-insert-and-change-combo-box-content-control": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/insert-and-change-combo-box-content-control.yaml", + "word-content-controls-insert-and-change-dropdown-list-content-control": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/insert-and-change-dropdown-list-content-control.yaml", + "word-content-controls-get-change-tracking-states": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/10-content-controls/get-change-tracking-states.yaml", "word-images-insert-and-get-pictures": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/15-images/insert-and-get-pictures.yaml", "word-lists-insert-list": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/20-lists/insert-list.yaml", + "word-lists-manage-styles": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/20-lists/manage-list-styles.yaml", "word-lists-organize-list": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/20-lists/organize-list.yaml", "word-paragraph-get-paragraph-on-insertion-point": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/get-paragraph-on-insertion-point.yaml", "word-paragraph-insert-line-and-page-breaks": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/insert-line-and-page-breaks.yaml", @@ -20,16 +25,25 @@ "word-paragraph-paragraph-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/paragraph-properties.yaml", "word-paragraph-search": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/search.yaml", "word-paragraph-get-word-count": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/get-word-count.yaml", + "word-paragraph-get-text": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/get-text.yaml", + "word-paragraph-onadded-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/onadded-event.yaml", + "word-paragraph-onchanged-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/onchanged-event.yaml", + "word-paragraph-ondeleted-event": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/25-paragraph/ondeleted-event.yaml", "word-properties-get-built-in-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/30-properties/get-built-in-properties.yaml", "word-properties-read-write-custom-document-properties": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/30-properties/read-write-custom-document-properties.yaml", "word-ranges-scroll-to-range": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/35-ranges/scroll-to-range.yaml", "word-ranges-split-words-of-first-paragraph": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/35-ranges/split-words-of-first-paragraph.yaml", "word-ranges-compare-location": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/35-ranges/compare-location.yaml", + "word-ranges-get-pages": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/35-ranges/get-pages.yaml", "word-tables-table-cell-access": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/40-tables/table-cell-access.yaml", "word-tables-manage-formatting": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/40-tables/manage-formatting.yaml", + "word-tables-manage-custom-style": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/40-tables/manage-custom-style.yaml", + "word-shapes-manage-shapes-text-boxes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/45-shapes/manage-shapes-text-boxes.yaml", + "word-document-manage-body": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-body.yaml", "word-document-insert-section-breaks": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/insert-section-breaks.yaml", "word-document-insert-external-document": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/insert-external-document.yaml", "word-document-manage-change-tracking": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-change-tracking.yaml", + "word-document-manage-tracked-changes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-tracked-changes.yaml", "word-document-manage-comments": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-comments.yaml", "word-document-manage-footnotes": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-footnotes.yaml", "word-document-manage-fields": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-fields.yaml", @@ -37,8 +51,14 @@ "word-document-manage-custom-xml-part-ns": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-custom-xml-part-ns.yaml", "word-document-manage-custom-xml-part": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-custom-xml-part.yaml", "word-document-manage-styles": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-styles.yaml", + "word-document-get-external-styles": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/get-external-styles.yaml", "word-document-save-close": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/save-close.yaml", + "word-document-manage-annotations": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/manage-annotations.yaml", + "word-document-compare-documents": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/compare-documents.yaml", "word-scenarios-doc-assembly": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/90-scenarios/doc-assembly.yaml", "word-scenarios-multiple-property-set": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/90-scenarios/multiple-property-set.yaml", - "word-insert-and-get-pictures": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/99-preview-apis/insert-and-get-pictures.yaml" + "word-scenarios-correlated-objects-pattern": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/90-scenarios/correlated-objects-pattern.yaml", + "word-close-document-window": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/99-preview-apis/close-document-window.yaml", + "word-insert-and-change-content-controls": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/99-preview-apis/insert-and-change-content-controls.yaml", + "word-manage-comments": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/99-preview-apis/manage-comments.yaml" } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 44cdeb503..000000000 --- a/yarn.lock +++ /dev/null @@ -1,973 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@^7.0.0": - version "7.15.8" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz" - integrity sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg== - dependencies: - "@babel/highlight" "^7.14.5" - -"@babel/helper-validator-identifier@^7.14.5": - version "7.15.7" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz" - integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== - -"@babel/highlight@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz" - integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== - dependencies: - "@babel/helper-validator-identifier" "^7.14.5" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@fast-csv/format@4.3.5": - version "4.3.5" - resolved "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz" - integrity sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A== - dependencies: - "@types/node" "^14.0.1" - lodash.escaperegexp "^4.1.2" - lodash.isboolean "^3.0.3" - lodash.isequal "^4.5.0" - lodash.isfunction "^3.0.9" - lodash.isnil "^4.0.0" - -"@fast-csv/parse@4.3.6": - version "4.3.6" - resolved "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz" - integrity sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA== - dependencies: - "@types/node" "^14.0.1" - lodash.escaperegexp "^4.1.2" - lodash.groupby "^4.6.0" - lodash.isfunction "^3.0.9" - lodash.isnil "^4.0.0" - lodash.isundefined "^3.0.1" - lodash.uniq "^4.5.0" - -"@types/chalk@0.4.31": - version "0.4.31" - resolved "https://registry.npmjs.org/@types/chalk/-/chalk-0.4.31.tgz" - integrity sha1-ox10JBprHtu5c8822XooloNKUfk= - -"@types/fs-extra@3.0.1": - version "3.0.1" - resolved "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-3.0.1.tgz" - integrity sha1-eCk6aKrT2GZ1Ho/P1k19ydARdHY= - dependencies: - "@types/node" "*" - -"@types/glob@*": - version "7.1.4" - resolved "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz" - integrity sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - -"@types/js-yaml@^3.12.0": - version "3.12.7" - resolved "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.7.tgz" - integrity sha512-S6+8JAYTE1qdsc9HMVsfY7+SgSuUU/Tp6TYTmITW0PZxiyIMvol3Gy//y69Wkhs0ti4py5qgR3uZH6uz/DNzJQ== - -"@types/lodash@^4.14.175": - version "4.14.175" - resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.175.tgz" - integrity sha512-XmdEOrKQ8a1Y/yxQFOMbC47G/V2VDO1GvMRnl4O75M4GW/abC5tnfzadQYkqEveqRM1dEJGFFegfPNA2vvx2iw== - -"@types/minimatch@*": - version "3.0.5" - resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz" - integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== - -"@types/node@*": - version "16.10.3" - resolved "https://registry.npmjs.org/@types/node/-/node-16.10.3.tgz" - integrity sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ== - -"@types/node@^11.10.5": - version "11.15.54" - resolved "https://registry.npmjs.org/@types/node/-/node-11.15.54.tgz" - integrity sha512-1RWYiq+5UfozGsU6MwJyFX6BtktcT10XRjvcAQmskCtMcW3tPske88lM/nHv7BQG1w9KBXI1zPGuu5PnNCX14g== - -"@types/node@^14.0.1": - version "14.17.21" - resolved "https://registry.npmjs.org/@types/node/-/node-14.17.21.tgz" - integrity sha512-zv8ukKci1mrILYiQOwGSV4FpkZhyxQtuFWGya2GujWg+zVAeRQ4qbaMmWp9vb9889CFA8JECH7lkwCL6Ygg8kA== - -"@types/shelljs@^0.8.3": - version "0.8.9" - resolved "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.9.tgz" - integrity sha512-flVe1dvlrCyQJN/SGrnBxqHG+RzXrVKsmjD8WS/qYHpq5UPjfq7UWFBENP0ZuOl0g6OpAlL6iBoLSvKYUUmyQw== - dependencies: - "@types/glob" "*" - "@types/node" "*" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -archiver-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz" - integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw== - dependencies: - glob "^7.1.4" - graceful-fs "^4.2.0" - lazystream "^1.0.0" - lodash.defaults "^4.2.0" - lodash.difference "^4.5.0" - lodash.flatten "^4.4.0" - lodash.isplainobject "^4.0.6" - lodash.union "^4.6.0" - normalize-path "^3.0.0" - readable-stream "^2.0.0" - -archiver@^5.0.0: - version "5.3.0" - resolved "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz" - integrity sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg== - dependencies: - archiver-utils "^2.1.0" - async "^3.2.0" - buffer-crc32 "^0.2.1" - readable-stream "^3.6.0" - readdir-glob "^1.0.0" - tar-stream "^2.2.0" - zip-stream "^4.1.0" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -async@^3.2.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" - integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -big-integer@^1.6.17: - version "1.6.49" - resolved "https://registry.npmjs.org/big-integer/-/big-integer-1.6.49.tgz" - integrity sha512-KJ7VhqH+f/BOt9a3yMwJNmcZjG53ijWMTjSAGMveQWyLwqIiwkjNP5PFgDob3Snnx86SjDj6I89fIbv0dkQeNw== - -binary@~0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz" - integrity sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk= - dependencies: - buffers "~0.1.1" - chainsaw "~0.1.0" - -bl@^4.0.3: - version "4.1.0" - resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - -bluebird@~3.4.1: - version "3.4.7" - resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz" - integrity sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM= - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -buffer-crc32@^0.2.1, buffer-crc32@^0.2.13: - version "0.2.13" - resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= - -buffer-indexof-polyfill@~1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz" - integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A== - -buffer@^5.5.0: - version "5.7.1" - resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -buffers@~0.1.1: - version "0.1.1" - resolved "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" - integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s= - -builtin-modules@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= - -chainsaw@~0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz" - integrity sha1-XqtQsor+WAdNDVgpE4iCi15fvJg= - dependencies: - traverse ">=0.3.0 <0.4" - -chalk@1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.3.0: - version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -charm@1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/charm/-/charm-1.0.1.tgz" - integrity sha1-aFZqelU9T+kXlwMN0YUtDdbvqC0= - dependencies: - inherits "^2.0.1" - -cli-cursor@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz" - integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= - dependencies: - restore-cursor "^1.0.1" - -cli-spinners@0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.2.0.tgz" - integrity sha1-hQeHN5E7iA9uyf/ntl6D7Hd2KE8= - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -colors@1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz" - integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= - -commander@^2.12.1: - version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -compress-commons@^4.1.0: - version "4.1.1" - resolved "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz" - integrity sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ== - dependencies: - buffer-crc32 "^0.2.13" - crc32-stream "^4.0.2" - normalize-path "^3.0.0" - readable-stream "^3.6.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -crc-32@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz" - integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== - dependencies: - exit-on-epipe "~1.0.1" - printj "~1.1.0" - -crc32-stream@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz" - integrity sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w== - dependencies: - crc-32 "^1.2.0" - readable-stream "^3.4.0" - -dayjs@^1.8.34: - version "1.10.7" - resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz" - integrity sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -duplexer2@~0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz" - integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= - dependencies: - readable-stream "^2.0.2" - -end-of-stream@^1.4.1: - version "1.4.4" - resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -exceljs@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/exceljs/-/exceljs-4.3.0.tgz" - integrity sha512-hTAeo5b5TPvf8Z02I2sKIT4kSfCnOO2bCxYX8ABqODCdAjppI3gI9VYiGCQQYVcBaBSKlFDMKlAQRqC+kV9O8w== - dependencies: - archiver "^5.0.0" - dayjs "^1.8.34" - fast-csv "^4.3.1" - jszip "^3.5.0" - readable-stream "^3.6.0" - saxes "^5.0.1" - tmp "^0.2.0" - unzipper "^0.10.11" - uuid "^8.3.0" - -exit-hook@^1.0.0: - version "1.1.1" - resolved "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz" - integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= - -exit-on-epipe@~1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz" - integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== - -fast-csv@^4.3.1: - version "4.3.6" - resolved "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz" - integrity sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw== - dependencies: - "@fast-csv/format" "4.3.5" - "@fast-csv/parse" "4.3.6" - -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - -fs-extra@3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz" - integrity sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE= - dependencies: - graceful-fs "^4.1.2" - jsonfile "^3.0.0" - universalify "^0.1.0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fstream@^1.0.12: - version "1.0.12" - resolved "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz" - integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -glob@^7.0.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: - version "7.2.0" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2: - version "4.2.8" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -immediate@~3.0.5: - version "3.0.6" - resolved "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz" - integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -interpret@^1.0.0: - version "1.4.0" - resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - -is-core-module@^2.2.0: - version "2.7.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.7.0.tgz" - integrity sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ== - dependencies: - has "^1.0.3" - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsonfile@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz" - integrity sha1-pezG9l9T9mLEQVx2daAzHQmS7GY= - optionalDependencies: - graceful-fs "^4.1.6" - -jszip@^3.5.0: - version "3.7.1" - resolved "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz" - integrity sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg== - dependencies: - lie "~3.3.0" - pako "~1.0.2" - readable-stream "~2.3.6" - set-immediate-shim "~1.0.1" - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz" - integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= - dependencies: - readable-stream "^2.0.5" - -lie@~3.3.0: - version "3.3.0" - resolved "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz" - integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== - dependencies: - immediate "~3.0.5" - -listenercount@~1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz" - integrity sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc= - -lodash.defaults@^4.2.0: - version "4.2.0" - resolved "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz" - integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= - -lodash.difference@^4.5.0: - version "4.5.0" - resolved "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz" - integrity sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw= - -lodash.escaperegexp@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz" - integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c= - -lodash.flatten@^4.4.0: - version "4.4.0" - resolved "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz" - integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= - -lodash.groupby@^4.6.0: - version "4.6.0" - resolved "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz" - integrity sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E= - -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz" - integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= - -lodash.isequal@^4.5.0: - version "4.5.0" - resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - -lodash.isfunction@^3.0.9: - version "3.0.9" - resolved "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz" - integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw== - -lodash.isnil@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz" - integrity sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw= - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" - integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= - -lodash.isundefined@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz" - integrity sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g= - -lodash.union@^4.6.0: - version "4.6.0" - resolved "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz" - integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg= - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" - integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== - -"mkdirp@>=0.5 0", mkdirp@^0.5.3: - version "0.5.5" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -node-status@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/node-status/-/node-status-1.0.0.tgz" - integrity sha1-eQanxHplh9A0lr907GNKuqA/joA= - dependencies: - charm "1.0.1" - cli-cursor "^1.0.2" - cli-spinners "0.2.0" - colors "1.1.2" - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onetime@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz" - integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= - -pako@~1.0.2: - version "1.0.11" - resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-parse@^1.0.6: - version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -printj@~1.1.0: - version "1.1.2" - resolved "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz" - integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdir-glob@^1.0.0: - version "1.1.1" - resolved "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz" - integrity sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA== - dependencies: - minimatch "^3.0.4" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - -resolve@^1.1.6, resolve@^1.3.2: - version "1.20.0" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - -restore-cursor@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz" - integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= - dependencies: - exit-hook "^1.0.0" - onetime "^1.0.0" - -rimraf@2: - version "2.7.1" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -saxes@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz" - integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== - dependencies: - xmlchars "^2.2.0" - -semver@^5.3.0: - version "5.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -set-immediate-shim@~1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" - integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= - -setimmediate@~1.0.4: - version "1.0.5" - resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -shelljs@^0.8.5: - version "0.8.5" - resolved "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz" - integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -tar-stream@^2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz" - integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== - dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - -tmp@^0.2.0: - version "0.2.1" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz" - integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== - dependencies: - rimraf "^3.0.0" - -"traverse@>=0.3.0 <0.4": - version "0.3.9" - resolved "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz" - integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk= - -tslib@^1.13.0, tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslint@^6.1.0: - version "6.1.3" - resolved "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz" - integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg== - dependencies: - "@babel/code-frame" "^7.0.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^4.0.1" - glob "^7.1.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - mkdirp "^0.5.3" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.13.0" - tsutils "^2.29.0" - -tsutils@^2.29.0: - version "2.29.0" - resolved "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz" - integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== - dependencies: - tslib "^1.8.1" - -typescript@^3.3.3333: - version "3.9.10" - resolved "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz" - integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -unzipper@^0.10.11: - version "0.10.11" - resolved "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz" - integrity sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw== - dependencies: - big-integer "^1.6.17" - binary "~0.3.0" - bluebird "~3.4.1" - buffer-indexof-polyfill "~1.0.0" - duplexer2 "~0.1.4" - fstream "^1.0.12" - graceful-fs "^4.2.2" - listenercount "~1.0.1" - readable-stream "~2.3.6" - setimmediate "~1.0.4" - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -uuid@^8.3.0: - version "8.3.2" - resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -wrappy@1: - version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -xmlchars@^2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz" - integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== - -yarn@^1.22.19: - version "1.22.19" - resolved "https://registry.npmjs.org/yarn/-/yarn-1.22.19.tgz" - integrity sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ== - -zip-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz" - integrity sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A== - dependencies: - archiver-utils "^2.1.0" - compress-commons "^4.1.0" - readable-stream "^3.6.0"