Skip to content

Commit 15b0646

Browse files
aafvstamMaarten van Stamdavidchesnut
authored
Add Add-in Commands to the Ribbon to interop between JavaScript and C# with Blazor Pages. (#762)
* Initial Branch Custom Add-in Functions from Ribbon * Made a little bit of progression on implementing Commands, not working though To be continued * Enabled JavaScript Add-in Commands (Color and Write), Blazor Functions still unable to be called from Add-in Commands. We know how to load the environment but Blazor load timing still arrives AFTER the function call. * Got the Ribbon .NET Blazor Interop to work from the Ribbon to run C# Methods in the OfficeJS Ribbon context. * Got everything to work, calling C# functions from the Ribbon, and calling JS functions from that C# function. * Added JS - CS Interop Functions to Word Office Add-in, similar to what we did earlier with Excel. Also some minor restructuring and fixes, removing obsolete code. * Updated final Excel Checks, Readme still open to finalize. * Making Minor Changes, still need to finalize Readme and checks before PR * Updated ReadMe and cleaning up before creating PR to Microsoft Repo * Remove generated items from csproj.user (in general I think .user should not even be in the project ...) * Added some comments * Update Samples/blazor-add-in/excel-blazor-add-in/excel-blazor-add-in/Pages/BubbleChart.razor.js Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/excel-blazor-add-in/excel-blazor-add-in/wwwroot/Commands/commands.js Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/excel-blazor-add-in/README.md Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/word-blazor-add-in/README.md Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/excel-blazor-add-in/excel-blazor-add-in/wwwroot/Commands/commands.js Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/excel-blazor-add-in/excel-blazor-sideloader/excel-blazor-sideloaderManifest/excel-blazor-sideloader.xml Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/excel-blazor-add-in/excel-blazor-sideloader/excel-blazor-sideloaderManifest/excel-blazor-sideloader.xml Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/excel-blazor-add-in/README.md Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/excel-blazor-add-in/README.md Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/excel-blazor-add-in/README.md Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/word-blazor-add-in/README.md Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/excel-blazor-add-in/README.md Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/word-blazor-add-in/README.md Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/word-blazor-add-in/README.md Co-authored-by: David Chesnut <[email protected]> * Update Samples/blazor-add-in/word-blazor-add-in/README.md Co-authored-by: David Chesnut <[email protected]> * Added suggestions from PR * Added some errorhandling and fixing Excel API call * Another missed change ... --------- Co-authored-by: Maarten van Stam <[email protected]> Co-authored-by: David Chesnut <[email protected]>
1 parent 05f76e7 commit 15b0646

File tree

20 files changed

+730
-212
lines changed

20 files changed

+730
-212
lines changed

Samples/blazor-add-in/excel-blazor-add-in/README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ This sample shows how to build an Excel add-in using .NET Blazor technologies. B
2424
- Initialize the Office JavaScript API library in Blazor context.
2525
- Interact with Excel to manipulate worksheets.
2626
- Interact with workbook content through Office JavaScript APIs.
27+
- Interact with methods defined on the Blazor Pages.
28+
- Interop between OfficeJS - JavaScript - C# and back to JavaScript.
2729

2830
## Applies to
2931

