How to set table header background colour using office js - ms-word

I am working on Office JS word addin project. I am creating a table with 4 columns and few rows. I want to set background colour of table header column to RED. How can I achieve this? Below is a sample code I am using for table creation.
function createTable() {
Word.run(function (context) {
var body = context.document.body;
var Table = body.insertTable(2, array.length, Word.InsertLocation.start, [array]);
return context.sync();
})
.catch(errorHandler);
}

Updated answer: To programmatically style a table in Word, use the Table.styles or Table.styleBuiltIn properties. You could also try the TableRow.shadingColor property.

Related

Replace text of current paragraph in MS word Office.js add-in

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.

Check if text selection is in header/footer

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");
}
});
});
}

Insert a line break with inserted text in a Word document

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.

How get parent Range of current Selection in word add-in using JavaScript API

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!

Controller lifecycle: when to call table.autoResizeColumn()

I'm currently using onAfterRendering() hook to auto adjust the layout of a table like this:
onAfterRendering: function() {
var table = this.getView().byId('table');
for (var i = 0; i < table.getColumns().length; i++) {
table.autoResizeColumn(i);
}
}
The result is not usable: all columns are sized 100% of the parent's width.
If I add a simple button to invoke the exact same logic the table gets drawn nicely. It looks like the complete table needs to be present in the DOM before autoResizeColumn() works properly.
My question: is there a suitable hook/event I can use to invoke the resizing once the table is in the document?
You can use the onAfterRendering of the table as suggested and add an if statement with bResized boolean or some kind of counter to prevent the endless loop.
As others have answered you can put add a function to oTable.onAfterRendering but the trick is if you do any rendering in that function it will trigger another rendering event that will again trigger onAfterRendering.
The problem here is where to hang the boolean switch that determine you have done the thing you have done.
One way to get around that is to add some customer data to the table with oTable.addCustomData.
The pattern becomes :
```
oTable.onAfterRendering = function () {
// check the prototype
// read the custom data
var customData = this.getCustomData();
// confirm *your* custom data is in the array (and not some other custom data)
// if not do your rendering operation and then
// set a switch to custom data
this.addCustomData(new sap.ui.core.CustomData({
key: "myRenderingCheck",
value: "true",
"writeToDom": true
}));