Skip to content

Commit a034dfc

Browse files
authored
Add a sample highlighting the perf benefits of the correlated objects pattern (#959)
1 parent 5e26d5f commit a034dfc

File tree

5 files changed

+191
-0
lines changed

5 files changed

+191
-0
lines changed

playlists-prod/word.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,15 @@
553553
group: Scenarios
554554
api_set:
555555
WordApi: '1.3'
556+
- id: word-scenarios-correlated-objects-pattern
557+
name: Correlated objects pattern
558+
fileName: correlated-objects-pattern.yaml
559+
description: Shows the performance benefits of avoiding `context.sync` calls in a loop.
560+
rawUrl: >-
561+
https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/correlated-objects-pattern.yaml
562+
group: Scenarios
563+
api_set:
564+
WordApi: '1.4'
556565
- id: word-insert-and-change-content-controls
557566
name: Content control basics
558567
fileName: insert-and-change-content-controls.yaml

playlists/word.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,15 @@
553553
group: Scenarios
554554
api_set:
555555
WordApi: '1.3'
556+
- id: word-scenarios-correlated-objects-pattern
557+
name: Correlated objects pattern
558+
fileName: correlated-objects-pattern.yaml
559+
description: Shows the performance benefits of avoiding `context.sync` calls in a loop.
560+
rawUrl: >-
561+
https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/90-scenarios/correlated-objects-pattern.yaml
562+
group: Scenarios
563+
api_set:
564+
WordApi: '1.4'
556565
- id: word-insert-and-change-content-controls
557566
name: Content control basics
558567
fileName: insert-and-change-content-controls.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
order: 3
2+
id: word-scenarios-correlated-objects-pattern
3+
name: Correlated objects pattern
4+
description: Shows the performance benefits of avoiding `context.sync` calls in a loop.
5+
author: OfficeDev
6+
host: WORD
7+
api_set:
8+
WordApi: '1.4'
9+
script:
10+
content: |
11+
$("#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));
12+
const jobMapping = [
13+
{ job: "{Coordinator}", person: "Sally" },
14+
{ job: "{Deputy}", person: "Bob" },
15+
{ job: "{Manager}", person: "Kim" }
16+
];
17+
async function replacePlaceholders() {
18+
Word.run(async (context) => {
19+
const startTime = Date.now();
20+
let count = 0;
21+
22+
// Find the locations of all the placeholder strings.
23+
const allSearchResults = [];
24+
for (let i = 0; i < jobMapping.length; i++) {
25+
let options = Word.SearchOptions.newObject(context);
26+
options.matchWildcards = false;
27+
let searchResults = context.document.body.search(jobMapping[i].job, options);
28+
searchResults.load('items');
29+
let correlatedSearchResult = {
30+
rangesMatchingJob: searchResults,
31+
personAssignedToJob: jobMapping[i].person
32+
}
33+
allSearchResults.push(correlatedSearchResult);
34+
}
35+
36+
// Sync to load those locations in the add-in.
37+
await context.sync()
38+
39+
// Replace the placeholder text at the known locations.
40+
for (let i = 0; i < allSearchResults.length; i++) {
41+
let correlatedObject = allSearchResults[i];
42+
43+
for (let j = 0; j < correlatedObject.rangesMatchingJob.items.length; j++) {
44+
let targetRange = correlatedObject.rangesMatchingJob.items[j];
45+
let name = correlatedObject.personAssignedToJob;
46+
targetRange.insertText(name, Word.InsertLocation.replace);
47+
count++;
48+
}
49+
}
50+
51+
await context.sync();
52+
console.log(`Replacing ${count} placeholders with the correlated objects pattern took ${Date.now() - startTime} milliseconds.`);
53+
console.log()
54+
});
55+
}
56+
async function replacePlaceholdersSlow() {
57+
Word.run(async (context) => {
58+
const startTime = Date.now();
59+
let count = 0;
60+
61+
// The context.sync calls in the loops will degrade performance.
62+
for (let i = 0; i < jobMapping.length; i++) {
63+
let options = Word.SearchOptions.newObject(context);
64+
options.matchWildcards = false;
65+
let searchResults = context.document.body.search(jobMapping[i].job, options);
66+
searchResults.load('items');
67+
68+
await context.sync();
69+
70+
for (let j = 0; j < searchResults.items.length; j++) {
71+
searchResults.items[j].insertText(jobMapping[i].person, Word.InsertLocation.replace);
72+
count++;
73+
await context.sync();
74+
}
75+
}
76+
console.log(`Replacing ${count} placeholders with in-loop sync statements took ${Date.now() - startTime} milliseconds.`);
77+
});
78+
}
79+
async function setup(timesToAddText: number = 1) {
80+
await Word.run(async (context) => {
81+
console.log("Setup beginning...");
82+
const body: Word.Body = context.document.body;
83+
body.clear();
84+
while (timesToAddText > 0) {
85+
body.insertParagraph(
86+
"This defines the roles of {Coordinator}, {Deputy}, {Manager}.",
87+
Word.InsertLocation.end
88+
);
89+
body.insertParagraph(
90+
"{Coordinator}: Oversees daily operations and ensures projects run smoothly by coordinating between different teams and resources.",
91+
Word.InsertLocation.end
92+
);
93+
body.insertParagraph(
94+
"{Deputy}: Assists and supports senior management, often stepping in to make decisions or manage tasks in {Manager}'s absence.",
95+
Word.InsertLocation.end
96+
);
97+
body.insertParagraph(
98+
"{Manager}: Leads the team, setting goals, planning strategies, and making decisions to achieve organizational objectives.",
99+
Word.InsertLocation.end
100+
);
101+
timesToAddText--;
102+
}
103+
await context.sync();
104+
console.log("Setup complete.");
105+
});
106+
}
107+
async function addLotsOfText() {
108+
// Add the setup text 100 times.
109+
setup(100);
110+
}
111+
// Default helper for invoking an action and handling errors.
112+
async function tryCatch(callback) {
113+
try {
114+
await callback();
115+
} catch (error) {
116+
// Note: In a production add-in, you'd want to notify the user through your add-in's UI.
117+
console.error(error);
118+
}
119+
}
120+
language: typescript
121+
template:
122+
content: |-
123+
<section class="ms-Fabric ms-font-m">
124+
<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>
125+
</section>
126+
127+
<section class="ms-Fabric samples ms-font-m">
128+
<h3>Setup</h3>
129+
<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>
130+
<button id="setup" class="ms-Button">
131+
<span class="ms-Button-label">Setup</span>
132+
</button><button id="add-lots-of-text" class="ms-Button">
133+
<span class="ms-Button-label">More text</span>
134+
</button>
135+
</section>
136+
137+
<section class="ms-Fabric samples ms-font-m">
138+
<h3>Replace placeholder text</h3>
139+
<button id="replace-placeholders" class="ms-Button">
140+
<span class="ms-Button-label">Replace all</span>
141+
</button>
142+
<button id="replace-placeholders-slow" class="ms-Button">
143+
<span class="ms-Button-label">Replace all (slow)</span>
144+
</button>
145+
</section>
146+
language: html
147+
style:
148+
content: |-
149+
section.samples {
150+
margin-top: 20px;
151+
}
152+
153+
section.samples .ms-Button, section.setup .ms-Button {
154+
display: block;
155+
margin-bottom: 5px;
156+
margin-left: 20px;
157+
min-width: 80px;
158+
}
159+
language: css
160+
libraries: |
161+
https://appsforoffice.microsoft.com/lib/1/hosted/office.js
162+
@types/office-js
163+
164+
[email protected]/dist/css/fabric.min.css
165+
[email protected]/dist/css/fabric.components.min.css
166+
167+
[email protected]/client/core.min.js
168+
@types/core-js
169+
170+
171+

view-prod/word.json

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"word-document-compare-documents": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/50-document/compare-documents.yaml",
5656
"word-scenarios-doc-assembly": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/doc-assembly.yaml",
5757
"word-scenarios-multiple-property-set": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/multiple-property-set.yaml",
58+
"word-scenarios-correlated-objects-pattern": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/90-scenarios/correlated-objects-pattern.yaml",
5859
"word-insert-and-change-content-controls": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/insert-and-change-content-controls.yaml",
5960
"word-manage-comments": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/prod/samples/word/99-preview-apis/manage-comments.yaml"
6061
}

view/word.json

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"word-document-compare-documents": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/50-document/compare-documents.yaml",
5656
"word-scenarios-doc-assembly": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/90-scenarios/doc-assembly.yaml",
5757
"word-scenarios-multiple-property-set": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/90-scenarios/multiple-property-set.yaml",
58+
"word-scenarios-correlated-objects-pattern": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/90-scenarios/correlated-objects-pattern.yaml",
5859
"word-insert-and-change-content-controls": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/99-preview-apis/insert-and-change-content-controls.yaml",
5960
"word-manage-comments": "https://raw.githubusercontent.com/OfficeDev/office-js-snippets/main/samples/word/99-preview-apis/manage-comments.yaml"
6061
}

0 commit comments

Comments
 (0)