From e0fdfcacf1dcc20bfc73d324d4dd33014bca04a6 Mon Sep 17 00:00:00 2001 From: Alison McKay Date: Thu, 17 Jul 2025 19:54:56 -0700 Subject: [PATCH 1/8] [Excel] (Chart) Add leader lines snippet --- .../excel/10-chart/chart-leader-lines.yaml | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 samples/excel/10-chart/chart-leader-lines.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..1d85a7ba --- /dev/null +++ b/samples/excel/10-chart/chart-leader-lines.yaml @@ -0,0 +1,187 @@ +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-labels").addEventListener("click", () => tryCatch(addDataLabels)); + document.getElementById("enable-leader-lines").addEventListener("click", () => tryCatch(enableLeaderLines)); + document.getElementById("disable-leader-lines").addEventListener("click", () => tryCatch(disableLeaderLines)); + document.getElementById("change-leader-line-format").addEventListener("click", () => tryCatch(changeLeaderLineFormat)); + + const sheetName = "Sample"; + + /** Add data labels to the chart and position them to demonstrate leader lines. */ + async function addDataLabels() { + 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. + 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. + series.points.items[1].dataLabel.top = series.points.items[1].dataLabel.top - 50; + series.points.items[2].dataLabel.top = series.points.items[2].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(); + }); + } + + /** Enable leader lines for chart data labels. */ + async function enableLeaderLines() { + 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; + + // Load the current leader lines setting. + dataLabels.load("showLeaderLines"); + await context.sync(); + + // Enable leader lines. + dataLabels.showLeaderLines = true; + + await context.sync(); + }); + } + + /** Disable leader lines for chart data labels. */ + async function disableLeaderLines() { + 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(); + }); + } + + /** Change the format of leader lines including color, weight, and line style. */ + async function changeLeaderLineFormat() { + 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 From 2e3fd85d62ce2ad0a77a604a32b305e17d7311ce Mon Sep 17 00:00:00 2001 From: Alison McKay Date: Fri, 18 Jul 2025 11:37:09 -0700 Subject: [PATCH 2/8] Fix minor bug --- .gitignore | 4 +++- samples/excel/10-chart/chart-leader-lines.yaml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index a133b939..2d2f29ea 100644 --- a/.gitignore +++ b/.gitignore @@ -64,4 +64,6 @@ npm-debug.log* ~$* # Used to ignore "playlists", but having those checked-in for diffing purposes is very useful, so undoing the ignore: -# playlists/** \ No newline at end of file +# playlists/** + +package-lock.json \ No newline at end of file diff --git a/samples/excel/10-chart/chart-leader-lines.yaml b/samples/excel/10-chart/chart-leader-lines.yaml index 1d85a7ba..6baedd74 100644 --- a/samples/excel/10-chart/chart-leader-lines.yaml +++ b/samples/excel/10-chart/chart-leader-lines.yaml @@ -8,7 +8,7 @@ api_set: script: content: |- document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); - document.getElementById("add-labels").addEventListener("click", () => tryCatch(addDataLabels)); + document.getElementById("add-data-labels").addEventListener("click", () => tryCatch(addDataLabels)); document.getElementById("enable-leader-lines").addEventListener("click", () => tryCatch(enableLeaderLines)); document.getElementById("disable-leader-lines").addEventListener("click", () => tryCatch(disableLeaderLines)); document.getElementById("change-leader-line-format").addEventListener("click", () => tryCatch(changeLeaderLineFormat)); From 477891c2f564e2d542f3fe9b50d2004e4450cb26 Mon Sep 17 00:00:00 2001 From: Alison McKay Date: Mon, 11 Aug 2025 16:16:42 -0700 Subject: [PATCH 3/8] Adjust comments --- .../excel/10-chart/chart-leader-lines.yaml | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/samples/excel/10-chart/chart-leader-lines.yaml b/samples/excel/10-chart/chart-leader-lines.yaml index 6baedd74..5cf58ad4 100644 --- a/samples/excel/10-chart/chart-leader-lines.yaml +++ b/samples/excel/10-chart/chart-leader-lines.yaml @@ -9,20 +9,20 @@ script: content: |- document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); document.getElementById("add-data-labels").addEventListener("click", () => tryCatch(addDataLabels)); - document.getElementById("enable-leader-lines").addEventListener("click", () => tryCatch(enableLeaderLines)); document.getElementById("disable-leader-lines").addEventListener("click", () => tryCatch(disableLeaderLines)); + document.getElementById("enable-leader-lines").addEventListener("click", () => tryCatch(enableLeaderLines)); document.getElementById("change-leader-line-format").addEventListener("click", () => tryCatch(changeLeaderLineFormat)); const sheetName = "Sample"; - /** Add data labels to the chart and position them to demonstrate leader lines. */ async function addDataLabels() { + // This funtion 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. + // Enable data labels for the series. Leader lines are enabled by default. series.hasDataLabels = true; series.points.load("items"); await context.sync(); @@ -44,42 +44,43 @@ script: }); } - /** Enable leader lines for chart data labels. */ - async function enableLeaderLines() { + async function disableLeaderLines() { + // This function 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; - - // Load the current leader lines setting. - dataLabels.load("showLeaderLines"); - await context.sync(); - // Enable leader lines. - dataLabels.showLeaderLines = true; - + // Disable leader lines. + dataLabels.showLeaderLines = false; + await context.sync(); }); } - /** Disable leader lines for chart data labels. */ - async function disableLeaderLines() { + async function enableLeaderLines() { + // This function 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; + + // Load the current leader lines setting. + dataLabels.load("showLeaderLines"); + await context.sync(); - // Disable leader lines. - dataLabels.showLeaderLines = false; - + // Enable leader lines. + dataLabels.showLeaderLines = true; + await context.sync(); }); } - /** Change the format of leader lines including color, weight, and line style. */ async function changeLeaderLineFormat() { + // This function 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); @@ -151,13 +152,13 @@ template:
-
-
From 79acde424586576abab0cccf4a2de124b6b42c09 Mon Sep 17 00:00:00 2001 From: Alison McKay Date: Mon, 11 Aug 2025 16:18:34 -0700 Subject: [PATCH 4/8] Run yarn start --- playlists-prod/excel.yaml | 9 +++++++++ playlists/excel.yaml | 9 +++++++++ view-prod/excel.json | 1 + view/excel.json | 1 + 4 files changed, 20 insertions(+) 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/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", From 56ec8d3d07e6588429cec526721b76cb04865f1e Mon Sep 17 00:00:00 2001 From: Alison McKay Date: Mon, 11 Aug 2025 16:32:37 -0700 Subject: [PATCH 5/8] Update excel.xlsx and run yarn start --- .../excel/10-chart/chart-leader-lines.yaml | 2 +- snippet-extractor-metadata/excel.xlsx | Bin 29172 -> 29298 bytes snippet-extractor-output/snippets.yaml | 169 ++++++++++++++++++ 3 files changed, 170 insertions(+), 1 deletion(-) diff --git a/samples/excel/10-chart/chart-leader-lines.yaml b/samples/excel/10-chart/chart-leader-lines.yaml index 5cf58ad4..5b771904 100644 --- a/samples/excel/10-chart/chart-leader-lines.yaml +++ b/samples/excel/10-chart/chart-leader-lines.yaml @@ -16,7 +16,7 @@ script: const sheetName = "Sample"; async function addDataLabels() { - // This funtion adds data labels to the chart and positions them to demonstrate leader lines. + // This function 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); diff --git a/snippet-extractor-metadata/excel.xlsx b/snippet-extractor-metadata/excel.xlsx index e9eadafdcf4b2966270f94f341fb736dde32b4b1..803e7052d5912061458796d566cc89501e3dc1f9 100644 GIT binary patch delta 19135 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 diff --git a/snippet-extractor-output/snippets.yaml b/snippet-extractor-output/snippets.yaml index c03992d7..58544a17 100644 --- a/snippet-extractor-output/snippets.yaml +++ b/snippet-extractor-output/snippets.yaml @@ -1258,6 +1258,54 @@ 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 + + + // This function 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 + + + // This function 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: @@ -1363,6 +1411,40 @@ dataLabel.text = dataLabelInfo[i].news; dataLabel.set(labelProperties[i]); } + await context.sync(); + }); +'Excel.ChartSeries:class': + - >- + // Link to full sample: + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml + + + // This function 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. + series.points.items[1].dataLabel.top = series.points.items[1].dataLabel.top - 50; + series.points.items[2].dataLabel.top = series.points.items[2].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#delete:member(1)': @@ -1466,6 +1548,40 @@ // Log the information. console.log(`Series ${category.value} - X:${xValues.value},Y:${yValues.value},Bubble:${bubbleSize.value}`); }); +'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 + + + // This function 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. + series.points.items[1].dataLabel.top = series.points.items[1].dataLabel.top - 50; + series.points.items[2].dataLabel.top = series.points.items[2].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#markerBackgroundColor:member': - >- // Link to full sample: @@ -1598,6 +1714,40 @@ 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 + + + // This function 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. + series.points.items[1].dataLabel.top = series.points.items[1].dataLabel.top - 50; + series.points.items[2].dataLabel.top = series.points.items[2].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#setBubbleSizes:member(1)': - >- // Link to full sample: @@ -1666,6 +1816,25 @@ newSeries.setValues(rangeSelection); newSeries.setXAxisValues(xRangeSelection); + 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 + + + // This function 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.ChartSeriesBy:enum': From 8b47a379291bfe812742bba47b3aebdb9b2c8206 Mon Sep 17 00:00:00 2001 From: Alison McKay Date: Mon, 11 Aug 2025 16:37:15 -0700 Subject: [PATCH 6/8] Incorporate copilot feedback --- samples/excel/10-chart/chart-leader-lines.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/samples/excel/10-chart/chart-leader-lines.yaml b/samples/excel/10-chart/chart-leader-lines.yaml index 5b771904..205e9033 100644 --- a/samples/excel/10-chart/chart-leader-lines.yaml +++ b/samples/excel/10-chart/chart-leader-lines.yaml @@ -66,10 +66,6 @@ script: const chart = sheet.charts.getItemAt(0); const series = chart.series.getItemAt(0); const dataLabels = series.dataLabels; - - // Load the current leader lines setting. - dataLabels.load("showLeaderLines"); - await context.sync(); // Enable leader lines. dataLabels.showLeaderLines = true; From 0a5be6cddbc6a5fe307819c164511b515c08a410 Mon Sep 17 00:00:00 2001 From: Alison McKay Date: Tue, 12 Aug 2025 14:18:37 -0700 Subject: [PATCH 7/8] Code review feedback --- .../excel/10-chart/chart-leader-lines.yaml | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/samples/excel/10-chart/chart-leader-lines.yaml b/samples/excel/10-chart/chart-leader-lines.yaml index 205e9033..ad2ac18e 100644 --- a/samples/excel/10-chart/chart-leader-lines.yaml +++ b/samples/excel/10-chart/chart-leader-lines.yaml @@ -9,14 +9,14 @@ script: content: |- document.getElementById("setup").addEventListener("click", () => tryCatch(setup)); document.getElementById("add-data-labels").addEventListener("click", () => tryCatch(addDataLabels)); - document.getElementById("disable-leader-lines").addEventListener("click", () => tryCatch(disableLeaderLines)); - document.getElementById("enable-leader-lines").addEventListener("click", () => tryCatch(enableLeaderLines)); + 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() { - // This function adds data labels to the chart and positions them to demonstrate leader lines. + // 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); @@ -32,8 +32,10 @@ script: await context.sync(); // Move some data labels to create distance from their chart points. - series.points.items[1].dataLabel.top = series.points.items[1].dataLabel.top - 50; - series.points.items[2].dataLabel.top = series.points.items[2].dataLabel.top + 50; + 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; @@ -44,8 +46,8 @@ script: }); } - async function disableLeaderLines() { - // This function disables leader lines for chart data labels. + 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); @@ -59,8 +61,8 @@ script: }); } - async function enableLeaderLines() { - // This function enables leader lines for chart data labels. + 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); @@ -75,8 +77,7 @@ script: } async function changeLeaderLineFormat() { - // This function changes the format of leader lines. - // It adjusts color, weight, and line style. + // 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); @@ -148,12 +149,12 @@ template:
-
-
From 73fb7495da7c8e33ebbdafdf4422a37cd2ccc964 Mon Sep 17 00:00:00 2001 From: Alison McKay Date: Tue, 12 Aug 2025 14:22:51 -0700 Subject: [PATCH 8/8] run yarn start --- snippet-extractor-metadata/excel.xlsx | Bin 29298 -> 29305 bytes snippet-extractor-output/snippets.yaml | 2470 ++++++++++++------------ 2 files changed, 1237 insertions(+), 1233 deletions(-) diff --git a/snippet-extractor-metadata/excel.xlsx b/snippet-extractor-metadata/excel.xlsx index 803e7052d5912061458796d566cc89501e3dc1f9..ab89b7460a3921f4fdf8d7f326b0467ec25cc7ac 100644 GIT binary patch delta 13770 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∾wp>sTUITkzSv+6ZjZcVRC`S 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 k;EarfMEL(%$t&2frxYLuhVfn!UNNJ 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 diff --git a/snippet-extractor-output/snippets.yaml b/snippet-extractor-output/snippets.yaml index 58544a17..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: @@ -1264,9 +1264,8 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml - // This function changes the format of leader lines. - - // It adjusts color, weight, and line style. + // 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); @@ -1288,9 +1287,8 @@ https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml - // This function changes the format of leader lines. - - // It adjusts color, weight, and line style. + // 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); @@ -1413,57 +1411,78 @@ } await context.sync(); }); -'Excel.ChartSeries:class': +'Excel.ChartSeries#getDimensionValues:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml - + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-bubble-chart.yaml - // This function 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(); + const sheet = context.workbook.worksheets.getItem("Sample"); + + // The sample chart is of type `Excel.ChartType.bubble`. + const bubbleChart = sheet.charts.getItem("Product Chart"); + + // Get the first series in the chart. + const firstSeries = bubbleChart.series.getItemAt(0); + + // Get the values for the dimensions we're interested in. + const bubbleSize = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.bubbleSizes); + const xValues = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.xvalues); + const yValues = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.yvalues); + const category = firstSeries.getDimensionValues(Excel.ChartSeriesDimension.categories); - // Move some data labels to create distance from their chart points. - series.points.items[1].dataLabel.top = series.points.items[1].dataLabel.top - 50; - series.points.items[2].dataLabel.top = series.points.items[2].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(); + + // Log the information. + console.log(`Series ${category.value} - X:${xValues.value},Y:${yValues.value},Bubble:${bubbleSize.value}`); }); -'Excel.ChartSeries#delete:member(1)': +'Excel.ChartSeries#setBubbleSizes: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) => { + /* + 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 seriesCollection = sheet.charts.getItemAt(0).series; - seriesCollection.load("count"); + 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(); - if (seriesCollection.count > 0) { - const series = seriesCollection.getItemAt(0); + // 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)); - // Delete the first series. - series.delete(); + // Show the product name and market share percentage. + newSeries.dataLabels.showSeriesName = true; + newSeries.dataLabels.showBubbleSize = true; + newSeries.dataLabels.showValue = false; } await context.sync(); @@ -1522,39 +1541,85 @@ 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(); - // Log the information. - console.log(`Series ${category.value} - X:${xValues.value},Y:${yValues.value},Bubble:${bubbleSize.value}`); + // Move some data labels to create distance from their chart points. + const point1 = series.points.items[1]; + const point2 = series.points.items[2]; + point1.dataLabel.top -= 50; + point2.dataLabel.top += 50; + + // Format the data labels. + series.dataLabels.geometricShapeType = Excel.GeometricShapeType.rectangle; + series.dataLabels.showCategoryName = true; + series.dataLabels.format.border.weight = 1; + + await context.sync(); }); -'Excel.ChartSeries#hasDataLabels:member': +'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 - // This function adds data labels to the chart and positions them to + // The following code adds data labels to the chart and positions them to demonstrate leader lines. await Excel.run(async (context) => { @@ -1572,14 +1637,76 @@ await context.sync(); // Move some data labels to create distance from their chart points. - series.points.items[1].dataLabel.top = series.points.items[1].dataLabel.top - 50; - series.points.items[2].dataLabel.top = series.points.items[2].dataLabel.top + 50; + 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': @@ -1714,143 +1841,20 @@ await context.sync(); }); -'Excel.ChartSeries#points:member': +'Excel.ChartSeriesBy:enum': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml - + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-data-source.yaml - // This function 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(); + // Create a new worksheet called "Sample" and activate it. + context.workbook.worksheets.getItemOrNullObject("Sample").delete(); + const sheet = context.workbook.worksheets.add("Sample"); - // 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. - series.points.items[1].dataLabel.top = series.points.items[1].dataLabel.top - 50; - series.points.items[2].dataLabel.top = series.points.items[2].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#setBubbleSizes:member(1)': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-bubble-chart.yaml - - - await Excel.run(async (context) => { - /* - The table is expected to look like this: - Product, Inventory, Price, Current Market Share - Calamansi, 2000, $2.45, 10% - ... - - We want each bubble to represent a single row. - */ - - // Get the worksheet and table data. - const sheet = context.workbook.worksheets.getItem("Sample"); - const table = sheet.tables.getItem("Sales"); - const dataRange = table.getDataBodyRange(); - - // Get the table data without the row names. - const valueRange = dataRange.getOffsetRange(0, 1).getResizedRange(0, -1); - - // Create the chart. - const bubbleChart = sheet.charts.add(Excel.ChartType.bubble, valueRange); - bubbleChart.name = "Product Chart"; - - // Remove the default series, since we want a unique series for each row. - bubbleChart.series.getItemAt(0).delete(); - - // Load the data necessary to make a chart series. - dataRange.load(["rowCount", "values"]); - await context.sync(); - - // For each row, create a chart series (a bubble). - for (let i = 0; i < dataRange.rowCount; i++) { - const newSeries = bubbleChart.series.add(dataRange.values[i][0], i); - newSeries.setXAxisValues(dataRange.getCell(i, 1)); - newSeries.setValues(dataRange.getCell(i, 2)); - newSeries.setBubbleSizes(dataRange.getCell(i, 3)); - - // Show the product name and market share percentage. - newSeries.dataLabels.showSeriesName = true; - newSeries.dataLabels.showBubbleSize = true; - newSeries.dataLabels.showValue = false; - } - - await context.sync(); - }); -'Excel.ChartSeries#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#showLeaderLines:member': - - >- - // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/10-chart/chart-leader-lines.yaml - - - // This function 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.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 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, [ @@ -3272,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)': @@ -3332,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 @@ -3398,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 @@ -3431,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': @@ -3488,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: @@ -4988,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: @@ -5058,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: @@ -5253,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: @@ -5316,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: @@ -5397,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: @@ -5430,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: @@ -5466,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)': @@ -5599,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(); - - // 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(); + // Retrieve the worksheet and the table in that worksheet. + const sheet = context.workbook.worksheets.getActiveWorksheet(); + const tableRange = sheet.getRange("B2:E6"); - // Asian and European teams have separate contests. - const asianSalesRange = sheet.getRange("A2:E4"); - const europeanSalesRange = sheet.getRange("A5:E7"); + // Create a merged range in the first row of the table. + const chartTitle = tableRange.getRow(0); + chartTitle.merge(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); + // Format the merged range. + chartTitle.format.horizontalAlignment = "Center"; - // 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)': - >- @@ -5765,7 +5646,7 @@ console.log(`\t${pivotTable.name}`); }); }); -'Excel.Range#getPrecedents:member(1)': +'Excel.Range#getDirectPrecedents:member(1)': - >- // Link to full sample: https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/precedents.yaml @@ -5773,46 +5654,45 @@ 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 precedents = range.getPrecedents(); + let directPrecedents = range.getDirectPrecedents(); range.load("address"); - precedents.areas.load("address"); + directPrecedents.areas.load("address"); await context.sync(); - console.log(`All precedent cells of ${range.address}:`); + console.log(`Direct 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++) { + // 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. - precedents.areas.items[i].format.fill.color = "Orange"; - console.log(` ${precedents.areas.items[i].address}`); + directPrecedents.areas.items[i].format.fill.color = "Yellow"; + console.log(` ${directPrecedents.areas.items[i].address}`); } await context.sync(); }); -'Excel.Range#getRangeEdge:member(1)': +'Excel.Range#getPrecedents:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-get-range-edge.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/precedents.yaml await Excel.run(async (context) => { - // Get the selected range. - const range = context.workbook.getSelectedRange(); - - // Specify the direction with the `KeyboardDirection` enum. - const direction = Excel.KeyboardDirection.up; - - // Get the active cell in the workbook. - const activeCell = context.workbook.getActiveCell(); + // 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 top-most cell of the current used range. - // This method acts like the Ctrl+Arrow key keyboard shortcut while a range is selected. - const rangeEdge = range.getRangeEdge( - direction, - activeCell // If the selected range contains more than one cell, the active cell must be defined. - ); - rangeEdge.select(); + 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)': @@ -5832,355 +5712,480 @@ return context.sync(); }); -'Excel.Range#getSpillingToRange:member(1)': +'Excel.Range#autoFill:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/dynamic-arrays.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-auto-fill.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(); + 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(); - - console.log(`Copying the table headers spilled into ${spillRange.address}.`); }); -'Excel.Range#getUsedRange:member(1)': +'Excel.Range#getCellProperties: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/cell-properties.yaml await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Sample"); - const salesTable = sheet.tables.getItem("SalesTable"); - const dataRange = salesTable.getDataBodyRange(); + const cell = context.workbook.getActiveCell(); - // 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(); + // 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 + }); - // Asian and European teams have separate contests. - const asianSalesRange = sheet.getRange("A2:E4"); - const europeanSalesRange = sheet.getRange("A5:E7"); + // 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 - // 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 Excel.run(async (context) => { + const sheet = context.workbook.worksheets.getActiveWorksheet(); - 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" - ); - } + // 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" + }; - 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" - ); - } + 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#getUsedRangeOrNullObject:member(1)': +'Excel.Range#copyFrom:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/used-range.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-copyfrom.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 */ - ); + // Place a label in front of the copied data. + sheet.getRange("F2").values = [["Copied Formula"]]; - //Must sync before reading value returned from *OrNullObject method/property. + // 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 - 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 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#group:member(1)': +'Excel.Range#getDependents:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/outline.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-dependents.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); + // This function highlights all the dependent cells of the active cell. - // 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(); + // 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#hyperlink:member': +'Excel.Range#getSpillingToRange:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-hyperlink.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/dynamic-arrays.yaml await Excel.run(async (context) => { - const sheet = context.workbook.worksheets.getItem("Orders"); + 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"]]; + + // 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(); - // 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; - } + 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#merge:member(1)': +'Excel.Range#getExtendedRange:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-merged-ranges.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-get-range-edge.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"); + // Get the selected range. + const range = context.workbook.getSelectedRange(); - // Create a merged range in the first row of the table. - const chartTitle = tableRange.getRow(0); - chartTitle.merge(true); + // Specify the direction with the `KeyboardDirection` enum. + const direction = Excel.KeyboardDirection.down; - // Format the merged range. - chartTitle.format.horizontalAlignment = "Center"; + // Get the active cell in the workbook. + const activeCell = context.workbook.getActiveCell(); + + // Get all the cells from the currently selected range to the bottom-most edge of the used range. + // This method acts like the Ctrl+Shift+Arrow key keyboard shortcut while a range is selected. + const extendedRange = range.getExtendedRange( + direction, + activeCell // If the selected range contains more than one cell, the active cell must be defined. + ); + extendedRange.select(); await context.sync(); }); -'Excel.Range#moveTo:member(1)': +'Excel.Range#getRangeEdge:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-copyfrom.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-get-range-edge.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:"]]; + // Get the selected range. + const range = context.workbook.getSelectedRange(); - // Move the range from A1:E1 to G12:K12. - sheet.getRange("A1:E1").moveTo("G12"); - await context.sync(); + // Specify the direction with the `KeyboardDirection` enum. + const direction = Excel.KeyboardDirection.up; + + // Get the active cell in the workbook. + const activeCell = context.workbook.getActiveCell(); + + // Get the top-most cell of the current used range. + // This method acts like the Ctrl+Arrow key keyboard shortcut while a range is selected. + const rangeEdge = range.getRangeEdge( + direction, + activeCell // If the selected range contains more than one cell, the active cell must be defined. + ); + rangeEdge.select(); + + await context.sync(); }); -'Excel.Range#removeDuplicates:member(1)': +'Excel.Range#hyperlink:member': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-remove-duplicates.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("Sample"); - const range = sheet.getRange("B2:D11"); + const sheet = context.workbook.worksheets.getItem("Orders"); + + let productsRange = sheet.getRange("A3:A5"); + productsRange.load("values"); - 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."); + // 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#set:member(2)': +'Excel.Range#getIntersectionOrNullObject:member(1)': - >- // Link to full sample: - https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/90-scenarios/multiple-property-set.yaml + https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/excel/42-range/range-relationships.yaml await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getItem("Sample"); + const salesTable = sheet.tables.getItem("SalesTable"); + const dataRange = salesTable.getDataBodyRange(); - const sourceRange = sheet.getRange("B2:E2"); - sourceRange.load("format/fill/color, format/font/name, format/font/color"); + // We want the most recent quarter that has data, so + // exclude quarters without data and get the last of + // the remaining columns. + const usedDataRange = dataRange.getUsedRange(true /* valuesOnly */); + const currentQuarterRange = usedDataRange.getLastColumn(); + + // Asian and European teams have separate contests. + const asianSalesRange = sheet.getRange("A2:E4"); + const europeanSalesRange = sheet.getRange("A5:E7"); + + // The data for each chart is the intersection of the + // current quarter column and the rows for the continent. + const asianContestRange = asianSalesRange.getIntersectionOrNullObject(currentQuarterRange); + const europeanContestRange = europeanSalesRange.getIntersectionOrNullObject(currentQuarterRange); + + // Must sync before you can test the output of *OrNullObject + // method/property. await context.sync(); - // Set properties based on the loaded and synced - // source range. - const targetRange = sheet.getRange("B7:E7"); - targetRange.set(sourceRange); - targetRange.format.autofitColumns(); + 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" + ); + } + 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: @@ -6198,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': - >- @@ -6639,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); @@ -6668,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: @@ -6716,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': - >- @@ -6747,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)': - >- @@ -6771,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: @@ -6802,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 @@ -6810,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)': @@ -7740,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)': - >- @@ -7793,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: @@ -7832,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)': - >- @@ -8018,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: @@ -8078,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. @@ -8208,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: @@ -8245,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: @@ -8283,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': @@ -8346,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: @@ -8358,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': @@ -8487,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: @@ -8547,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: