Created
January 15, 2018 20:15
-
-
Save Rick-Kirkham/9c5a803e52480ec7f00bb3224292e0ab to your computer and use it in GitHub Desktop.
Shared with Script Lab
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: 48227941-document-not-in-sync-after-replace-text-2 | |
description: '' | |
author: Rick-Kirkham | |
host: WORD | |
api_set: {} | |
script: | |
content: |- | |
$("#setup").click(() => tryCatch(setup)); | |
$("#run").click(() => tryCatch(FindAndReplace)); | |
async function FindAndReplace() { | |
let myTags = [ | |
{ "value": "1", "text": "{{test}}" }, | |
{ "value": "2", "text": "[[test]]" }, | |
{ "value": "3", "text": "{test}" }, | |
{ "value": "4", "text": "bob" }, | |
{ "value": "5", "text": "bobb" }, | |
{ "value": "6", "text": "ssally" }, | |
{ "value": "7", "text": "sally" } | |
]; | |
let allSearchResults = []; | |
await Word.run(async (context) => { | |
for (let tag of myTags) { | |
let options = Word.SearchOptions.newObject(context); | |
options.matchWildCards = false; | |
let searchResults = context.document.body.search(tag.text, options); | |
searchResults.load('text'); | |
// Store each set of found ranges and the text that should replace | |
// them together, so we don't have to reconstruct the correlation | |
// after the context.sync. | |
let correlatedSearchResult = { | |
searchHits: searchResults, | |
replacementString: tag.value | |
} | |
allSearchResults.push(correlatedSearchResult); | |
} | |
await context.sync(); | |
/// Now that we've loaded the found ranges we correlate each to | |
// its replacement string, and then find each range's location relation | |
// to every other. For example, 'bob' would be Inside 'xbobx'. | |
let correlatedFoundRanges = []; | |
allSearchResults.forEach(function (correlatedSearchResult) { | |
correlatedSearchResult.searchHits.items.forEach(function (foundRange) { | |
let correlatedFoundRange = { | |
range: foundRange, | |
replacementText: correlatedSearchResult.replacementString, | |
locationRelations: [] | |
} | |
correlatedFoundRanges.push(correlatedFoundRange); | |
}); | |
}); | |
// Two-dimensional loop over the found ranges to find each one's | |
// location relation with every other range. | |
for (let i = 0; i < correlatedFoundRanges.length; i++) { | |
for (let j = 0; j < correlatedFoundRanges.length; j++) { | |
if (i !== j) // Don't need the range's location relation with itself. | |
{ | |
let locationRelation = correlatedFoundRanges[i].range.compareLocationWith(correlatedFoundRanges[j].range); | |
correlatedFoundRanges[i].locationRelations.push(locationRelation); | |
} | |
} | |
} | |
// It is not necesary to *explicitly* call load() for the | |
// LocationRelation objects, but a sync is required to load them. | |
await context.sync(); | |
let nonReplaceableRanges = []; | |
correlatedFoundRanges.forEach(function (correlatedFoundRange) { | |
correlatedFoundRange.locationRelations.forEach(function (locationRelation) { | |
switch (locationRelation.value) { | |
case "Inside": | |
case "InsideStart": | |
case "InsideEnd": | |
// If the range is contained inside another range, | |
// blacklist it. | |
nonReplaceableRanges.push(correlatedFoundRange); | |
break; | |
default: | |
// Leave it off the blacklist, so it will get its | |
// replacement string. | |
break; | |
} | |
}); | |
}); | |
// Do the replacement, but skip the blacklisted ranges | |
correlatedFoundRanges.forEach(function (correlatedFoundRange) { | |
if (nonReplaceableRanges.indexOf(correlatedFoundRange) === -1) { | |
correlatedFoundRange.range.insertText(correlatedFoundRange.replacementText, Word.InsertLocation.replace); | |
} | |
}) | |
await context.sync(); | |
}); | |
} | |
async function setup() { | |
await Word.run(async (context) => { | |
context.document.body.clear(); | |
context.document.body.insertParagraph("{{test}}", "start"); | |
context.document.body.insertParagraph("[[test]]", "end"); | |
context.document.body.insertParagraph("{test}", "end"); | |
context.document.body.insertParagraph("bobb", "end"); | |
context.document.body.insertParagraph("bob", "end"); | |
context.document.body.insertParagraph("ssally", "end"); | |
context.document.body.insertParagraph("sally", "end"); | |
await context.sync(); | |
}); | |
} | |
async function tryCatch(callback) { | |
try { | |
await callback(); | |
} | |
catch (error) { | |
OfficeHelpers.UI.notify(error); | |
OfficeHelpers.Utilities.log(error); | |
} | |
} | |
language: typescript | |
template: | |
content: "\n<div id=\"setup-container\">\n\t<p class=\"ms-font-m\">Choose \"Setup\" to insert sample text into the document.</p>\n <button id=\"setup\" class=\"ms-Button\">\n <span class=\"ms-Button-label\">Setup</span>\n </button>\n</div>\n\n<div id=\"samples-container\">\n\t<p class=\"ms-font-m\">Choose \"Run\" to search/replace text strings in the document.</p>\n <button id=\"run\" class=\"ms-Button\">\n <span class=\"ms-Button-label\">Run</span>\n </button> \n</div>\n" | |
language: html | |
style: | |
content: |4 | |
body { | |
margin: 0; | |
padding: 10px; | |
} | |
/* Button customization, including overwriting some Fabric defaults */ | |
.ms-Button, .ms-Button:focus { | |
background: #217346; | |
border: #217346; | |
} | |
.ms-Button > .ms-Button-label, | |
.ms-Button:focus > .ms-Button-label, | |
.ms-Button:hover > .ms-Button-label { | |
color: white; | |
} | |
.ms-Button:hover, .ms-Button:active { | |
background: #164b2e; | |
} | |
.ms-Button.is-disabled, .ms-Button:disabled { | |
background-color: #f4f4f4; | |
border-color: #f4f4f4; | |
} | |
.ms-Button.is-disabled .ms-Button-label, | |
.ms-Button:disabled .ms-Button-label { | |
color: #a6a6a6; | |
} | |
#setup.ms-Button, #setup.ms-Button:focus { | |
background: darkred; | |
border: darkred; | |
} | |
#setup.ms-Button:hover, #setup.ms-Button:active { | |
background: red; | |
} | |
#samples-container { | |
margin-top: 20px; | |
} | |
#samples-container .ms-Button { | |
display: block; | |
margin-bottom: 5px; | |
} | |
#samples-container .ms-Button, #setup-container .ms-Button { | |
margin-left: 20px; | |
min-width: 80px; | |
} | |
language: css | |
libraries: |- | |
// Office.js | |
https://appsforoffice.microsoft.com/lib/1/hosted/office.js | |
// NPM libraries | |
jquery@3.1.1 | |
office-ui-fabric-js@1.4.0/dist/js/fabric.min.js | |
office-ui-fabric-js@1.4.0/dist/css/fabric.min.css | |
office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css | |
@microsoft/office-js-helpers@0.7.4/dist/office.helpers.min.js | |
core-js@2.4.1/client/core.min.js | |
// IntelliSense: Use dt~library_name for DefinitelyTyped or URLs to d.ts files | |
@types/office-js | |
@types/jquery | |
@types/core-js | |
@microsoft/office-js-helpers@0.7.4/dist/office.helpers.d.ts |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment