Skip to content

Commit 106b4d1

Browse files
authored
shared runtime ribbon sample (#61)
* add initial working files shared runtime * removed auth dialogs * Added DataFilter * cleanup app.tsx * cleanup on app.tsx * simplify connectbutton.tsx * clean out old auth dialogs * add office initialize state tracking * removed unneeded components * reduced dependencies removed unneeded code * clean up manifest and icons * remove sync button not needed for now * enabled open close task pane buttons * move globals and fix icon links * clean up add-in name * resolve manifest conflict * add readme contents * more cleanup work * additional cleanup * add CORS header * update preview info * note access header * minor check * add screenshot * fix link * fix typo * renamed sample folder * Update README.md * better pic description * Update README.md * Update README.md
1 parent 599e667 commit 106b4d1

36 files changed

+14266
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[config]
2+
SCM_DO_BUILD_DURING_DEPLOYMENT=true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2+
# See LICENSE in the project root for license information.
3+
4+
# Created by https://www.gitignore.io/api/osx,windows
5+
6+
### OSX ###
7+
.DS_Store
8+
.AppleDouble
9+
.LSOverride
10+
11+
# Icon must end with two \r
12+
Icon
13+
14+
15+
# Thumbnails
16+
._*
17+
18+
# Files that might appear in the root of a volume
19+
.DocumentRevisions-V100
20+
.fseventsd
21+
.Spotlight-V100
22+
.TemporaryItems
23+
.Trashes
24+
.VolumeIcon.icns
25+
26+
# Directories potentially created on remote AFP share
27+
.AppleDB
28+
.AppleDesktop
29+
Network Trash Folder
30+
Temporary Items
31+
.apdisk
32+
33+
34+
### Windows ###
35+
# Windows image file caches
36+
Thumbs.db
37+
ehthumbs.db
38+
39+
# Folder config file
40+
Desktop.ini
41+
42+
# Recycle Bin used on file shares
43+
$RECYCLE.BIN/
44+
45+
# Windows Installer files
46+
*.cab
47+
*.msi
48+
*.msm
49+
*.msp
50+
51+
# Windows shortcuts
52+
*.lnk
53+
54+
# Ignore the following folders
55+
.vs
56+
.idea
57+
*.log
58+
obj
59+
bin
60+
*.user
61+
62+
node_modules/**
63+
packages/**
64+
typings/**
65+
.vscode/**
66+
.awcache/**
67+
68+
dist/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
---
2+
page_type: sample
3+
products:
4+
- office-excel
5+
- office-365
6+
languages:
7+
- typescript
8+
extensions:
9+
contentType: samples
10+
technologies:
11+
- Add-ins
12+
createdDate: 3/02/2020 1:25:00 PM
13+
description: "This sample shows how to create contextual ribbon buttons that are enabled based on the state of your add-in. It also shows how to use the Office.js API to show or hide the task pane. This sample also demonstrates how to run code when the task pane is closed, such as on document open."
14+
---
15+
16+
# Manage ribbon and task pane UI, and run code on doc open
17+
18+
## Summary
19+
20+
This sample shows how to create contextual ribbon buttons that are enabled based on the state of your add-in. It also shows how to use the Office.js API to show or hide the task pane. This sample also demonstrates how to run code when the task pane is closed, such as on document open.
21+
22+
![Screen shot of the add-in with ribbon buttons enabled and disabled](excel-shared-runtime.png)
23+
24+
## Features
25+
26+
- Contextual ribbon UI that enables or disables the buttons.
27+
- Set load behavior to load the add-in and run code when the document is opened.
28+
- Open and close the task pane through the Office.js API.
29+
- Handle Office.js events even when the task pane is closed.
30+
- Share data globally, such as between custom functions and the task pane.
31+
32+
## Applies to
33+
34+
- Excel on Windows (one-time purchase and subscription)
35+
36+
## Prerequisites
37+
38+
The features used in this sample are currently in preview and subject to change. They are not currently supported for use in production environments. To try the preview features, you will need to [join Office Insider](https://insider.office.com/join). A good way to try out preview features is by using an Office 365 subscription. If you don't already have an Office 365 subscription, you can get one by joining the [Office 365 Developer Program](https://developer.microsoft.com/office/dev-program).
39+
40+
Before running this sample, make sure you have installed a recent version of [npm](https://www.npmjs.com/get-npm) and [Node.js](https://nodejs.org/en/) on your computer. To check if you have already installed these tools, run the commands `node -v` and `npm -v` in your terminal.
41+
42+
## Solution
43+
44+
Solution | Author(s)
45+
---------|----------
46+
Office Add-in Shared Runtime Ribbon/Task pane APIs | Microsoft
47+
48+
## Version history
49+
50+
Version | Date | Comments
51+
---------| -----| --------
52+
1.0 | 3-2-2020 | Initial release
53+
54+
## Disclaimer
55+
56+
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
57+
58+
----------
59+
60+
## Scenario: A contextual add-in
61+
62+
This sample demonstrates a fictional scenario where the add-in connects to a backend data service to help the user import and work with Contoso data. To keep things simple, the data is mock data and the sample does not require an actual backend data service.
63+
64+
The add-in is aware of whether it is connected. When connected you will see the task pane update to allow you to import data, and also the ribbon buttons will be enabled to let you insert a table and work with the data.
65+
66+
Additionally the add-in has a custom function that can display a filtered view of the data. The custom function is aware of the connection status, so that when connected, it will display the mock data. When disconnected, it will show `#N/A`.
67+
68+
## Build and run the solution
69+
70+
In the command prompt, run the command `start npm start`. This will open a second command prompt, build the project and then start a server (with dev mode settings). It takes from 5 to 30 seconds. When it finishes, the last line should say `Compiled successfully`. Minimize this command prompt.
71+
72+
Back in the original command prompt, run the command `npm run sideload`. This will launch Excel and sideload the add-in. After a few seconds, a ribbon named `Contoso Data` will appear.
73+
74+
The add-in's ribbon buttons have the following behavior:
75+
76+
- **Connect service:** Connects to a mock Contoso data service. You can choose a CSV file, or database.
77+
- **Disconnect service:** Disonnects from the mock Contoso data service.
78+
- **Insert data:** Inserts a table from the mock Contoso data service.
79+
- **Sum:** Enabled when you are in the table. Select a range of numerical cells and it will output the sum of those cells.
80+
- **Load on doc open:** Choose this to enable the add-in to run the next time the document is opened. The `Sum` button will work immediately when in the table the next time the document is opened. Note that you need to save the document first to save this change.
81+
- **No load behavior:** Choose this to disable the add-in from running on document open. The Sum button will not work until you activate the add-in in some way (ribbon, task pane or custom function action).
82+
- **Open task pane:** Opens the task pane.
83+
- **Close task pane:** Closes the task pane. The task pane is not shut down and will remember its state.
84+
85+
If the add-in is not connected to a service, the task pane will show a button to connect. Once connected, the task pane lets you choose a category from the data and insert a custom function. The custom function will filter data displayed to the selected category.
86+
87+
88+
## Key parts of this sample
89+
90+
Global state is tracked in a window object retrieved using a `getGlobal()` function. This is accessible to custom functions, the task pane, and the ribbon (because all the code is running in the same JavaScript runtime.) The `ensureStateInitialized()` method initializes global state on startup. The global state tracks many items such as whether the add-in is connected to a service, and whether the task pane is open or closed.
91+
92+
### Enable and disable ribbon buttons
93+
94+
To enable and disable ribbon buttons the add-in uses the `Office.ribbon.requestUpdate` method and passes a JSON description of the buttons. Anytime there is a state change that requires the ribbon buttons to change, the `updateRibbon()` is called which sets if buttons are enabled based on global state variables.
95+
96+
### Open and close the task pane
97+
98+
To open or close the task pane, the add-in uses the `Office.addin.showAsTaskpane()` and `Office.addin.hide()` methods.
99+
100+
### Set runtime load behavior
101+
102+
If the `Load on doc open` button is chosen, the add-in configures the document so that the add-in begins running as soon as the document is opened. This allows the add-in to start running and monitoring Office events before the task pane is displayed. To configure the document to load the add-in on open, the add-in uses the `Office.addin.setStartupBehavior(Office.StartupBehavior.load)` method. To turn off the document load behavior, the add-in uses the `Office.addin.setStartupBehavior(Office.StartupBehavior.none)` method.
103+
104+
### Run code in the background
105+
106+
The add-in has a `Sum` button that is enabled when you move the range selection inside the expenses table. An event in the table is used to detect when the range selection is in or out of the table. If the add-in was configured to load on doc open, the event code will be operational as soon as the document is opened, and the `Sum` button will work even though the task pane is not yet opened.
107+
108+
To run code when the document opens, the add-in relies on the `Office.Initialize` event. This event is called when the document is opened and the load behavior is set for doc open. The add-in calls `ensureInitialize()` to set up the initial global state.
109+
110+
```typescript
111+
Office.initialize = async () => {
112+
ensureStateInitialized(true);
113+
114+
...
115+
```
116+
117+
The `ensureStateInitialized()` method will call the `monitorSheetCHanges()` method which will then search for the expenses table. If the expenses table was inserted, it adds an event handler for the `onTableSelectionChange` event. This is how the event handler code is set up on doc open.
118+
119+
```typescript
120+
export async function monitorSheetChanges() {
121+
try {
122+
let g = getGlobal() as any;
123+
if (g.state.isInitialized) {
124+
await Excel.run(async context => {
125+
let table = context.workbook.tables.getItem('ExpensesTable');
126+
if (table !== undefined) {
127+
table.onSelectionChanged.add(onTableSelectionChange);
128+
await context.sync();
129+
updateRibbon();
130+
} else {
131+
g.state.isSumEnabled = false;
132+
updateRibbon();
133+
}
134+
...
135+
```
136+
137+
## Security notes
138+
139+
In the webpack.dev.js file, a header is set to `"Access-Control-Allow-Origin": "*"`. This is only for development purposes. In production code, you should list the allowed domains and not leave this header open to all domains.
140+
141+
You'll be prompted to install certificates for trusted access to https://localhost. The certificates are intended only for running and studying this code sample. Do not reuse them in your own code solutions or in production environments.
142+
143+
You can install or uninstall the certificates by running the following commands in the project folder.
144+
145+
```
146+
npx office-addin-dev-certs install
147+
npx office-addin-dev-certs uninstall
148+
```
149+
150+
## Copyright
151+
152+
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
153+
154+
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information, see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.
155+
156+
<img src="https://telemetry.sharepointpnp.com/officedev/samples/excel-shared-runtime-scenario" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3+
* See LICENSE in the project root for license information.
4+
*/
5+
6+
html,
7+
body {
8+
width: 100%;
9+
height: 100%;
10+
margin: 0;
11+
padding: 0;
12+
}
13+
14+
ul,
15+
p,
16+
h1,
17+
h2,
18+
h3,
19+
h4,
20+
h5,
21+
h6 {
22+
margin: 0;
23+
padding: 0;
24+
}
25+
26+
.ms-welcome {
27+
position: relative;
28+
display: -webkit-flex;
29+
display: flex;
30+
-webkit-flex-direction: column;
31+
flex-direction: column;
32+
-webkit-flex-wrap: nowrap;
33+
flex-wrap: nowrap;
34+
min-height: 500px;
35+
min-width: 320px;
36+
overflow: auto;
37+
overflow-x: hidden;
38+
}
39+
40+
.ms-welcome__header {
41+
min-height: 250px;
42+
padding: 20px;
43+
padding-bottom: 30px;
44+
display: -webkit-flex;
45+
display: flex;
46+
-webkit-flex-direction: column;
47+
flex-direction: column;
48+
-webkit-flex-wrap: nowrap;
49+
flex-wrap: nowrap;
50+
-webkit-align-items: center;
51+
align-items: center;
52+
-webkit-justify-content: flex-end;
53+
justify-content: flex-end;
54+
}
55+
56+
.ms-welcome__header > h1 {
57+
margin-top: 30px;
58+
text-align: center;
59+
}
60+
61+
.ms-welcome__main {
62+
display: -webkit-flex;
63+
display: flex;
64+
-webkit-flex-direction: column;
65+
flex-direction: column;
66+
-webkit-flex-wrap: nowrap;
67+
flex-wrap: nowrap;
68+
-webkit-align-items: center;
69+
align-items: center;
70+
-webkit-flex: 1 0 0;
71+
flex: 1 0 0;
72+
padding: 30px 20px;
73+
}
74+
75+
.ms-welcome__main > h2 {
76+
width: 100%;
77+
text-align: center;
78+
}
79+
80+
.ms-welcome__features {
81+
list-style-type: none;
82+
margin-top: 30px;
83+
}
84+
85+
.ms-welcome__features.ms-List .ms-ListItem {
86+
padding: 0px;
87+
padding-bottom: 20px;
88+
display: -webkit-flex;
89+
display: flex;
90+
-webkit-flex-direction: row;
91+
flex-direction: row;
92+
-webkit-flex-wrap: nowrap;
93+
flex-wrap: nowrap;
94+
-webkit-align-items: center;
95+
align-items: center;
96+
}
97+
98+
.ms-welcome__features.ms-List .ms-ListItem > .ms-Icon {
99+
font-size: 14pt;
100+
}
101+
102+
.ms-welcome__features.ms-List .ms-ListItem > .ms-Icon {
103+
margin-right: 10px;
104+
}
105+
106+
.ms-welcome__action.ms-Button--hero {
107+
margin-top: 30px;
108+
display: -webkit-flex;
109+
display: flex;
110+
-webkit-flex-direction: row;
111+
flex-direction: row;
112+
-webkit-flex-wrap: nowrap;
113+
flex-wrap: nowrap;
114+
-webkit-justify-content: center;
115+
justify-content: center;
116+
-webkit-align-items: center;
117+
align-items: center;
118+
}
119+
120+
.ms-welcome__action.ms-Button--hero .ms-Button-icon .ms-Icon {
121+
margin-left: 5px;
122+
margin-top: 4px;
123+
border: none;
124+
font-size: 14pt;
125+
}
126+
127+
.ms-welcome__action.ms-Button--hero:hover .ms-Button-icon .ms-Icon {
128+
border: none;
129+
}
130+
131+
@media (min-width: 0) and (max-width: 350px) {
132+
.ms-welcome__features {
133+
width: 100%;
134+
}
135+
}
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDtzCCAp+gAwIBAgIJAM2mE5TOxoFEMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNV
3+
BAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHUmVkbW9uZDEPMA0GA1UECgwG
4+
T2ZmaWNlMRwwGgYDVQQLDBNPZmZpY2VFeHRlbnNpYmlsaXR5MRUwEwYDVQQDDAxs
5+
b2NhbGhvc3QtY2EwHhcNMTgwNDExMTgwNjExWhcNMjMwNDExMTgwNjExWjByMQsw
6+
CQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1JlZG1vbmQxDzANBgNV
7+
BAoMBk9mZmljZTEcMBoGA1UECwwTT2ZmaWNlRXh0ZW5zaWJpbGl0eTEVMBMGA1UE
8+
AwwMbG9jYWxob3N0LWNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
9+
ymd3VtdKsAtRo2Ug5cpC2sXa2VACIbwkQHNEps2Q8wcBhAdfahKIStfQKrTF8UqW
10+
tcpfSIhxcBMBhBITDXKlnu1HRO77ufC/w1AToJKPfzC2RfMEiLpeuHk8Sy65ST8f
11+
o3L1BuqwYsVspFu//hLpeGQAv7Z4QV/DOeR2Uw8bi9m8ayYEDaMckVq1Pq7gF+vP
12+
tOG/EDyAHoM5PzWd75TNNM3ysbN0edT9SEk3fOUOR1b0M0QXsxRAzgkpFUtTFy4a
13+
7YMFL113Jb+wMiUS7KZJalDrcjhthJInlAUwYNE3qFGqK412VbGDnwnas7L3+m8u
14+
PXM6AMgFKRvT+48zf9JkyQIDAQABo1AwTjAdBgNVHQ4EFgQUAnM7hKUXgNu7/kXI
15+
TkhWbbx428IwHwYDVR0jBBgwFoAUAnM7hKUXgNu7/kXITkhWbbx428IwDAYDVR0T
16+
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAPcsXB8fcFuRf3OuX7iUFPU1c04VK
17+
1y0HnWNC0jkPQKAale5+AsV99TFIBxb4ml+iokUU+SIdMwlHFkeVeVHhH8545LUF
18+
lbRQCjlcWsN9eAAci7h+BxE9sQt4LBNGmedzM+7+9rR3pzMI6zsaVyK7xS85G1mF
19+
nw3Ajfs+zqu3li+wsVF/4M7o6z0mjA036ejh3YgLabMSNHfNA+1ltPZwlKSE6+zR
20+
Wudewkb2yeDK85Z4l3vOhZPtZsBV2Uni34qXdTSAPGSXcRKd9NuArTjvt1QbD313
21+
8YY1RxQjEDdW14StquAbm8BCrGZ6ks3h5mJQh++6pqELRI3P24e5zc1gIg==
22+
-----END CERTIFICATE-----

0 commit comments

Comments
 (0)