Error when trying to edit created Document with context.application.createDocument - javascript

I am developing an office web addin, and running in Word Online.
I am trying to edit a document that I have created with context.application.createDocument. Here is the code:
Word.run(function (context) {
var myNewDoc = context.application.createDocument(base64);
context.load(myNewDoc);
return context.sync().then(function () {
myNewDoc.body.insertText('Hello World!', 'Start');
myNewDoc.open();
return context.sync();
});
});
I get this error at insertion of text / context.sync():
GeneralException The action isn’t supported in Word Online. Check the
OfficeExtension.Error.debugInfo for more information. statement: var
body=v.body;
Please help.

This error is by design. On the newly created document, you can only call open methods. All others methods are not supported which means you can't operate the newly created document.

Related

Add Checkbox/DropDownList in WORD using Addin JS API

I'm new to WORD ADDIN and I want to add Checkbox/DropDownList in MS WORD using Word Addin and I tried to add using Word.ContentControlType but its not helping. Can anybody tell me or provide any reference regarding it? I'm sharing my code along with the link to the official documentation of WORD ADDIN JAVASCRIPT API.
Thanks.
document.getElementById("btn-1").addEventListener("click", ()=>{
Word.run(function (context) {
var range = context.document.getSelection();
// var myContentControl = range.insertContentControl();
var myContentControl = range.insertContentControl(Word.ContentControlType.checkBox);
myContentControl.tag = 'FirstName';
myContentControl.title = 'FirstName';
myContentControl.cannotEdit = false;
// myContentControl.style = 'Heading 2';
myContentControl.insertText('');
myContentControl.appearance = Word.ContentControlAppearance.boundingBox;
context.load(myContentControl, 'id');
return context.sync().then(function () {});
});
});
https://learn.microsoft.com/en-us/javascript/api/word/word.contentcontroltype?view=word-js-preview
Thank you for reaching us! Checkbox and DropDownList content control are not supported so far by Office JS API to get or operate it. I'd recommend going to Microsoft 365 Developer Platform Ideas Forum and see if this feature has already been requested or request a new feature.

How to extract page numbers from Word document via add-in built using the Word JavaScript API

in Word via an add-in built using the Word Javascript API, I'm trying to read the page number of each location a string of text appears in the document text. E.g. the word "HELP" appears on pages 2, 6, 10 and 45. How can I read the page number?
A stripped down version of the code I have so far is:
async function run() {
await Word.run(async (context) => {
let paragraphs = context.document.body.paragraphs;
paragraphs.load("text"); // WHAT ELSE NEEDS TO BE LOADED TO ALLOW PAGE NO EXTRACTION?
await context.sync();
// loop through document to find text
paragraphs.items.forEach((item) => {
let paragraph = item.text.trim();
if (paragraph.includes("EXAMPLE STRING")) {
let pageNumber = what_goes_here?;
console.log("Text found on page: " + pageNumber);
}
});
});
}
This works fine for finding the text string, but I can't work out how to get the page number (pageNumber in the code above).
I've been through the Word API documentation but can't find anything. I can, for example, where the text is in a list extract the list level by loading the "listItemOrNullObject" object and reading the "listString", but I can't see any way to get the page number.
Any ideas? If this isn't available via the standard Word API (as I'm suspecting) has anyone got any workarounds?
I'd like to do this using JS and the Word API (great cross platform support etc.) and not have to use VBA, C# etc.
Thank you!
Currently there hasn't been such an JS API to return the page number of the selected text. You can post the API request here: https://techcommunity.microsoft.com/t5/microsoft-365-developer-platform/idb-p/Microsoft365DeveloperPlatform
Wenjun

How to use XPath in a newly opened window?

With the code below (intended for a bookmarklet), I am trying to open a new window, look for certain span-elements, and click each of them. However, I cannot access the code of the new window through XPath.
Inserting the code (copy & paste) of the clickElem function directly in the new tab works fine
CORS is not a problem since it's the same domain/subdomain/protocol
I've been also following this answer.
JavaScript:
const w = window.open('https://example.com', 'Example', 'width=500, height=500');
w.clickElem = () => {
const xpath = '//span[text()="Click here"]';
const selectedNodeElements = w.document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);
let currentNode = selectedNodeElements.iterateNext();
while (currentNode) {
currentNode.click();
currentNode = selectedNodeElements.iterateNext();
}
}
setTimeout(w.clickElem, 8000);
When I try to access the text via currentNode.textContent I receive following error:
"Error in protected function: Cannot read properties of null (reading 'textContent')"
Grateful for every hint!
Are you sure you are already inside your tab? I'm thinking about something you need to get the active tab like this one?
I finally found my own mistake after going through my code on and on and coming across this answer. The .iterateNext() didn't work because the context node was wrongly set to document. Instead, it should be w.document to reference the newly opened window.
const selectedNodeElements = w.document.evaluate(xpath, w.document, null, XPathResult.ANY_TYPE, null);

ReportViewer Web Form causes page to hang

