-
Notifications
You must be signed in to change notification settings - Fork 125
/
Copy pathcorrelated-objects-pattern.yaml
171 lines (157 loc) · 7.02 KB
/
correlated-objects-pattern.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
order: 3
id: word-scenarios-correlated-objects-pattern
name: Correlated objects pattern
description: Shows the performance benefits of avoiding `context.sync` calls in a loop.
author: OfficeDev
host: WORD
api_set:
WordApi: '1.4'
script:
content: |
$("#replace-placeholders").on("click", () => tryCatch(replacePlaceholders)); $("#replace-placeholders-slow").on("click", () => tryCatch(replacePlaceholdersSlow)); $("#setup").on("click", () => tryCatch(setup)); $("#add-lots-of-text").on("click", () => tryCatch(addLotsOfText));
const jobMapping = [
{ job: "{Coordinator}", person: "Sally" },
{ job: "{Deputy}", person: "Bob" },
{ job: "{Manager}", person: "Kim" }
];
async function replacePlaceholders() {
Word.run(async (context) => {
const startTime = Date.now();
let count = 0;
// Find the locations of all the placeholder strings.
const allSearchResults = [];
for (let i = 0; i < jobMapping.length; i++) {
let options = Word.SearchOptions.newObject(context);
options.matchWildcards = false;
let searchResults = context.document.body.search(jobMapping[i].job, options);
searchResults.load('items');
let correlatedSearchResult = {
rangesMatchingJob: searchResults,
personAssignedToJob: jobMapping[i].person
}
allSearchResults.push(correlatedSearchResult);
}
// Sync to load those locations in the add-in.
await context.sync()
// Replace the placeholder text at the known locations.
for (let i = 0; i < allSearchResults.length; i++) {
let correlatedObject = allSearchResults[i];
for (let j = 0; j < correlatedObject.rangesMatchingJob.items.length; j++) {
let targetRange = correlatedObject.rangesMatchingJob.items[j];
let name = correlatedObject.personAssignedToJob;
targetRange.insertText(name, Word.InsertLocation.replace);
count++;
}
}
await context.sync();
console.log(`Replacing ${count} placeholders with the correlated objects pattern took ${Date.now() - startTime} milliseconds.`);
console.log()
});
}
async function replacePlaceholdersSlow() {
Word.run(async (context) => {
const startTime = Date.now();
let count = 0;
// The context.sync calls in the loops will degrade performance.
for (let i = 0; i < jobMapping.length; i++) {
let options = Word.SearchOptions.newObject(context);
options.matchWildcards = false;
let searchResults = context.document.body.search(jobMapping[i].job, options);
searchResults.load('items');
await context.sync();
for (let j = 0; j < searchResults.items.length; j++) {
searchResults.items[j].insertText(jobMapping[i].person, Word.InsertLocation.replace);
count++;
await context.sync();
}
}
console.log(`Replacing ${count} placeholders with in-loop sync statements took ${Date.now() - startTime} milliseconds.`);
});
}
async function setup(timesToAddText: number = 1) {
await Word.run(async (context) => {
console.log("Setup beginning...");
const body: Word.Body = context.document.body;
body.clear();
while (timesToAddText > 0) {
body.insertParagraph(
"This defines the roles of {Coordinator}, {Deputy}, {Manager}.",
Word.InsertLocation.end
);
body.insertParagraph(
"{Coordinator}: Oversees daily operations and ensures projects run smoothly by coordinating between different teams and resources.",
Word.InsertLocation.end
);
body.insertParagraph(
"{Deputy}: Assists and supports senior management, often stepping in to make decisions or manage tasks in {Manager}'s absence.",
Word.InsertLocation.end
);
body.insertParagraph(
"{Manager}: Leads the team, setting goals, planning strategies, and making decisions to achieve organizational objectives.",
Word.InsertLocation.end
);
timesToAddText--;
}
await context.sync();
console.log("Setup complete.");
});
}
async function addLotsOfText() {
// Add the setup text 100 times.
setup(100);
}
// 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);
}
}
language: typescript
template:
content: |-
<section class="ms-Fabric ms-font-m">
<p>This sample demonstrates the performance optimization gained from the correlated objects pattern. For more information, see <a href="https://learn.microsoft.com/en-us/office/dev/add-ins/concepts/correlated-objects-pattern">Avoid using the context.sync method in loops</a>.</p>
</section>
<section class="ms-Fabric samples ms-font-m">
<h3>Setup</h3>
<p>Use <b>Setup</b> to create a basic text block with some placeholders. Use <b>More text</b> to create a longer text block to better see performance distinctions.</p>
<button id="setup" class="ms-Button">
<span class="ms-Button-label">Setup</span>
</button><button id="add-lots-of-text" class="ms-Button">
<span class="ms-Button-label">More text</span>
</button>
</section>
<section class="ms-Fabric samples ms-font-m">
<h3>Replace placeholder text</h3>
<button id="replace-placeholders" class="ms-Button">
<span class="ms-Button-label">Replace all</span>
</button>
<button id="replace-placeholders-slow" class="ms-Button">
<span class="ms-Button-label">Replace all (slow)</span>
</button>
</section>
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
@types/office-js
[email protected]/dist/css/fabric.min.css
[email protected]/dist/css/fabric.components.min.css
[email protected]/client/core.min.js
@types/core-js
@types/[email protected]