order: 1 id: excel-manage-sensitivity-labels name: Manage sensitivity labels description: Shows how to inspect the sensitivity label catalog and get or set the sensitivity label of an Excel workbook. host: EXCEL api_set: ExcelApi: preview script: content: | document.getElementById("get-catalog-status").addEventListener("click", () => tryCatch(getCatalogStatus)); document.getElementById("get-available-labels").addEventListener("click", () => tryCatch(getAvailableLabels)); document.getElementById("get-catalog-attributes").addEventListener("click", () => tryCatch(getCatalogAttributes)); document.getElementById("get-workbook-label").addEventListener("click", () => tryCatch(getWorkbookLabel)); document.getElementById("set-workbook-label").addEventListener("click", () => tryCatch(setWorkbookLabel)); document.getElementById("set-workbook-label-with-attributes").addEventListener("click", () => tryCatch(setWorkbookLabelWithAttributes)); async function getCatalogStatus() { // Check whether sensitivity labeling is available for the current user. await Excel.run(async (context) => { const labelCatalog: Excel.SensitivityLabelsCatalog = context.sensitivityLabelsCatalog; if (!labelCatalog) { console.warn("The sensitivity label catalog isn't available in this version of Excel."); return; } labelCatalog.load("getLabelingCapability"); await context.sync(); switch (labelCatalog.getLabelingCapability) { case Excel.LabelingCapability.labelingEnabled: console.log("Sensitivity labeling is enabled."); break; case Excel.LabelingCapability.labelingDisabled: console.log("Sensitivity labeling is disabled."); break; case Excel.LabelingCapability.labelingPolicyNotFound: console.log("No sensitivity labeling policy was found."); break; case Excel.LabelingCapability.noLicense: console.log("The current user doesn't have a valid sensitivity labeling license."); break; default: console.log(`Unknown labeling capability: ${labelCatalog.getLabelingCapability}`); break; } }); } async function getAvailableLabels() { // Get the published labels and sublabels available to the current user. await Excel.run(async (context) => { const labelSelect = document.getElementById("label-id") as HTMLSelectElement; labelSelect.options.length = 0; const placeholder = document.createElement("option"); placeholder.textContent = "Select a label"; placeholder.value = ""; labelSelect.add(placeholder); const labelCatalog: Excel.SensitivityLabelsCatalog = context.sensitivityLabelsCatalog; if (!labelCatalog) { console.warn("The sensitivity label catalog isn't available in this version of Excel."); return; } const availableLabels: Excel.SensitivityLabelDetailsCollection = labelCatalog.getLabels(); availableLabels.load( "items/color,items/id,items/isAbacAttributesRequired,items/isAbacEnabled,items/isEnabled," + "items/name,items/order,items/protectionType,items/siteId,items/tooltip," + "items/children/items/id,items/children/items/name,items/children/items/isEnabled" ); await context.sync(); if (availableLabels.items.length === 0) { console.log("No sensitivity labels are available for the current user."); return; } console.log("Available sensitivity labels:"); availableLabels.items.forEach((labelDetails: Excel.SensitivityLabelDetails) => { const childLabels = labelDetails.children && labelDetails.children.items.length ? labelDetails.children.items .map((childLabel: Excel.SensitivityLabelDetails) => `${childLabel.name} (${childLabel.id})`) .join(", ") : "None"; console.log( `\n${labelDetails.name}\n` + ` ID: ${labelDetails.id}\n` + ` Site ID: ${labelDetails.siteId}\n` + ` Tooltip: ${labelDetails.tooltip}\n` + ` Color: ${labelDetails.color}\n` + ` Enabled: ${labelDetails.isEnabled ? "Yes" : "No"}\n` + ` Display order: ${labelDetails.order}\n` + ` ABAC enabled: ${labelDetails.isAbacEnabled ? "Yes" : "No"}\n` + ` ABAC attributes required: ${labelDetails.isAbacAttributesRequired ? "Yes" : "No"}\n` + ` Sublabels: ${childLabels}\n` + ` Protection type: ${labelDetails.protectionType}` ); }); addLabelOptions(availableLabels); }); } async function getCatalogAttributes() { // Get available ABAC attributes and describe the kind of value each attribute accepts. const container = document.getElementById("abac-attributes"); while (container.firstChild) { container.removeChild(container.firstChild); } await Excel.run(async (context) => { const labelCatalog: Excel.SensitivityLabelsCatalog = context.sensitivityLabelsCatalog; if (!labelCatalog) { console.warn("The sensitivity label catalog isn't available in this version of Excel."); return; } labelCatalog.load("getLabelingCapabilities"); await context.sync(); const capabilities: Excel.LabelingCapability[] = labelCatalog.getLabelingCapabilities; if (capabilities.indexOf(Excel.LabelingCapability.attributeBasedAccessControlEnabled) === -1) { console.warn("ABAC attributes aren't enabled or available for the current user."); return; } const catalogAttributes: OfficeExtension.ClientResult = labelCatalog.getAttributes(); await context.sync(); if (catalogAttributes.value.length === 0) { console.log("No ABAC attributes are available in the sensitivity label catalog."); return; } console.log("Available ABAC attributes:"); catalogAttributes.value.forEach((attribute: Excel.SensitivityLabelAbacAttribute) => { let dataTypeDescription: string; switch (attribute.dataType) { case Excel.SensitivityLabelAbacAttributeDataType.booleanValue: dataTypeDescription = "Boolean"; break; case Excel.SensitivityLabelAbacAttributeDataType.dateValue: dataTypeDescription = "Date"; break; case Excel.SensitivityLabelAbacAttributeDataType.numberValue: dataTypeDescription = "Number"; break; case Excel.SensitivityLabelAbacAttributeDataType.stringValue: dataTypeDescription = "String"; break; case Excel.SensitivityLabelAbacAttributeDataType.unknown: dataTypeDescription = "Unknown"; break; default: dataTypeDescription = `Unrecognized (${attribute.dataType})`; break; } console.log(`ABAC attribute: ${attribute.displayName}`, { dataType: attribute.dataType, dataTypeDescription, displayOrder: attribute.displayOrder, isActive: attribute.isActive, isMultiValued: attribute.isMultiValued, values: attribute.values.map((attributeValue: Excel.SensitivityLabelAbacAttributeValue) => ({ displayName: attributeValue.displayName, displayOrder: attributeValue.displayOrder, id: attributeValue.id, isActive: attributeValue.isActive })) }); }); addAttributeOptions(catalogAttributes.value); }); } function addAttributeOptions(attributes: Excel.SensitivityLabelAbacAttribute[]) { const container = document.getElementById("abac-attributes"); attributes.filter((attribute) => attribute.isActive) .sort((first, second) => first.displayOrder - second.displayOrder) .forEach((attribute, index) => { const group = document.createElement("div"); const label = document.createElement("label"); label.htmlFor = `abac-attribute-${index}`; label.textContent = `${attribute.displayName} (${attribute.isMultiValued ? "select one or more" : "select one"})`; const select = document.createElement("select"); select.id = label.htmlFor; select.name = attribute.displayName; select.multiple = attribute.isMultiValued; if (!attribute.isMultiValued) { const placeholder = document.createElement("option"); placeholder.textContent = "No value selected"; placeholder.value = ""; select.add(placeholder); } attribute.values.filter((value) => value.isActive) .sort((first, second) => first.displayOrder - second.displayOrder) .forEach((value) => { const option = document.createElement("option"); option.textContent = value.displayName; option.value = value.id; select.add(option); }); group.appendChild(label); group.appendChild(select); container.appendChild(group); }); } function addLabelOptions(availableLabels: Excel.SensitivityLabelDetailsCollection) { const labelSelect = document.getElementById("label-id") as HTMLSelectElement; availableLabels.items.forEach((labelDetails: Excel.SensitivityLabelDetails) => { // Parent labels can't be applied directly, so group their sublabels. if (labelDetails.children && labelDetails.children.items.length > 0) { const labelGroup = document.createElement("optgroup"); labelGroup.label = labelDetails.name; labelDetails.children.items.forEach((childLabel: Excel.SensitivityLabelDetails) => { const childOption = document.createElement("option"); childOption.textContent = childLabel.name; childOption.value = childLabel.id; childOption.disabled = !childLabel.isEnabled; labelGroup.appendChild(childOption); }); labelSelect.add(labelGroup); } else { const labelOption = document.createElement("option"); labelOption.textContent = labelDetails.name; labelOption.value = labelDetails.id; labelOption.disabled = !labelDetails.isEnabled; labelSelect.add(labelOption); } }); } async function getWorkbookLabel() { // Get the sensitivity label currently applied to the workbook. await Excel.run(async (context) => { const workbook: Excel.Workbook = context.workbook; const workbookLabel: Excel.SensitivityLabel = workbook.sensitivityLabel; const currentLabel: Excel.SensitivityLabelDetails = workbookLabel.getCurrentOrNullObject(); currentLabel.load( "color,id,isAbacAttributesRequired,isAbacEnabled,isEnabled,name,order,protectionType,siteId,tooltip" ); await context.sync(); if (currentLabel.isNullObject) { console.log("The workbook doesn't have a sensitivity label."); return; } // Get ABAC values only when enabled for the label. let abacAttributeValues: Excel.SensitivityLabelAbacAttributeValue[] = []; if (currentLabel.isAbacEnabled) { currentLabel.load("abacAttributeValues"); await context.sync(); abacAttributeValues = currentLabel.abacAttributeValues; } const attributeValues = abacAttributeValues.length ? abacAttributeValues .map((attributeValue: Excel.SensitivityLabelAbacAttributeValue) => `${attributeValue.displayName} (ID: ${attributeValue.id}, ` + `order: ${attributeValue.displayOrder}, active: ${attributeValue.isActive ? "Yes" : "No"})`) .join(", ") : "None"; let protectionDescription: string; switch (currentLabel.protectionType) { case Excel.SensitivityLabelProtectionType.adminDefined: protectionDescription = "Defined by an administrator"; break; case Excel.SensitivityLabelProtectionType.userDefined: protectionDescription = "Defined by the user"; break; case Excel.SensitivityLabelProtectionType.noProtection: protectionDescription = "No protection"; break; default: protectionDescription = `Unknown (${currentLabel.protectionType})`; break; } console.log( `Current workbook sensitivity label:\n\n${currentLabel.name}\n` + ` ID: ${currentLabel.id}\n` + ` Site ID: ${currentLabel.siteId}\n` + ` Tooltip: ${currentLabel.tooltip}\n` + ` Color: ${currentLabel.color}\n` + ` Enabled: ${currentLabel.isEnabled ? "Yes" : "No"}\n` + ` Display order: ${currentLabel.order}\n` + ` ABAC enabled: ${currentLabel.isAbacEnabled ? "Yes" : "No"}\n` + ` ABAC attributes required: ${currentLabel.isAbacAttributesRequired ? "Yes" : "No"}\n` + ` ABAC attribute values: ${attributeValues}\n` + ` Protection type: ${protectionDescription}` ); }); } async function setWorkbookLabel() { // Apply the selected sensitivity label to the entire workbook. await Excel.run(async (context) => { const labelId = (document.getElementById("label-id") as HTMLSelectElement).value; if (!labelId) { console.warn("Get available labels and select a label first."); return; } const workbook: Excel.Workbook = context.workbook; const workbookLabel: Excel.SensitivityLabel = workbook.sensitivityLabel; const updateResult: OfficeExtension.ClientResult = workbookLabel.tryToUpdate(labelId); await context.sync(); if (updateResult.value.status === Excel.SensitivityLabelUpdateStatus.success) { console.log("Applied the sensitivity label to the workbook."); } else { console.error(`The sensitivity label wasn't applied. Status: ${updateResult.value.status}`); } }); } async function setWorkbookLabelWithAttributes() { // Apply the selected sensitivity label with the chosen ABAC attribute values. await Excel.run(async (context) => { const labelId = (document.getElementById("label-id") as HTMLSelectElement).value; if (!labelId) { console.warn("Get available labels and select a label first."); return; } const attributeControls = document.getElementById("abac-attributes") .querySelectorAll("select"); if (attributeControls.length === 0) { console.warn("Get catalog attributes and select attribute values first."); return; } const labelCatalog: Excel.SensitivityLabelsCatalog = context.sensitivityLabelsCatalog; if (!labelCatalog) { console.warn("The sensitivity label catalog isn't available in this version of Excel."); return; } labelCatalog.load("getLabelingCapabilities"); await context.sync(); if (labelCatalog.getLabelingCapabilities.indexOf(Excel.LabelingCapability.attributeBasedAccessControlEnabled) === -1) { console.warn("ABAC attributes aren't enabled or available for the current user."); return; } // Refresh the catalog to validate selections against the current policy. const catalogAttributes: OfficeExtension.ClientResult = labelCatalog.getAttributes(); await context.sync(); const selectedAttributes: Excel.SensitivityLabelAbacAttribute[] = []; for (const select of Array.from(attributeControls)) { const selectedIds = Array.from(select.selectedOptions) .map((option) => option.value).filter((id) => id !== ""); if (selectedIds.length === 0) { continue; } const attribute: Excel.SensitivityLabelAbacAttribute | undefined = catalogAttributes.value.find((attribute) => attribute.displayName === select.name); if (!attribute || !attribute.isActive || (!attribute.isMultiValued && selectedIds.length > 1)) { console.warn("The attribute selections are no longer valid. Get catalog attributes and select values again."); return; } const selectedValues: Excel.SensitivityLabelAbacAttributeValue[] = attribute.values.filter((value) => value.isActive && selectedIds.indexOf(value.id) !== -1); if (selectedValues.length !== selectedIds.length) { console.warn("The attribute selections are no longer valid. Get catalog attributes and select values again."); return; } const selectedAttribute: Excel.SensitivityLabelAbacAttribute = { ...attribute, values: selectedValues }; selectedAttributes.push(selectedAttribute); } if (selectedAttributes.length === 0) { console.warn("Select at least one ABAC attribute value first."); return; } const options: Excel.SensitivityLabelTryUpdateOptions = { abacAttributes: selectedAttributes }; const workbook: Excel.Workbook = context.workbook; const workbookLabel: Excel.SensitivityLabel = workbook.sensitivityLabel; const updateResult: OfficeExtension.ClientResult = workbookLabel.tryToUpdate(labelId, options); await context.sync(); if (updateResult.value.status === Excel.SensitivityLabelUpdateStatus.success) { console.log("Applied the sensitivity label and ABAC attributes to the workbook."); } else { console.error(`The sensitivity label wasn't applied. Status: ${updateResult.value.status}`); } }); } // Default helper for invoking an action and handling errors. async function tryCatch(callback) { try { await callback(); } catch (error) { // In a production add-in, notify the user through your add-in's UI. console.error(error); } } language: typescript template: content: |-

This sample uses preview APIs to inspect your organization's sensitivity labels and apply a label to the current workbook.

Prerequisites: Use a test workbook and sign in to Excel with a work or school account that has sensitivity labeling enabled and at least one label published to it.

These preview APIs might not be available in every version of Excel.

Attribute-based access control (ABAC) attributes must be enabled and available for the current user to retrieve catalog attributes.

Labels and ABAC attributes come from your organization's policy and can't be created by this sample.

Try it out

Setting a label affects the entire workbook and may change protection or access. Check the console for the result, then use Get workbook label to verify the label and its ABAC values.

For labels that use ABAC attributes, Get catalog attributes displays active attributes and their active values. Choose values, then use Set workbook label with attributes instead of Set workbook label. For a multi-select list, hold Ctrl on Windows or Command on Mac to select multiple values.

language: html style: content: |- body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 14px; line-height: 1.5; padding: 10px; } section { margin-bottom: 20px; } h3 { margin-top: 0; margin-bottom: 10px; font-size: 16px; } p { margin: 0 0 10px 0; } button { background-color: #f0f0f0; color: #333333; border: 1px solid #8a8a8a; padding: 8px 16px; font-size: 14px; cursor: pointer; border-radius: 2px; margin-left: 20px; margin-bottom: 5px; min-width: 80px; display: block; } button:hover { background-color: #e0e0e0; } button:active { background-color: #d0d0d0; } label, select { display: block; margin-left: 20px; } select { box-sizing: border-box; margin-bottom: 8px; padding: 6px; width: calc(100% - 40px); } language: css libraries: |- https://officeapis.public.onecdn.static.microsoft/beta/office.js https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/master/types/office-js-preview/index.d.ts