I was asked to take a look at what should be a simple problem with one of our web pages for a small dashboard web app. This app just shows some basic state info for underlying backend apps which I work heavily on. The issues is as follows:
On a page where a user can input parameters and request to view a report with the given user input, a button invokes a JS function which opens a new page in the browser to show the rendered report. The code looks like this:
$('#btnShowReport').click(function () {
document.getElementById("Error").innerHTML = "";
var exists = CheckSession();
if (exists) {
window.open('<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>');
}
});
The page that is then opened has the following code which is called from Page_Load:
rptViewer.ProcessingMode = ProcessingMode.Remote
rptViewer.AsyncRendering = True
rptViewer.ServerReport.Timeout = CInt(WebConfigurationManager.AppSettings("ReportTimeout")) * 60000
rptViewer.ServerReport.ReportServerUrl = New Uri(My.Settings.ReportURL)
rptViewer.ServerReport.ReportPath = "/" & My.Settings.ReportPath & "/" & Request("Report")
'Set the report to use the credentials from web.config
rptViewer.ServerReport.ReportServerCredentials = New SQLReportCredentials(My.Settings.ReportServerUser, My.Settings.ReportServerPassword, My.Settings.ReportServerDomain)
Dim myCredentials As New Microsoft.Reporting.WebForms.DataSourceCredentials
myCredentials.Name = My.Settings.ReportDataSource
myCredentials.UserId = My.Settings.DatabaseUser
myCredentials.Password = My.Settings.DatabasePassword
rptViewer.ServerReport.SetDataSourceCredentials(New Microsoft.Reporting.WebForms.DataSourceCredentials(0) {myCredentials})
rptViewer.ServerReport.SetParameters(parameters)
rptViewer.ServerReport.Refresh()
I have omitted some code which builds up the parameters for the report, but I doubt any of that is relevant.
The problem is that, when the user clicks the show report button, and this new page opens up, depending on the types of parameters they use the report could take quite some time to render, and in the mean time, the original page becomes completely unresponsive. The moment the report page actually renders, the main page begins functioning again. Where should I start (google keywords, ReportViewer properties, etc) if I want to fix this behavior such that the other page can load asynchronously without affecting the main page?
Edit -
I tried doing the follow, which was in a linked answer in a comment here:
$.ajax({
context: document.body,
async: true, //NOTE THIS
success: function () {
window.open(Address);
}
});
this replaced the window.open call. This seems to work, but when I check out the documentation, trying to understand what this is doing I found this:
The .context property was deprecated in jQuery 1.10 and is only maintained to the extent needed for supporting .live() in the jQuery Migrate plugin. It may be removed without notice in a future version.
I removed the context property entirely and it didnt seem to affect the code at all... Is it ok to use this ajax call in this way to open up the other window, or is there a better approach?
Using a timeout should open the window without blocking your main page
$('#btnShowReport').click(function () {
document.getElementById("Error").innerHTML = "";
var exists = CheckSession();
if (exists) {
setTimeout(function() {
window.open('<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>');
}, 0);
}
});
This is a long shot, but have you tried opening the window with a blank URL first, and subsequently changing the location?
$("#btnShowReport").click(function(){
If (CheckSession()) {
var pop = window.open ('', 'showReport');
pop = window.open ('<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>', 'showReport');
}
})
use
`$('#btnShowReport').click(function () {
document.getElementById("Error").innerHTML = "";
var exists = CheckSession();
if (exists) {
window.location.href='<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>';
}
});`
it will work.

Triggering a custom event with attributes from a Firefox extension

I have a Firefox extension that modifies the content of the page that the user is looking at. As part of that process the extension needs to trigger a custom event that the extension itself adds to the page source. I am having difficulties passing parameters to that custom event. What am I doing wrong?
Script block inserted into the head of the page:
document.addEventListener("show-my-overlay", EX_ShowOverlay, false, false, true);
function EX_ShowOverlay(e) {
alert('Parameter: ' + e.index);
// ...
}
Code in the extension:
var event = content.document.createEvent("Events");
event.initEvent("show-my-overlay", true, true);
event['index'] = 123;
content.document.dispatchEvent(event);
The event gets triggered successfully, but e.index is undefined.
I managed to get it working by creating an element on the page and then having the event handler find the element and read its attributes, but it didn't feel elegant. I want to do it without the element.
EDIT:
I also tried triggering the event with CustomEvent, but it throws an exception in the handler:
var event = new CustomEvent('show-my-overlay', { detail: { index: 123 } });
content.document.dispatchEvent(event);
function EX_ShowOverlay(e) {
alert('Parameter: ' + e.detail.index);
// ...
}
Permission denied to access property 'detail'
OP has solved their problem using postMessage. For those of us who actually do have to solve it using CustomEvent (being able to specify message types is useful), here's the answer:
Firefox won't allow the page script to access anything in the detail object sent by the content script via CustomEvent unless you clone the event detail into the document first using the Firefox-specific cloneInto() function.
The following does work over here to send an object from the extension to the page:
var clonedDetail = cloneInto({ index: 123 }, document.defaultView);
var event = new CustomEvent('show-my-overlay', { detail: clonedDetail });
document.dispatchEvent(event);
The Mozilla docs have more detail on cloneInto.
You cannot access "expandos" (additional properties defined on a native prototype object) across security boundaries. The security boundary in this case being between the fully privileged chrome (add-on) code and the non-privileged website code.
So you need to pass data using something "standard". The CustomEvent stuff would do, however your code is wrong. You have to call the constructor or initCustomEvent() correctly:
var event = new CustomEvent('show-my-overlay', { detail: { index: 123 } });
content.document.dispatchEvent(event);
Another alternative is the postMessage API.

Categories

Resources