Building a word add-in using javascript (office.js) to insert text. So far unformatted text with .insertText. If I would like to insert the below, which function should be used?
formatted text (for instance size, font, style)
Line break
Bullet point
Code:
results.items[i].insertText("Any text going here.", "replace");
How would I for instance insert a line break in the "Any text going here"?
Using JavaScript, add a "line-break" (I'm assuming you mean the same as pressing ENTER in the UI - this is technically a new paragraph) using the string "\n". So, for example:
results.items[i].insertText("Any text going here.\n", "replace");
Use insertBreak for inserting breaks of different types. It could be line break, paragraph break, section break etc.
insertBreak(breakType: Word.BreakType, insertLocation: Word.InsertLocation): void;
For adding lists like bullet points. Use startNewList
startNewList(): Word.List;
List example
//This example starts a new list stating with the second paragraph.
await Word.run(async (context) => {
let paragraphs = context.document.body.paragraphs;
paragraphs.load("$none"); //We need no properties.
await context.sync();
var list = paragraphs.items[1].startNewList(); //Indicates new list to be started in the second paragraph.
list.load("$none"); //We need no properties.
await context.sync();
//To add new items to the list use start/end on the insert location parameter.
list.insertParagraph('New list item on top of the list', 'Start');
let paragraph = list.insertParagraph('New list item at the end of the list (4th level)', 'End');
paragraph.listItem.level = 4; //Sets up list level for the lsit item.
//To add paragraphs outside the list use before/after:
list.insertParagraph('New paragraph goes after (not part of the list)', 'After');
await context.sync();
});
For formatting text, you can get hints by looking at examples here which set Font family and color of text.
//adding formatting like html style
var blankParagraph = context.document.body.paragraphs.getLast().insertParagraph("", "After");
blankParagraph.insertHtml('<p style="font-family: verdana;">Inserted HTML.</p><p>Another paragraph</p>', "End");
// another example using modern Change the font color
// Run a batch operation against the Word object model.
Word.run(function (context) {
// Create a range proxy object for the current selection.
var selection = context.document.getSelection();
// Queue a commmand to change the font color of the current selection.
selection.font.color = 'blue';
// Synchronize the document state by executing the queued commands,
// and return a promise to indicate task completion.
return context.sync().then(function () {
console.log('The font color of the selection has been changed.');
});
})
.catch(function (error) {
console.log('Error: ' + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
console.log('Debug info: ' + JSON.stringify(error.debugInfo));
}
});
The Word addin tutorial has a lot of nifty tricks for common tasks with code samples.
Related
I'm working on a simple office-js Word app, built with the Yeoman Generator. I have a very basic document with the following structure:
1. This is heading one
1.1 This is subheading 1
1.2 This is subheading 2
Some random text here...
Paragraph I want to attach to the list from the beginning of my doc
When I try to attach this last paragraph to my list though, I'm getting the following output:
Word document's screenshot:
It looks as though it's first trying to insert it to the level=1 of that list (thus the initial 3) and then actually inserts it to the root list's position (thus the secondary 2).
The code I'm running looks as follows:
const insertHeading = async (event: Office.AddinCommands.Event) => {
try {
await Word.run(async (context) => {
const selection = context.document.getSelection();
selection.load("paragraphs");
await context.sync();
const lists = context.document.body.lists;
const list = lists.getFirst();
const paragraph = selection.paragraphs.getFirst();
list.load("id");
await context.sync();
paragraph.attachToList(list.id, 0);
await context.sync();
})
} catch (error) {
console.info("Error occurred", error.debugInfo);
} finally {
event.completed();
}
}
I'd expect this paragraph to be added as 2nd item of the root level (with 2.) and without this turquoise strike, shown in the image above.
Any help would be much appreciated!
In a Word add-in, I'm trying to:
receive documentSelectionChanged events,
get the text of the current paragraph, and
replace the string foo with the string bar in the current paragraph.
Everything is working except the last part. The text of the Word document isn't changing.
This is my code:
function updateText() {
var range, foo_range, par;
Word.run(function (context) {
range = context.document.getSelection();
range.paragraphs.load('items');
return context.sync()
.then(function() {
par = range.paragraphs.items[0];
console.log(par.text); // THIS WORKS!
foo_range = par.search('foo');
foo_range.load('items');
})
.then(context.sync)
.then(function() {
console.log(foo_range.items[0].text); // THIS WORKS!
foo_range.items[0].insertText('bar', 'Replace');
// Here, I am trying all the load options I can think of
foo_range.load('items');
foo_range.items[0].load('text');
foo_range.load('text');
range.paragraphs.load('items');
range.paragraphs.load('text');
return context.sync();
});
});
}
Any idea why foo doesn't get replaced by bar in the Word document?
I can't reproduce. Your code works for me on desktop Office 365.
BTW, none of those load calls before the last context.sync do anything, and you should delete them. You only need to load a property (and then sync) when you are going to read the property after the sync. Since you are only writing to the document, you don't need to load anything.
The Word Addin we created allows adding custom comments to text selections. Word does not allow adding comments in headers / footers. Because of that, users should get warned when text in a header/footer is selected.
The selection's OOXML structure for text in body and text in header is identical.
The Word UI itself disabled the review comments section when footer/header text is selected.
When dumping the text selection object to te console, none of the object fields point to the selection being in header/footer.
How can be found out programmatically that text is selected in the header/footer?
Issue: https://github.com/OfficeDev/office-js/issues/341
You can achieve this by looking at the parentBody property of the selection range. The type property on the parentBody will reveal whether the selection is in the 'Header' or elsewhere (see documentation).
Example
function determineSelectionInHeader() {
Word.run(function (context) {
const HEADER_TYPE = "Header";
// Retrieve and load 'type' of selection.
var selection = context.document.getSelection();
var parentBody = selection.parentBody;
parentBody.load("type");
context
.sync()
.then(function () {
if (parentBody.type === HEADER_TYPE) {
console.log("This is the header");
}
});
});
}
I am trying to append a hyperlink immediately following a piece of selected text in Word 2013 using the Shared JS API.
Inserting the hyperlink using OOXML works fine when inserting at current cursor with no selection. My problem is 'finding' the end of the selected text to append the OOXML.
Just using setSelectedDataAsync overwrites the existing text. I have tried reading the selected text as OOXML and concatenating the hyperlink XML to it but without success.
I have not tried reading the current selection and then modifying that OOXML but would prefer to avoid.
In the Word JS API a before and after are provided on the selection so it is straightforward to do. Is it possible to do this in the Shared API? Thanks.
The following code sample illustrates the approach that Marc described in his comment above (with one exception: it gets the selected data as Text, not as HTML).
This snippet uses getSelectedDataAsync to get the selected data (as Text), and then appends a hyperlink to that data and uses setSelectedDataAsync to push that string back into the document (as HTML).
Office.context.document.getSelectedDataAsync(Office.CoercionType.Text,
{ valueFormat: "unformatted" },
function (asyncResult) {
var error = asyncResult.error;
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
console.log(error.name + ": " + error.message);
}
else {
// Get selected data.
var dataValue = asyncResult.value;
console.log("Selected data is: " + dataValue);
// Create newText by appending hyperlink to dataValue.
var myHyperlink = "<a href='https://www.bing.com'>https://www.bing.com</a>";
var newText = dataValue + " " + myHyperlink;
console.log("New text is: " + newText);
// Replace selected text with newText value.
Office.context.document.setSelectedDataAsync(newText, { coercionType: "html" },
function (asyncResult) {
var error = asyncResult.error;
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
console.log(error.name + ": " + error.message);
}
});
}
});
Note: One side-effect of getting the selected data as Text, as this snippet does, is that when you write back that string (with the hyperlink appended) to the document, you'll lose any formatting (for example: font color, style, etc.) that was previously present in the selected text. If it's important that you preserve formatting of the originally selected text, you'll need to get the selected data as HTML and then append your hyperlink to the the portion of HTML which contains the originally selected text, before writing that HTML back to the document.
You can quickly and easily try this code snippet yourself in Word by using Script Lab (https://aka.ms/getscriptlab). Simply install the Script Lab add-in (free), then choose "Import" in the navigation menu, and use the following GIST URL: https://gist.github.com/kbrandl/8e235fb0ccc190bf42ed9ce1874f5559.
I need to insert a paragraph with ContentControl after the current selection paragraph, suppose the current selection is in middle of any paragraph, table or CC, I need to insert a new paragraph with CC after that.
I have tried below code to get the current selection and set range to end of that then will insert the paragraph after it:
var range = context.document.getSelection().getRange("end");
range.insertParagraph("","After");
but it insert the Paragraph after the current Selection, not after current selection parent.
Please advice. Thanks.
What you are observing is by design. You are getting the range of the selection. What you need to do is to get the range of the paragraph and then add another after.
All ranges have a paragraphs collection, the first paragraph will the the paragraph containing the selection, so you can get tit by calling:
context.document.getSelection().paragraphs.getFirst().getRange().insertParagraph("",after");
the full code sample would look like this:
Word.run(async (context) => {
var myParagraph = context.document.getSelection().paragraphs.getFirst().getRange().insertParagraph("", "after")
myParagraph.insertContentControl();
return context.sync();
})
.catch(function (error) {
console.log(error.message)
})
Note: if the selection expands more than one paragraph, probably you would need to do a getLast() instead of a getFirst(), but i am not sure your exact scenario.
thanks!