diff --git a/playlists-prod/excel.yaml b/playlists-prod/excel.yaml index dcbbf01a..a1229c67 100644 --- a/playlists-prod/excel.yaml +++ b/playlists-prod/excel.yaml @@ -177,6 +177,15 @@ 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 diff --git a/playlists/excel.yaml b/playlists/excel.yaml index 5892ba9e..7e9d49ed 100644 --- a/playlists/excel.yaml +++ b/playlists/excel.yaml @@ -177,6 +177,15 @@ 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 diff --git a/samples/excel/10-chart/chart-leader-lines.yaml b/samples/excel/10-chart/chart-leader-lines.yaml new file mode 100644 index 00000000..ad2ac18e --- /dev/null +++ b/samples/excel/10-chart/chart-leader-lines.yaml @@ -0,0 +1,185 @@ +order: 17 +id: excel-chart-leader-lines +name: Leader lines +description: Show and hide leader lines for chart labels. +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("hide-chart-leader-lines").addEventListener("click", () => tryCatch(hideChartLeaderLines)); + document.getElementById("show-chart-leader-lines").addEventListener("click", () => tryCatch(showChartLeaderLines)); + document.getElementById("change-leader-line-format").addEventListener("click", () => tryCatch(changeLeaderLineFormat)); + + const sheetName = "Sample"; + + async function addDataLabels() { + // 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(); + }); + } + + async function hideChartLeaderLines() { + // 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(); + }); + } + + async function showChartLeaderLines() { + // The following code enables 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; + + // Enable leader lines. + dataLabels.showLeaderLines = true; + + await context.sync(); + }); + } + + async function changeLeaderLineFormat() { + // 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(); + }); + } + + /** Create sample data and a line chart for the leader lines 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:C4"); + dataRange.values = sampleData; + + // Create a line chart. + const chart = sheet.charts.add(Excel.ChartType.line, dataRange); + chart.title.text = "Sales Quantity"; + + 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); + } + } + + /** Sample data for the chart. */ + const sampleData = [ + ["Type", "Product A", "Product B"], + ["Q1", 15, 20], + ["Q2", 22, 15], + ["Q3", 33, 47] + ]; + language: typescript +template: + content: |- +
+

This sample shows how to add leader lines for data labels on your charts.

+
+
+

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/snippet-extractor-metadata/excel.xlsx b/snippet-extractor-metadata/excel.xlsx index e9eadafd..ab89b746 100644 Binary files a/snippet-extractor-metadata/excel.xlsx and b/snippet-extractor-metadata/excel.xlsx differ diff --git a/snippet-extractor-output/snippets.yaml b/snippet-extractor-output/snippets.yaml index c03992d7..d7d069fb 100644 --- a/snippet-extractor-output/snippets.yaml +++ b/snippet-extractor-output/snippets.yaml @@ -16,15 +16,6 @@ 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': - >- // Link to full sample: @@ -54,6 +45,15 @@ 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#suspendScreenUpdatingUntilNextSync:member(1)': - >- // Link to full sample: @@ -1258,6 +1258,52 @@ await context.sync(); }); +'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: @@ -1365,23 +1411,78 @@ } await context.sync(); }); -'Excel.ChartSeries#delete:member(1)': +'Excel.ChartSeries#getDimensionValues:member(1)': - >- // 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-bubble-chart.yaml await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); - const seriesCollection = sheet.charts.getItemAt(0).series; - seriesCollection.load("count"); + + // 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(); - if (seriesCollection.count > 0) { - const series = seriesCollection.getItemAt(0); + // 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 - // Delete the first series. - series.delete(); + + 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(); @@ -1440,31 +1541,173 @@ 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:class': - >- // 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-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("Sample"); + 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(); - // The sample chart is of type `Excel.ChartType.bubble`. - const bubbleChart = sheet.charts.getItem("Product Chart"); + // 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 - // 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); + // 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 - // Log the information. - console.log(`Series ${category.value} - X:${xValues.value},Y:${yValues.value},Bubble:${bubbleSize.value}`); + + // 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': - >- @@ -1598,90 +1841,20 @@ 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% - ... - - 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#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"; + // 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, [ @@ -3103,39 +3276,6 @@ const settings = context.workbook.settings; settings.add("ContosoReviewXmlPartId", customXmlPart.id); - 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) => { - 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.CustomXmlPartCollection#getItem:member(1)': @@ -3163,7 +3303,7 @@ 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 @@ -3229,7 +3369,7 @@ 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 @@ -3262,34 +3402,52 @@ 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': @@ -3319,6 +3477,21 @@ wholesaleDataHierarchy.showAs = wholesaleShowAs; await context.sync(); }); +'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.DataValidation#errorAlert:member': - >- // Link to full sample: @@ -4819,6 +4992,28 @@ 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#altTextDescription:member': - >- // Link to full sample: @@ -4889,28 +5084,6 @@ 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': - >- // Link to full sample: @@ -5084,27 +5257,28 @@ 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(); + await Excel.run(async (context) => { + const pivotTable = context.workbook.worksheets.getActiveWorksheet().pivotTables.getItem("Farm Sales"); + pivotTable.layout.load("layoutType"); + 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(); - } - }); - } + // 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: @@ -5147,28 +5321,27 @@ 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(); + 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(); - // 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); - }); + // 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: @@ -5228,21 +5401,6 @@ await context.sync(); }); -'Excel.Range#autoFill:member(1)': - - >- - // 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("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#clearOrResetContents:member(1)': - >- // Link to full sample: @@ -5261,22 +5419,6 @@ range.clearOrResetContents(); await context.sync(); }); -'Excel.Range#copyFrom: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 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#control:member': - >- // Link to full sample: @@ -5297,113 +5439,46 @@ }; await context.sync(); }); -'Excel.Range#find:member(1)': - - >- - // Link to full sample: - 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 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 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.Range#findOrNullObject: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 - - - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - 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(); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-cell-control.yaml - if (foundRange.isNullObject) { - console.log("Text not found"); - } else { - console.log(foundRange.address); - } - }); -'Excel.Range#getCellProperties:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/cell-properties.yaml + // Change the value of the checkbox in B3. 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 - }); + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("B3"); - // 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}`); + range.values = [["TRUE"]]; + await context.sync(); }); -'Excel.Range#getDependents:member(1)': +'Excel.Range#valuesAsJson:member': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-dependents.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/20-data-types/data-types-formatted-number.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)': @@ -5430,143 +5505,118 @@ } await context.sync(); }); -'Excel.Range#getDirectPrecedents:member(1)': +'Excel.Range#sort:member': - >- // 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/30-events/event-column-and-row-sort.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(); + async function sortTopToBottom(criteria: string) { + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const range = sheet.getRange("A1:E5"); - console.log(`Direct precedent cells of ${range.address}:`); + // Find the column header that provides the sort criteria. + const header = range.find(criteria, {}); + header.load("columnIndex"); + await context.sync(); - // 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)': + 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)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-get-range-edge.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-merged-ranges.yaml await Excel.run(async (context) => { - // Get the selected range. - const range = context.workbook.getSelectedRange(); + // Retrieve the worksheet and the table in that worksheet. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const tableRange = sheet.getRange("B2:E6"); - // Specify the direction with the `KeyboardDirection` enum. - const direction = Excel.KeyboardDirection.down; + // Retrieve the merged range within the table and load its details. + const mergedAreas = tableRange.getMergedAreasOrNullObject(); + mergedAreas.load("address"); + mergedAreas.load("cellCount"); - // Get the active cell in the workbook. - const activeCell = context.workbook.getActiveCell(); + // Select the merged range. + const range = mergedAreas.areas.getItemAt(0); + range.select(); + await context.sync(); - // 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(); + // Print out the details of the `mergedAreas` range object. + console.log(`Address of the merged range: ${mergedAreas.address}`); + console.log(`Number of cells in the merged range: ${mergedAreas.cellCount}`); await context.sync(); }); -'Excel.Range#getIntersectionOrNullObject:member(1)': +'Excel.Range#merge:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-relationships.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-merged-ranges.yaml await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const salesTable = sheet.tables.getItem("SalesTable"); - const dataRange = salesTable.getDataBodyRange(); + // Retrieve the worksheet and the table in that worksheet. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const tableRange = sheet.getRange("B2:E6"); - // 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(); + // Create a merged range in the first row of the table. + const chartTitle = tableRange.getRow(0); + chartTitle.merge(true); - // Asian and European teams have separate contests. - const asianSalesRange = sheet.getRange("A2:E4"); - const europeanSalesRange = sheet.getRange("A5:E7"); + // Format the merged range. + chartTitle.format.horizontalAlignment = "Center"; - // 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(); + await context.sync(); + }); +'Excel.Range#group:member(1)': + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/outline.yaml - 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" - ); - } - 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" - ); - } + 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(); }); -'Excel.Range#getMergedAreasOrNullObject: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-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"); - - // Retrieve the merged range within the table and load its details. - const mergedAreas = tableRange.getMergedAreasOrNullObject(); - mergedAreas.load("address"); - mergedAreas.load("cellCount"); - - // Select the merged range. - const range = mergedAreas.areas.getItemAt(0); - range.select(); - await context.sync(); + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/outline.yaml - // Print out the details of the `mergedAreas` range object. - console.log(`Address of the merged range: ${mergedAreas.address}`); - console.log(`Number of cells in the merged range: ${mergedAreas.cellCount}`); - 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#getPivotTables:member(1)': - >- @@ -5586,38 +5636,361 @@ fullyContainedPivotTables.load("name"); await 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}`); - }); + // 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#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#getPrecedents: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. + 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}:`); + + // 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#getSpecialCells: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 usedRange = sheet.getUsedRange(); + + // Find the ranges with either text or logical (boolean) values. + const formulaRanges = usedRange.getSpecialCells("Constants", "LogicalText"); + formulaRanges.format.fill.color = "orange"; + + return context.sync(); + }); +'Excel.Range#autoFill:member(1)': + - >- + // 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("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#getCellProperties: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 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 + }); + + // 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 + + + 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.Range#copyFrom: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 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#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#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. + + // Dependent cells contain formulas that refer to other cells. + + 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}:`); + + // 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.Range#getSpillingToRange:member(1)': + - >- + // Link to full sample: + 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"); + + // Set G4 to a formula that returns a dynamic array. + const targetCell = sheet.getRange("G4"); + targetCell.formulas = [["=A4:D4"]]; + + // Get the address of the cells that the dynamic array spilled into. + const spillRange = targetCell.getSpillingToRange(); + spillRange.load("address"); + + // Fit the columns for readability. + sheet.getUsedRange().format.autofitColumns(); + await context.sync(); + + console.log(`Copying the table headers spilled into ${spillRange.address}.`); + }); +'Excel.Range#find:member(1)': + - >- + // Link to full sample: + 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 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 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.Range#findOrNullObject:member(1)': + - >- + // Link to full sample: + 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 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.Range#getPrecedents:member(1)': +'Excel.Range#getExtendedRange: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/range-get-range-edge.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(); + // Get the selected range. + const range = context.workbook.getSelectedRange(); - console.log(`All precedent cells of ${range.address}:`); + // 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(); - // 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#getRangeEdge:member(1)': @@ -5646,47 +6019,37 @@ await context.sync(); }); -'Excel.Range#getSpecialCells:member(1)': +'Excel.Range#hyperlink: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/excel/42-range/range-hyperlink.yaml await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Orders"); - const sheet = context.workbook.worksheets.getActiveWorksheet(); - const usedRange = sheet.getUsedRange(); - - // Find the ranges with either text or logical (boolean) values. - const formulaRanges = usedRange.getSpecialCells("Constants", "LogicalText"); - formulaRanges.format.fill.color = "orange"; - - return context.sync(); - }); -'Excel.Range#getSpillingToRange:member(1)': - - >- - // Link to full sample: - 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"); + let productsRange = sheet.getRange("A3:A5"); + productsRange.load("values"); - // Set G4 to a formula that returns a dynamic array. - const targetCell = sheet.getRange("G4"); - targetCell.formulas = [["=A4:D4"]]; + await context.sync(); - // Get the address of the cells that the dynamic array spilled into. - const spillRange = targetCell.getSpillingToRange(); - spillRange.load("address"); + // 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]; - // Fit the columns for readability. - sheet.getUsedRange().format.autofitColumns(); - await context.sync(); + let hyperlink = { + textToDisplay: cellText, + screenTip: "Search Bing for '" + cellText + "'", + address: "https://www.bing.com?q=" + cellText + } + cellRange.hyperlink = hyperlink; + } - console.log(`Copying the table headers spilled into ${spillRange.address}.`); + await context.sync(); }); -'Excel.Range#getUsedRange:member(1)': +'Excel.Range#getIntersectionOrNullObject:member(1)': - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-relationships.yaml @@ -5746,272 +6109,83 @@ await context.sync(); }); -'Excel.Range#getUsedRangeOrNullObject:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/used-range.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 */ - ); - - //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#group: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(); - - // 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(); - }); -'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"); - - 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.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)': +'Excel.Range#getUsedRange:member(1)': - >- // 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/42-range/range-relationships.yaml await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); + const sheet = context.workbook.worksheets.getItem("Sample"); + const salesTable = sheet.tables.getItem("SalesTable"); + const dataRange = salesTable.getDataBodyRange(); - // 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" - }; + // 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(); - 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 - } - } - }; + // Asian and European teams have separate contests. + const asianSalesRange = sheet.getRange("A2:E4"); + const europeanSalesRange = sheet.getRange("A5:E7"); - const nonApplicableProps: Excel.SettableCellProperties = { - format: { - fill: { - pattern: Excel.FillPattern.gray25 - }, - font: { - color: "Gray", - italic: true - } - } - }; + // 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); - 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 - } - } - } - }; + // Must sync before you can test the output of *OrNullObject + // method/property. + await context.sync(); - 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" + ); + } - // 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] - ]); + 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" + ); + } - sheet.getUsedRange().format.autofitColumns(); await context.sync(); }); -'Excel.Range#sort:member': +'Excel.Range#removeDuplicates: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 + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-remove-duplicates.yaml - async function sortTopToBottom(criteria: string) { - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); - const range = sheet.getRange("A1:E5"); + await Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getItem("Sample"); + const range = sheet.getRange("B2:D11"); - // Find the column header that provides the sort criteria. - const header = range.find(criteria, {}); - header.load("columnIndex"); - await context.sync(); + const deleteResult = range.removeDuplicates([0],true); + deleteResult.load(); + await context.sync(); - range.sort.apply( - [ - { - key: header.columnIndex, - sortOn: Excel.SortOn.value - } - ], - false /*matchCase*/, - true /*hasHeaders*/, - Excel.SortOrientation.rows - ); - 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#style:member': - >- // Link to full sample: @@ -6029,64 +6203,63 @@ await context.sync(); }); -'Excel.Range#ungroup:member(1)': +'Excel.Range#getUsedRangeOrNullObject: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/used-range.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 context.sync(); - }); -'Excel.Range#values:member': - - >- - // Link to full sample: - 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 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 */ + ); - // Change the value of the checkbox in B3. + //Must sync before reading value returned from *OrNullObject method/property. + await context.sync(); - await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); - const range = sheet.getRange("B3"); + 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"; + } - range.values = [["TRUE"]]; - await context.sync(); + await context.sync(); }); -'Excel.Range#valuesAsJson:member': +'Excel.Range#set:member(2)': - >- // 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, + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/90-scenarios/multiple-property-set.yaml - // 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"); + const sheet = context.workbook.worksheets.getItem("Sample"); - // 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(); + 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.RangeAreas#format:member': - >- @@ -6470,6 +6643,19 @@ 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 settings = context.workbook.settings; + settings.onSettingsChanged.add(onChangedSetting); + + await context.sync(); + console.log("Settings changed handler registered."); + }); +'Excel.SettingCollection#onSettingsChanged: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) => { const settings = context.workbook.settings; settings.onSettingsChanged.add(onChangedSetting); @@ -6499,19 +6685,6 @@ await context.sync(); }); -'Excel.SettingCollection#onSettingsChanged: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) => { - const settings = context.workbook.settings; - settings.onSettingsChanged.add(onChangedSetting); - - await context.sync(); - console.log("Settings changed handler registered."); - }); 'Excel.Shape#delete:member(1)': - >- // Link to full sample: @@ -6547,21 +6720,22 @@ shape.fill.foregroundColor = "yellow" await context.sync(); }); -'Excel.Shape#getAsImage:member(1)': +'Excel.Shape#rotation: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-create-and-delete.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 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(); - - 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': - >- @@ -6578,17 +6752,21 @@ await context.sync(); }); -'Excel.Shape#incrementLeft:member(1)': +'Excel.Shape#getAsImage: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/44-shape/shape-images.yaml await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Shapes"); - const shape = sheet.shapes.getItem("Square") - shape.incrementLeft(-25); + 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)': - >- @@ -6602,18 +6780,6 @@ shape.incrementRotation(180); 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#line:member': - >- // Link to full sample: @@ -6633,7 +6799,7 @@ await context.sync(); }); -'Excel.Shape#lockAspectRatio:member': +'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 @@ -6641,26 +6807,33 @@ 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 shape = sheet.shapes.getItem("Square") + shape.incrementLeft(-25); await context.sync(); }); -'Excel.Shape#rotation:member': +'Excel.Shape#incrementTop: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/44-shape/shape-move-and-order.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 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)': @@ -7571,30 +7744,118 @@ await context.sync(); }); -'Excel.Workbook#close:member(1)': +'Excel.Workbook#properties: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/excel/26-document/properties.yaml await Excel.run(async (context) => { - context.workbook.close(Excel.CloseBehavior.save); + 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#getActiveCell:member(1)': +'Excel.Workbook#onActivated: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/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; - let myWorkbook = context.workbook; - let activeCell = myWorkbook.getActiveCell(); - activeCell.load("address"); + // 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"); - console.log("The active cell is " + activeCell.address); + // 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)': - >- @@ -7624,19 +7885,22 @@ console.log("No active shape"); } }); -'Excel.Workbook#getSelectedRanges:member(1)': +'Excel.Workbook#getActiveCell: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/50-workbook/workbook-get-active-cell.yaml await Excel.run(async (context) => { - const selectedRanges = context.workbook.getSelectedRanges(); - selectedRanges.format.fill.color = "lightblue"; + 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: @@ -7663,132 +7927,41 @@ 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#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#properties:member': - - >- - // 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/excel/50-workbook/workbook-insert-external-worksheets.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; - + // 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(); - - console.log("Set the following document properties: title, subject, keywords, comments, category, manager, company."); }); -'Excel.Workbook#save:member(1)': +'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.save(Excel.SaveBehavior.save); + context.workbook.close(Excel.CloseBehavior.save); }); -'Excel.Workbook#styles:member': +'Excel.Workbook#save: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/excel/50-workbook/workbook-save-and-close.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."); + context.workbook.save(Excel.SaveBehavior.save); }); 'Excel.WorkbookProtection#protect:member(1)': - >- @@ -7849,48 +8022,6 @@ } 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#customProperties:member': - >- // Link to full sample: @@ -7909,124 +8040,46 @@ console.log(`${property.key}:${property.value}`); }); }); -'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#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#getRanges:member(1)': +'Excel.Worksheet#onColumnSorted: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/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(); - const specifiedRanges = sheet.getRanges("D3:D5, G3:G5"); - specifiedRanges.format.fill.color = "pink"; - - await context.sync(); - }) -'Excel.Worksheet#onChanged:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/30-events/events-worksheet.yaml + // 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(); - await Excel.run(async (context) => { - let sheet = context.workbook.worksheets.getItem("Sample"); - sheet.onChanged.add(onChange); - 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"; + } - console.log("Added a worksheet-level data-changed event handler."); + return context.sync(); + }); + }); }); -'Excel.Worksheet#onColumnSorted:member': +'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 column handler"); + console.log("Adding row 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) => { + // 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("Column sorted: " + event.address); + console.log("Row sorted: " + event.address); const sheet = context.workbook.worksheets.getActiveWorksheet(); // Clear formatting for section, then highlight the sorted area. @@ -8039,6 +8092,25 @@ }); }); }); +'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: @@ -8076,6 +8148,19 @@ ); }); } +'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: @@ -8114,49 +8199,32 @@ console.log(" Source of change event: " + source + "."); }); } -'Excel.Worksheet#onRowSorted:member': +'Excel.Worksheet#showOutlineLevels: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 + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/outline.yaml - await Excel.run(async (context) => { - console.log("Adding row handler"); + Excel.run(async (context) => { 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(); - }); - }); + // This shows the top 3 outline levels; collapsing any additional sublevels. + sheet.showOutlineLevels(3, 3); + await context.sync(); }); -'Excel.Worksheet#onSingleClicked:member': +'Excel.Worksheet#slicers: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/excel/38-pivottable/pivottable-slicer.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."); - + 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': @@ -8177,6 +8245,83 @@ 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: @@ -8189,32 +8334,60 @@ await context.sync(); }); -'Excel.Worksheet#showOutlineLevels:member(1)': +'Excel.Worksheet#getNext: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/54-worksheet/reference-worksheets-by-relative-position.yaml - Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getActiveWorksheet(); + 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]}`) - // This shows the top 3 outline levels; collapsing any additional sublevels. - sheet.showOutlineLevels(3, 3); await context.sync(); }); -'Excel.Worksheet#slicers:member': +'Excel.Worksheet#getPrevious:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/38-pivottable/pivottable-slicer.yaml + 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 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"; + 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': @@ -8318,6 +8491,45 @@ } }); } +'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: @@ -8378,45 +8590,6 @@ await context.sync(); }); -'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.WorksheetCustomPropertyCollection#add:member(1)': - >- // Link to full sample: diff --git a/view-prod/excel.json b/view-prod/excel.json index ae1ad840..38e8b662 100644 --- a/view-prod/excel.json +++ b/view-prod/excel.json @@ -18,6 +18,7 @@ "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-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", diff --git a/view/excel.json b/view/excel.json index 993906cb..6c50b9c8 100644 --- a/view/excel.json +++ b/view/excel.json @@ -18,6 +18,7 @@ "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-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",