@@ -38,9 +40,9 @@ This sample shows how to build an Excel add-in using .NET Blazor technologies. B
3840
1. Download or clone the [Office Add-ins samples repository](https://github.com/OfficeDev/Office-Add-in-samples).
3941
1. Open Visual Studio 2022 and open the **Office-Add-in-samples\Samples\blazor-add-in\excel-blazor-add-in\excel-blazor-add-in.sln** solution. (Do **not** open Visual Studio "as administrator". There is a bug that will prevent the add-in from sideloading when Visual Studio is elevated in this way.)
4042
1. Choose **Debug** > **Start Debugging**. Or press F5 to start the solution.
41-
1. When Excel opens, choose **Home** > **Show Taskpane**.
42-
43-
Next, try out the controls.
43+
1. When Excel opens, choose **Sample Add-in** > **Show task pane** (if not already open).
44+
1. Try out the controls on the task panes.
45+
1. Try out the custom buttons on the **Sample Add-in** tab on the ribbon.
4446

4547
## Understand an Office Add-in in Blazor Context
4648

@@ -94,6 +96,9 @@ The fundamental pattern includes the following steps.
9496
1. Use **JSModule.InvokeVoidAsync** to call JavaScript functions from your C# code.
9597
1. Call Office JS APIs to interact with the worksheet from JavaScript code.
9698

99+
### Blazor interop with Add-in Commands
100+
This sample shows how to use Blazor with custom buttons on the ribbon. The buttons call the same functions that are defined on the task pane. This sample is configured to use the shared runtime which is required for this interop to work correctly.
101+
97102
## Debugging
98103

99104
This sample is configured to support debugging both JavaScript and C# files. New Blazor projects need the following file updates to support C# debugging.
@@ -131,6 +136,7 @@ Version | Date | Comments
131136
---------| ---------------- | ------------------
132137
1.0 | May 27, 2022 | Initial release
133138
2.0 | February 1, 2024 | Upgraded to .NET 8
139+
3.0 | April 18, 2024 | Added Add-in Commands, demo JS and C# Interop from the Ribbon
134140

135141
## Copyright
136142

Samples/blazor-add-in/excel-blazor-add-in/excel-blazor-add-in/BlazorAddIn.csproj

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
<Nullable>enable</Nullable>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<TargetOfficeVersion>15.0</TargetOfficeVersion>
8+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
89
</PropertyGroup>
9-
10+
1011
<ItemGroup>
11-
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.1" />
12-
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.1" PrivateAssets="all" />
13-
<PackageReference Include="Microsoft.JSInterop.WebAssembly" Version="8.0.1" />
12+
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.3" />
13+
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.3" PrivateAssets="all" />
14+
<PackageReference Include="Microsoft.JSInterop.WebAssembly" Version="8.0.3" />
1415
</ItemGroup>
1516

1617
<ItemGroup>

Samples/blazor-add-in/excel-blazor-add-in/excel-blazor-add-in/Pages/BubbleChart.razor.cs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
/* Copyright(c) Maarten van Stam. All rights reserved. Licensed under the MIT License. */
2-
32
using Microsoft.AspNetCore.Components;
43
using Microsoft.JSInterop;
54

5+
using System.Diagnostics.CodeAnalysis;
6+
using System.Runtime.InteropServices.JavaScript;
7+
using System.Runtime.Versioning;
8+
69
namespace BlazorAddIn.Pages
710
{
811
/// <summary>
912
/// Starter class to demo how to create a bubble chart.
1013
/// </summary>
14+
[SupportedOSPlatform("browser")]
1115
public partial class BubbleChart
1216
{
13-
[Inject]
14-
public IJSRuntime JSRuntime { get; set; } = default!;
15-
public IJSObjectReference JSModule { get; set; } = default!;
17+
[Inject, AllowNull]
18+
private IJSRuntime JSRuntime { get; set; }
19+
private IJSObjectReference? JSModule { get; set; }
1620

1721
protected override async Task OnAfterRenderAsync(bool firstRender)
1822
{
@@ -31,8 +35,28 @@ private async Task CreateTable() =>
3135
/// <summary>
3236
/// Function to create the actual bubble chart.
3337
/// </summary>
34-
private async Task CreateBubbleChart() =>
38+
private async Task CreateBubbleChart() =>
3539
await JSModule.InvokeVoidAsync("createBubbleChart");
40+
41+
[JSImport("createTable", "BubbleChart")]
42+
internal static partial Task CreateImportedTable();
43+
44+
[JSImport("createBubbleChart", "BubbleChart")]
45+
internal static partial Task RunCreateChart();
46+
47+
[JSInvokable]
48+
public static async Task CreateBubbles()
49+
{
50+
await JSHost.ImportAsync("BubbleChart", "../Pages/BubbleChart.razor.js");
51+
await CreateImportedTable();
52+
await RunCreateChart();
53+
}
54+
55+
[JSInvokable]
56+
public static string SayHelloBubble(string name)
57+
{
58+
return $"Hello Bubble, {name} from BubbleChart!";
59+
}
3660
}
3761
}
3862

Samples/blazor-add-in/excel-blazor-add-in/excel-blazor-add-in/Pages/BubbleChart.razor.js

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,33 @@
33
* This bubble chart sample is extracted from the excellent helper tool called Script Lab.
44
* Find this sample and more at https://aka.ms/getscriptlab.
55
*/
6+
console.log("Loading BubbleChart.razor.js");
7+
8+
export async function createTable() {
9+
await Excel.run(async (context) => {
10+
context.workbook.worksheets.getItemOrNullObject("Sample").delete();
11+
const sheet = context.workbook.worksheets.add("Sample");
12+
13+
const inventoryTable = sheet.tables.add("A1:D1", true);
14+
inventoryTable.name = "Sales";
15+
inventoryTable.getHeaderRowRange().values = [["Product", "Inventory", "Price", "Current Market Share"]];
16+
17+
inventoryTable.rows.add(null, [
18+
["Calamansi", 2000, "$2.45", "10%"],
19+
["Cara cara orange", 10000, "$2.12", "45%"],
20+
["Limequat", 4000, "$0.70", "66%"],
21+
["Meyer lemon", 100, "$2.65", "5%"],
22+
["Pomelo", 4000, "$1.69", "14%"],
23+
["Yuzu", 7500, "$3.23", "34%"]
24+
]);
25+
26+
sheet.getUsedRange().format.autofitColumns();
27+
sheet.getUsedRange().format.autofitRows();
28+
29+
sheet.activate();
30+
await context.sync();
31+
});
32+
}
633

734
export async function createBubbleChart() {
835
await Excel.run(async (context) => {
@@ -51,28 +78,3 @@ export async function createBubbleChart() {
5178
});
5279
}
5380

54-
export async function createTable() {
55-
await Excel.run(async (context) => {
56-
context.workbook.worksheets.getItemOrNullObject("Sample").delete();
57-
const sheet = context.workbook.worksheets.add("Sample");
58-
59-
let inventoryTable = sheet.tables.add("A1:D1", true);
60-
inventoryTable.name = "Sales";
61-
inventoryTable.getHeaderRowRange().values = [["Product", "Inventory", "Price", "Current Market Share"]];
62-
63-
inventoryTable.rows.add(null, [
64-
["Calamansi", 2000, "$2.45", "10%"],
65-
["Cara cara orange", 10000, "$2.12", "45%"],
66-
["Limequat", 4000, "$0.70", "66%"],
67-
["Meyer lemon", 100, "$2.65", "5%"],
68-
["Pomelo", 4000, "$1.69", "14%"],
69-
["Yuzu", 7500, "$3.23", "34%"]
70-
]);
71-
72-
sheet.getUsedRange().format.autofitColumns();
73-
sheet.getUsedRange().format.autofitRows();
74-
75-
sheet.activate();
76-
await context.sync();
77-
});
78-
}

Samples/blazor-add-in/excel-blazor-add-in/excel-blazor-add-in/Pages/Index.razor.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,26 @@
33
using Microsoft.AspNetCore.Components;
44
using Microsoft.JSInterop;
55

6+
using System.Diagnostics;
7+
using System.Diagnostics.CodeAnalysis;
8+
69
namespace BlazorAddIn.Pages
710
{
811
/// <summary>
912
/// Starter class to demo how to insert `Hello world!` text.
1013
/// </summary>
1114
public partial class Index
1215
{
13-
[Inject]
14-
public IJSRuntime JSRuntime { get; set; } = default!;
15-
public IJSObjectReference JSModule { get; set; } = default!;
16+
[Inject, AllowNull]
17+
private IJSRuntime JSRuntime { get; set; }
18+
private IJSObjectReference JSModule { get; set; } = default!;
1619

1720
protected override async Task OnAfterRenderAsync(bool firstRender)
1821
{
1922
if (firstRender)
2023
{
24+
Debug.WriteLine("Hit OnAfterRenderAsync in Index.razor.cs!");
25+
Console.WriteLine("Hit OnAfterRenderAsync in Index.razor.cs in Console!");
2126
JSModule = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./Pages/Index.razor.js");
2227
}
2328
}
@@ -27,5 +32,11 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
2732
/// </summary>
2833
private async Task HelloButton() =>
2934
await JSModule.InvokeVoidAsync("helloButton");
35+
36+
[JSInvokable]
37+
public static string SayHelloIndex(string name)
38+
{
39+
return $"Hello Index, {name} from Index!";
40+
}
3041
}
3142
}

Samples/blazor-add-in/excel-blazor-add-in/excel-blazor-add-in/Pages/Index.razor.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
/**
33
* Basic function to show how to insert a value into cell A1 on the selected Excel worksheet.
44
*/
5+
console.log("Loading Index.razor.js");
6+
57
export function helloButton() {
68

9+
console.log("We are now entering function: helloButton");
10+
711
return Excel.run(context => {
812

13+
914
// Insert text 'Hello world!' into cell A1.
1015
context.workbook.worksheets.getActiveWorksheet().getRange("A1").values = [['Hello world!']];
1116

Samples/blazor-add-in/excel-blazor-add-in/excel-blazor-add-in/wwwroot/BlazorAddIn.lib.module.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
* - Configuring Blazor settings.
88
*/
99

10+
console.log("Loading BlazorAddin.lib.module.js");
11+
1012
/**
1113
* beforeStart(options, extensions):
1214
*
@@ -19,14 +21,17 @@ export async function beforeStart(wasmoptions, extensions) {
1921
console.log("We are now entering function: beforeStart");
2022

2123
Office.onReady((info) => {
24+
25+
// Office Finished Loading
26+
console.log("Office onReady.");
27+
2228
// Check that we loaded into Excel.
2329
if (info.host === Office.HostType.Excel) {
2430
console.log("We are now hosting in Excel.");
2531
}
2632
else {
2733
console.log("We are now hosting in The Browser (of your choice).");
2834
}
29-
console.log("Office onReady.");
3035
});
3136
}
3237

@@ -38,4 +43,5 @@ export async function beforeStart(wasmoptions, extensions) {
3843
*/
3944
export async function afterStarted(blazor) {
4045
console.log("We are now entering function: afterStarted");
41-
}
46+
}
47+

0 commit comments

Comments
 (0)