Problems setting range with Office Javascript from Excel Online Add-In - excel

I am trying set a range of cells an Excel Add-In.
var officeInitialized = new Promise((resolve, reject) => {
Office.initialize = () => {
resolve();
};
});
function setValues(parms) {
return Excel.run((ctx) => {
for (var i = 0; i < parms.ranges.length; i++) {
var addr = parms.ranges[i];
var addrPart = addr.split("!");
var sheet = ctx.workbook.worksheets.getItem(addrPart[0]);
if (sheet == null) {
sheet = ctx.workbook.worksheets.add(addrPart[0]);
sheet.activate();
}
var range = sheet.getRange(addrPart[1]);
range.values = parms.values[i];
}
return ctx.sync()
.catch(function (error) {
console.log("Error: " + error);
if (error instanceof OfficeExtension.Error) {
console.log("Debug info: " + JSON.stringify(error.debugInfo));
}
})
.then(() => {
return {};
});
});
}
function Test() {
console.log("Test called");
setValues({ranges: ["Tabelle1!A1:B2"], "values":[[[1, 2],[3, 4]]]});
}
My function is called. But the range content does not change. The error handler is not called.
What's wrong?

Related

How to get code to execute in order in node.js

I am trying to finish my script, but for some reason i don't know, it refuses to execute in the order i put it in.
I've tried placing a 'wait' function between the JoinRequest update function and the following code, but when run, it acts as if the function call and wait function were the other way round, countering the point of the wait().
const Roblox = require('noblox.js')
var fs = require('fs');
var joinRequests = []
...
function wait(ms) {
var d = new Date();
var d2 = null;
do { d2 = new Date(); }
while(d2-d < ms*1000);
};
...
function updateJReqs() {
Roblox.getJoinRequests(4745601).then((array) => {
var i;
var final = [];
for(i = 0; i < array.length; i++) {
final.push(array[i].username);
};
if(final === '') {
final = '-None';
};
joinRequests = final
console.log('Updated join requests.')
});
}
function check() {
setTimeout(() => {
fs.readFile('Request.txt',encoding = 'utf-8', function(err, data) {
if (err) {
check();
} else {
updateJReqs(); //for some reason this function is executed alongside the below, not before it.
// Tried putting wait(x) in here.
console.log('Request received: ' + data)
var solution = joinRequests
console.log('Fuffiling request with ' + solution)
fufillRequest(solution)
fs.unlink('Request.txt', function(err) {
if(err) throw err;
});
check();
}
});
}, 400)
}
check();
The script is supposed to wait until a file is created (accomplished), update the list of join requests (accomplished) and then create a new file with the list of join requests in(not accomplished).
if I understand your code you work with async code, you need to return a promise in updateJReqs and add a condition of leaving from the function because you have an infinite recursion
function updateJReqs() {
return new Promise(resolve => {
Roblox.getJoinRequests(4745601).then((array) => {
var i;
var final = [];
for(i = 0; i < array.length; i++) {
final.push(array[i].username);
};
if(final === '') {
final = '-None';
};
joinRequests = final
console.log('Updated join requests.')
resolve();
});
}
}
async function check() {
setTimeout(() => {
fs.readFile('Request.txt',encoding = 'utf-8', function(err, data) {
if (err) {
await check();
} else {
await updateJReqs();
// Tried putting wait(x) in here.
console.log('Request received: ' + data)
var solution = joinRequests
console.log('Fuffiling request with ' + solution)
fufillRequest(solution)
fs.unlink('Request.txt', function(err) {
if(err) throw err;
});
// you dont have an exit from your function check();
return 'Success';
}
});
}, 400)
}
check().then(res => console.log(res));

Firebase hosting gives error Error: could not handle the request

I am using firebase hosting for the purpose of getting a google spreadsheet data using node js API. It works well if i fetch 1000 rows but when i fetch 10000, it give me error Error: could not handle the request.
Below is the url with 1000 request
https://us-central1-valuemyplace-1525346661329.cloudfunctions.net/app/spreadsheet
Below is the url with 10000 request
https://us-central1-valuemyplace-1525346661329.cloudfunctions.net/app/test
Here is my code
function listMajors(auth) {
const sheets = google.sheets({version: 'v4', auth});
sheets.spreadsheets.values.get({
spreadsheetId: '1Lpbx-LQQTh-lF2E1lQmPnqZhvT2bWfQ9gxBX-qGBz_M',
range: 'A1:P120933',
//valueRenderOption: 'UNFORMATTED_VALUES'
//majorDimension: 'COLUMNS'
}, (err, {data}) => {
if (err) return console.log('The API returned an error: ' + err);
const rows = data.values;
if (rows.length) {
rows.map((row) => {
const zipObj = (arr1, arr2, obj) => {
if (arr1.length === 0 || arr2.length === 0) { return 0; }
obj[arr1[0]] = arr2[0];
return zipObj(arr1.slice(1), arr2.slice(1), obj);
}
const ress = [];
for (let i = 1; i < rows.length; i++) {
let obj = {};
zipObj(data.values[0], data.values[i], obj);
ress.push(obj);
}
//console.log(res);
firebase.database().ref().set(ress);
res.send(ress);
// console.log(row.length);
});
} else {
console.log('No data found.');
}
});
}
Please help me to solve this problem. Thanks in advance.
I solved by myself using
function listMajors(auth) {
const sheets = google.sheets({version: 'v4', auth});
sheets.spreadsheets.values.get({
spreadsheetId: '1Lpbx-LQQTh-lF2E1lQmPnqZhvT2bWfQ9gxBX-qGBz_M',
range: 'A1:P120933',
//valueRenderOption: 'UNFORMATTED_VALUES'
//majorDimension: 'COLUMNS'
}, (err, {data}) => {
if (err) return console.log('The API returned an error: ' + err);
const rows = data.values;
if (rows.length) {
** //rows.map((row) => {** *Do comment here*
const zipObj = (arr1, arr2, obj) => {
if (arr1.length === 0 || arr2.length === 0) { return 0; }
obj[arr1[0]] = arr2[0];
return zipObj(arr1.slice(1), arr2.slice(1), obj);
}
const ress = [];
for (let i = 1; i < rows.length; i++) {
let obj = {};
zipObj(data.values[0], data.values[i], obj);
ress.push(obj);
}
//console.log(res);
firebase.database().ref().set(ress);
res.send(ress);
// console.log(row.length);
**//});** *Comment Here*
} else {
console.log('No data found.');
}
});
}

GeneralException on multiple edits in a promise chain

In my Excel add-in I want to perform multiple edits on my document sequentially.
I'm using the promise chain to achive this.
Unfortunately I'm getting a GeneralException: An internal error has occurred. from some of my edits.
The following example performs 250 edits and I get something between 20 and 30 GeneralExceptions in each run. (with Office 2016, in Office online it's much worse)
Example:
var promise;
Office.initialize = function (reason) {
// add awesome addin initialize code here
promise = new OfficeExtension.Promise(function (resolve, reject) { resolve(null); });
for (var i = 0; i < 200; i++) {
insertData("Data" + i);
}
}
function insertData(data) {
if (Office.context.requirements.isSetSupported("ExcelApi", "1.0")) {
//insert the data into the spreadsheet
promise = promise.then(function () {
Excel.run(function (ctx) {
var sheet = ctx.workbook.worksheets.getActiveWorksheet();
var range = ctx.workbook.getSelectedRange();
range.getCell(0, 0).values = data;
range.getCell(1, 0).select();
return ctx.sync()
}).catch(function (error) {
addLogEntry(error.message);
});
});
}
else if (Office.context.requirements.isSetSupported("WordApi", "1.0")) {
promise = promise.then(function () {
Word.run(function (ctx) {
var body = ctx.document.body;
var selectedRange = ctx.document.getSelection();
selectedRange.insertText(data + "\n", 'End');
selectedRange.select('End');
return ctx.sync();
}).catch(function (error) {
addLogEntry(error.message);
});
});
}
}
function addLogEntry(message) {
// log message here
}
What am I doing wrong?
Here the stack trace of the error:
"GeneralException: An internal error has occurred.
at Anonymous function (https://appsforoffice.microsoft.com/lib/1/hosted/word-win32-16.01.debug.js:9329:6)
at lib$es6$promise$$internal$$tryCatch (https://appsforoffice.microsoft.com/lib/1/hosted/word-win32-16.01.debug.js:11207:8)
at lib$es6$promise$$internal$$invokeCallback (https://appsforoffice.microsoft.com/lib/1/hosted/word-win32-16.01.debug.js:11217:8)
at lib$es6$promise$$internal$$publish (https://appsforoffice.microsoft.com/lib/1/hosted/word-win32-16.01.debug.js:11193:9)
at lib$es6$promise$asap$$flush (https://appsforoffice.microsoft.com/lib/1/hosted/word-win32-16.01.debug.js:11027:8)"
I have found a solution, but it is not very elegant and VERY slow (especially in office online)
maybe someone can come up with something better? ;)
Here the fixed insertData function:
var isSending = false;
function insertData(data) {
if (!isSending) {
isSending = true;
if (Office.context.requirements.isSetSupported("ExcelApi", "1.0")) {
//insert the data into the spreadsheet
//promise = promise.then(function () {
Excel.run(function (ctx) {
var sheet = ctx.workbook.worksheets.getActiveWorksheet();
var range = ctx.workbook.getSelectedRange();
range.getCell(0, 0).values = data;
range.getCell(1, 0).select();
return ctx.sync()
}).then(function () {
isSending = false;
if (queue.length > 0) {
insertData(queue.splice(0, 1)[0]);
}
}).catch(function (error) {
addLogEntry(error.message);
});
//});
}
else if (Office.context.requirements.isSetSupported("WordApi", "1.0")) {
//promise = promise.then(function () {
Word.run(function (ctx) {
var body = ctx.document.body;
var selectedRange = ctx.document.getSelection();
selectedRange.insertText(data + "\n", 'End');
selectedRange.select('End');
return ctx.sync();
}).then(function () {
isSending = false;
if (queue.length > 0) {
insertData(queue[0]);
queue = queue.splice(0, 1);
}
}).catch(function (error) {
addLogEntry(error.message);
});
//});
}
}
else {
queue.push(data);
}
}

Node js Promises with recursive function

I want to read the all (text) files from a specific directory and it's all subdirecoty recursively.. I am able to read the file and append the result to a global variable. but i want to access the variable at the end of all operation. I am trying with promises but i am unable to access it. please help
var file_path = `C:\\Users\\HP\\Desktop\\test_folder`;
const fs = require('fs');
var final_array = [];
let getFolderTree = function(file_path) {
return new Promise(function(resolve, reject) {
fs.readdir(file_path, function(err, folders) {
if (err) {
console.log("error reading folder :: " + err);
} else {
if (folders.length !== 0) {
for (let i = 0; i < folders.length; i++) {
if (folders[i].endsWith("txt")) {
let text_file_path = file_path + `\\` + folders[i];
fs.readFile(text_file_path, function(error_read, data) {
if (error_read) {
console.log("error reading " + error_read);
} else {
return resolve(final_array.push(data));// want to access final_array at the end of all operations
}
});
} else {
let current_path = file_path + `\\` + folders[i];
getFolderTree(current_path);
}
}
}
}
});
});
}
getFolderTree(file_path).then(function() {
console.log(final_array); // this is not working
});
I think i have found the solution but I am still confused about how it works.
I took reference from another code and able to figure out some how.
var fs = require('fs');
var path = require('path');
let root_path = "C:\\Users\\HP\\Desktop\\test_folder";
function getAllDirectoriesPath(current_path) {
var results = [];
return new Promise(function (resolve, reject) {
fs.readdir(current_path, function (erro, sub_dirs) {
if (erro) {
console.log(error);
} else {
let no_of_subdir = sub_dirs.length;
if (!no_of_subdir) {
return resolve(results);
} else {
sub_dirs.forEach(function (dir) {
dir = path.resolve(current_path, dir);
fs.stat(dir, function (err, stat) {
if (stat && stat.isDirectory()) {
getAllDirectoriesPath(dir).then(function (res) {
results = results.concat(res);
if (!--no_of_subdir) {
resolve(results);
}
});
} else {
fs.readFile(dir, function (err, data) {
results.push(data.toString());
if (!--no_of_subdir) {
resolve(results);
}
});
}
});
});
}
}
});
});
}
getAllDirectoriesPath(root_path).then(function (results) {
console.log(results);
});

Completing loops inside of node.js promises

I am trying to complete a few loops over firebase objects using .forEach and I am also using promises. This isn't working out how I had planned it. My basic problem is that the loops inside of my promises complete well after the promise chain itself completes. Here is my function:
var queue = new Queue(productUpdateQueue, function(data, progress, resolve, reject) {
var incomingUpdateData = data;
var receiptID = incomingUpdateData.receiptID;
var userID = incomingUpdateData.userID;
var oldProductID = incomingUpdateData.oldProductID;
var newProductID = incomingUpdateData.newProductID;
var newReceipt = incomingUpdateData.newReceipt;
var postID = "";
var updateObject = {};
updateObject['usersPrivate/'+userID+'/receipts/'+receiptID+'/items/'+oldProductID] = null;
updateObject['usersPrivate/'+userID+'/receipts/'+receiptID+'/items/'+newProductID] = newReceipt;
clicks.child('VigLink').orderByChild('item').equalTo(oldProductID).once('value', function(cuidSnapshot) {
return cuidSnapshot.forEach(function(cuidSnapshot) {
var cuid = cuidSnapshot.key;
updateObject['clicks/VigLink/'+cuid+'/item'] = newProductID;
console.log('one');
progress(20);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('receipts').child(receiptID).child('items').child(oldProductID).once('value', function(oldSnapshot) {
var data = oldSnapshot.val()
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/items/'+oldProductID] = null
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/items/'+newProductID] = data
if (data != null) {
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/itemIDs/'+newProductID] = now
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/itemIDs/'+oldProductID] = null
};
console.log('two');
progress(40);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('shops').child(oldProductID).once('value', function(oldSnapshot) {
var data = oldSnapshot.val()
updateObject['userReceiptMetrics/'+userID+'/shops/'+oldProductID] = null;
updateObject['userReceiptMetrics/'+userID+'/shops/'+newProductID] = data;
if (data != null) {
updateObject['userReceiptMetrics/'+userID+'/shopIDs/'+newProductID] = now;
updateObject['userReceiptMetrics/'+userID+'/shopIDs/'+oldProductID] = null;
};
console.log('three');
progress(60);
});
}).then(function() {
posts.once('value', function(postSnapshot) {
// use Promise.all and Array#map to wait for all these queries to finish
var allPosts = postSnapshot.val()
var postKeys = Object.keys(allPosts)
return Promise.all(postKeys.map(function(postKey) {
var postID = postKey;
return posts.child(postID).child('items').child(oldProductID).once('value', function(itemSnapshot) {
return itemSnapshot.forEach(function(itemSnapshot) {
var itemData = itemSnapshot.val()
console.log('post snapshot'+ itemData);
updateObject['posts/'+postID+'/items/'+oldProductID] = null
updateObject['posts/'+postID+'/items/'+newProductID] = itemData
});
});
}));
});
}).then(function() {
// Move to next item
return console.log('hey look here'+updateObject['posts/'+postID+'/items/'+newProductID]);
return firebaseRoot.update(updateObject, function(error) {
if (error) {
console.log("Error updating data:", error);
reject()
} else {
progress(100);
// resolve();
console.log('four');
}
});
}).then(function() {
// Move to next item
return console.log('second one'+updateObject['posts/'+postID+'/items/'+newProductID]);
return firebaseRoot.update(updateObject, function(error) {
if (error) {
console.log("Error updating data:", error);
reject()
} else {
progress(100);
// resolve();
console.log('four');
}
});
});
// Finish the task asynchronously
setTimeout(function() {
reject();
}, 10000);
});
And here is the output:
one
two
three
hey look hereundefined
second oneundefined
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
I think I might be using promises incorrectly but I don't know.
I figured out that I should be using Promise.all() in order to wait for my forEach loops to complete. Here is the code I used to solve my problem, enjoy:
var queue = new Queue(productUpdateQueue, function(data, progress, resolve, reject) {
var incomingUpdateData = data;
var receiptID = incomingUpdateData.receiptID;
var userID = incomingUpdateData.userID;
var oldProductID = incomingUpdateData.oldProductID;
var newProductID = incomingUpdateData.newProductID;
var newReceipt = incomingUpdateData.newReceipt;
var postID = "-KZOO0UII67uOmYo6DJh";
var postKeys = [];
var updateObject = {};
updateObject['usersPrivate/'+userID+'/receipts/'+receiptID+'/items/'+oldProductID] = null;
updateObject['usersPrivate/'+userID+'/receipts/'+receiptID+'/items/'+newProductID] = newReceipt;
return clicks.child('VigLink').orderByChild('item').equalTo(oldProductID).once('value', function(cuidSnapshot) {
return cuidSnapshot.forEach(function(cuidSnapshot) {
var cuid = cuidSnapshot.key;
updateObject['clicks/VigLink/'+cuid+'/item'] = newProductID;
progress(10);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('receipts').child(receiptID).child('items').child(oldProductID).once('value', function(oldSnapshot) {
var data = oldSnapshot.val()
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/items/'+oldProductID] = null
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/items/'+newProductID] = data
if (data != null) {
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/itemIDs/'+newProductID] = now
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/itemIDs/'+oldProductID] = null
};
progress(25);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('shops').child(oldProductID).once('value', function(oldSnapshot) {
var data = oldSnapshot.val()
updateObject['userReceiptMetrics/'+userID+'/shops/'+oldProductID] = null;
updateObject['userReceiptMetrics/'+userID+'/shops/'+newProductID] = data;
if (data != null) {
updateObject['userReceiptMetrics/'+userID+'/shopIDs/'+newProductID] = now;
updateObject['userReceiptMetrics/'+userID+'/shopIDs/'+oldProductID] = null;
};
progress(40);
});
}).then(function() {
progress(55);
return posts.orderByChild('receipt').equalTo(receiptID).once('value');
}).then(function(postSnapshot) {
return postSnapshot.forEach(function(post) {
progress(70);
postKeys.push(post.key)
});
}).then(function() {
return Promise.all(postKeys.map(function(postKey) {
return posts.child(postKey).child('items').child(oldProductID).once('value', function(itemSnapshot) {
var itemData = itemSnapshot.val()
updateObject['posts/'+postKey+'/items/'+oldProductID] = null;
updateObject['posts/'+postKey+'/items/'+newProductID] = itemData;
});
})).then(function(results) {
progress(85);
return results;
});
}).then(function() {
return firebaseRoot.update(updateObject, function(error) {
if (error) {
console.log("Error updating data:", error);
reject()
} else {
progress(100);
resolve();
}
});
});
// Finish the task asynchronously
setTimeout(function() {
reject();
}, 10000);
});

Resources