Skip to content

Instantly share code, notes, and snippets.

@akrantz
Last active August 10, 2023 23:00
Show Gist options
  • Save akrantz/93f3da3865bd8c0583f3e3ecbc258b4a to your computer and use it in GitHub Desktop.
Save akrantz/93f3da3865bd8c0583f3e3ecbc258b4a to your computer and use it in GitHub Desktop.
Use tags to process subsets of slides.
name: Work with tags
description: Use tags to process subsets of slides.
host: POWERPOINT
api_set: {}
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));
$("#enumerate-tags").click(() => tryCatch(enumerateTags));
async function addTagToSelectedSlide() {
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");
await context.sync();
const audienceTag = 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));
});
}
function getSelectedSlideIndex() {
// 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<number>(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].index);
}
} catch (error) {
reject(console.log(error));
}
});
});
}
async function deleteSlidesByAudience() {
await PowerPoint.run(async function(context) {
const slides = context.presentation.slides;
slides.load("tags/key, tags/value");
await context.sync();
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];
if (currentTag.key === "CUSTOMER_TYPE" && currentTag.value === "Premium") {
currentSlide.delete();
}
}
}
await context.sync();
});
}
async function addMultipleSlideTags() {
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();
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)
);
}
});
}
async function addShapeTag() {
await PowerPoint.run(async function(context) {
const slide = context.presentation.slides.getItemAt(0);
const shape = slide.shapes.getItemAt(0);
shape.tags.add("MOUNTAIN", "Denali");
await context.sync();
const myShapeTag = 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));
});
}
async function addPresentationTag() {
await PowerPoint.run(async function(context) {
let presentationTags = context.presentation.tags;
presentationTags.add("COLOR", "blue");
await context.sync();
const 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));
});
}
async function deletePresentationTag() {
await PowerPoint.run(async function(context) {
let presentationTags = context.presentation.tags;
presentationTags.delete("COLOR");
await context.sync();
console.log(JSON.stringify(presentationTags));
});
}
/** 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: ${error}`);
}
}
async function loadTags(tags: PowerPoint.TagCollection) {
// for each tag in tag collection, log the tag key and value to the console
for (let index = 0; index < tags.items.length; ++index) {
const tag = tags.items[index];
tag.load();
}
}
async function logTags(context: PowerPoint.RequestContext, tags:
PowerPoint.TagCollection) {
for (let index = 0; index < tags.items.length; ++index) {
const tag = tags.items[index];
console.log(`Tag [${index}] key: ${tag.key}, Tag value: ${tag.value}`);
}
}
async function enumerateTags() {
return PowerPoint.run(async (context) => {
// load for presentation
context.presentation.load(["slides", "tags"]);
context.presentation.slides.load(["items"]);
context.presentation.tags.load(["items"]);
loadTags(context.presentation.tags);
await context.sync();
// load for each slide
for (let slideIndex = 0; slideIndex < context.presentation.slides.items.length; ++slideIndex) {
const slide = context.presentation.slides.items[slideIndex];
slide.load(["shapes", "tags"]);
slide.shapes.load("items");
slide.tags.load("items");
loadTags(slide.tags);
}
await context.sync();
// load for each shape on each slide
for (let slideIndex = 0; slideIndex < context.presentation.slides.items.length; ++slideIndex) {
const slide = context.presentation.slides.items[slideIndex];
for (let shapeIndex = 0; shapeIndex < slide.shapes.items.length; ++shapeIndex) {
const shape = slide.shapes.items[shapeIndex];
shape.load(["tags"]);
shape.tags.load("items");
}
}
await context.sync();
// log presentation tags
logTags(context, context.presentation.tags);
for (let slideIndex = 0; slideIndex < context.presentation.slides.items.length; ++slideIndex) {
const slide = context.presentation.slides.items[slideIndex];
console.log(`Slide ${slideIndex}: ${slide.tags.items.length} tags.`);
logTags(context, slide.tags);
for (let shapeIndex = 0; shapeIndex < slide.shapes.items.length; ++shapeIndex) {
const shape = slide.shapes.items[shapeIndex];
if (shape.tags.items.length > 0) {
console.log(`Shape ${shapeIndex}: ${shape.tags.items.length} tags.`);
logTags(context, shape.tags);
}
}
}
});
}
language: typescript
template:
content: "<section class=\"ms-font-m\">\n <p>These snippets show how to use tags with the presentation and its slides and shapes.</p>\n\n<section class=\"samples ms-font-m\">\n <h3>Try it out</h3>\n\n <p>1. Add several slides to the deck. Add content to each so they are visually distinct in the thumbnail pane.</p>\n\n <p>2. Select a <i>single</i> slide and press <b>Add tag</b> to tag the slide to be shown only to premium customers.</p>\n <button id=\"add-selected-slide-tag\" class=\"ms-Button\">\n <span class=\"ms-Button-label\">Add tag</span>\n </button>\n\n <p>3. Repeat step 2 for another slide.</p>\n\n <p>4. Press <b>Delete premium customer slides</b> to remove from the presentation slides that should only be shown to premium customers.</p>\n <button id=\"delete-slides-by-audience\" class=\"ms-Button\">\n <span class=\"ms-Button-label\">Delete premium customer slides</span>\n </button>\n\n <p>5. Press <b>Add slide tags</b> to add mulitiple tags to the first slide of the presentation.</p>\n <button id=\"add-slide-tags\" class=\"ms-Button\">\n <span class=\"ms-Button-label\">Add slide tags</span>\n </button>\n\n <p>6. Select the first slide and on the ribbon, navigate <b>Insert</b> > <b>Illustrations</b> > <b>Shapes</b> to add a shape to it. Press <b>Add shape tag</b>.</p>\n <button id=\"add-shape-tag\" class=\"ms-Button\">\n <span class=\"ms-Button-label\">Add shape tag</span>\n </button>\n\n <p>7. Press <b>Add presentation tag</b>.</p>\n <button id=\"add-presentation-tag\" class=\"ms-Button\">\n <span class=\"ms-Button-label\">Add presentation tag</span>\n </button>\n\n <p>8. Press <b>Delete presentation tag</b>.</p>\n <button id=\"delete-presentation-tag\" class=\"ms-Button\">\n <span class=\"ms-Button-label\">Delete presentation tag</span>\n </button>\n\n\t <p>8. Press <b>Enumerate tags</b>.</p>\n\t <button id=\"enumerate-tags\" class=\"ms-Button\">\n\t <span class=\"ms-Button-label\">Enumerate tags</span>\n\t </button></section>"
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
[email protected]/dist/css/fabric.min.css
[email protected]/dist/css/fabric.components.min.css
[email protected]/client/core.min.js
@types/core-js
[email protected]
@types/[email protected]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment