I´m developing an addIn for office (word) and I´m stuck with this problem. I need to assign custom properties to a new document that is going to be opened in a new window/instance.
I´m already using custom properties for documents that are already opened this way:
setProperty(propName, propValue) {
Word.run(context => {
context.document.properties.customProperties.add(propName, propValue);
return context.sync();
}).catch(error => {
if (error instanceof OfficeExtension.Error) {
console.log(
"Error code and message: " + JSON.stringify(error.debugInfo)
);
}
});
}
getFileOverride(attach, file) {
self.getDocumentAsBase64(attach.id).then(data => {
Word.run(context => {
let body = context.document.body;
body.insertFileFromBase64(data, Word.InsertLocation.replace);
return context
.sync()
.then(() => {
self.setProperty("fileId", file.id);
self.setProperty("attachId", attach.id);
})
.then(context.sync)
.catch(error => {
self.updateStatus("Error al obtener el archivo");
if (error instanceof OfficeExtension.Error) {
console.log(
"Error code and message: " + JSON.stringify(error.debugInfo)
);
}
});
}).catch(error => {
if (error instanceof OfficeExtension.Error) {
console.log(
"Error code and message: " + JSON.stringify(error.debugInfo)
);
}
});
});
}
But when I create a new document I don´t know how to achieve this. I´ve tried the following but gives a General Exception error:
getDocumentAsBase64(function(data) {
Word.run(function(context) {
var myNewDoc = context.application.createDocument(data);
context.load(myNewDoc);
return context
.sync()
.then(function() {
myNewDoc.properties.load();
myNewDoc.properties.customProperties.add("custom", "prop");
myNewDoc.open();
})
.then(context.sync)
.catch(function(myError) {
//otherwise we handle the exception here!
updateStatus(myError.message);
});
}).catch(function(myError) {
updateStatus(myError.message);
});
});
I've tried making a function similar to setProperty but it doesn't add the properties:
function setExternalProperty(document, propName, propValue) {
Word.run(context => {
document.properties.load();
document.properties.customProperties.add("custom", "prop");
return context.sync();
}).catch(error => {
if (error instanceof OfficeExtension.Error) {
console.log("Error code and message: " + JSON.stringify(error.debugInfo));
}
});
}
How can I achieve this?
I found the solution, it was quite simple. I change my function to this:
getFileNew(attach, file) {
self.getDocumentAsBase64(attach.id).then(data => {
Word.run(context => {
var myNewDoc = context.application.createDocument(data);
myNewDoc.properties.load();
myNewDoc.properties.customProperties.add("fileId", file.id);
myNewDoc.properties.customProperties.add("fileName", file.name);
myNewDoc.properties.customProperties.add("attachId", attach.id);
myNewDoc.properties.customProperties.add("attachName", attach.name);
myNewDoc.open();
return context.sync()
}).catch(error => {
if (error instanceof OfficeExtension.Error) {
console.log(
"Error code and message: " + JSON.stringify(error.debugInfo)
);
}
});
});
}
SIDENOTE: This only works on desktop version. If you want to open a document in a new window in Office Online you have to omit the customProperties or it´ll throw an exception
Related
I am going to use vonage for text service.
However, only node.js syntax exists, and the corresponding API is being used.
There is a phenomenon that the callback is executed later when trying to receive the values returned from the callback to check for an error.
How can I solve this part? The code is below.
await vonage.message.sendSms(from, to, text, async (err, responseData) => {
if (err) {
console.log('1');
result.message = err;
} else {
if (responseData.messages[0]['status'] === '0') {
console.log('2');
} else {
console.log('3');
result.error = `Message failed with error: ${responseData.messages[0]['error-text']}`;
}
}
});
console.log(result);
return result;
When an error occurs as a result of executing the above code,
result{error:undefined}
3
Outputs are in order.
From what I can understand the issue is that you are passing a async callback. you could simply just give vonage.message.sendSms() a synchronous callback like so.
const result = {};
vonage.message.sendSms(from, to, text, (err, responseData) => {
if (err) {
console.log('1');
result.message = err;
} else {
if (responseData.messages[0]['status'] === '0') {
console.log('2');
} else {
console.log('3');
result.error = `Message failed with error: ${responseData.messages[0]['error-text']}`;
}
}
});
if you want to use async or promises I would suggest something like this
const sendSMS = (from, to, text) => new Promise( (resolve, reject) => {
vonage.message.sendSms(from, to, text, (err, responseData) => {
if (err) {
reject(err);
} else {
resolve(responseData);
}
});
});
// elsewhere
sendSMS(from, to, text)
.then(...)
.catch(...);
I have the below code which is binding to an LDAP server and I want to return the user that I have added "ab" within the "interviewees" group (code taken from ldapjs client api page). I can see I am getting back a response from the server with the expected EventEmitter object. I am expecting to see information about the user when calling logging console.log() on the searchEntry object. I appear to have no searchEntry objects. Is my DN for my user correct? I am currently unsure whether the issue is with my query and I am not getting any data back or whether I am failing to process the response correctly?
const client = ldap.createClient({ url: 'ldap://' + LDAP_SERVER + ':' + LDAP_PORT });
// Connect and bind to the Active Directory.
const connectToClient = async () => {
const secret = LDAP_SECRET_KEY;
return await new Promise((resolve, reject) => {
client.bind(LDAP_USER, secret, function (err, res) {
if (err) {
console.error(err);
reject('Failed to connect to LDAP server');
} else {
resolve('Connected to LDAP server');
}
});
});
};
onst searchADForUser = async () => {
return await new Promise((resolve, reject) => {
client.search('CN=ab,OU=interviewees,OU=Users,OU=interview,DC=interview,DC=workspace,DC=com', function (err, res) {
if (err) {
console.error(err);
reject('Error searching LDAP server');
} else {
res.on('searchEntry', function (entry) {
console.log('entry: ' + JSON.stringify(entry.object));
});
res.on('searchReference', function (referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function (err) {
console.error('error: ' + err.message);
});
res.on('end', function (result) {
console.log('status: ' + result.status);
});
resolve(res);
}
});
});
};
const handler = async (event) => {
try {
return responses.success(
await connectToClient().then(async function(event) {
console.log(event);
await searchADForUser().then(function(event) {
console.log(event);
}).catch(function(event) {
console.log(event);
})
}).catch(function(event) {
console.log(event);
})
);
} catch (err) {
console.error(err);
return responses.error(err);
} finally {
client.unbind();
}
};
The active directory structure is below
The central issue I was having was understanding how to process the returned EventEmitter object from the search function. I need to add to an array on each searchEntry event and then return that entry in my resolve callback function only once the end event had occurred. The code above was calling resolve immediately and hence no searchEntry events or the end event had been processed yet.
Code I am now using below:
function (err, res) {
if (err) {
console.error(err);
reject(new Error('Error retrieving users from Active Directory'));
} else {
const entries = [];
res.on('searchEntry', function (entry) {
entries.push(entry);
});
res.on('searchReference', function (referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function (err) {
console.error('error: ' + err.message);
});
res.on('end', function (result) {
console.log('status: ' + result.status);
if (result.status !== 0) {
reject(new Error('Error code received from Active Directory'));
} else {
resolve(entries);
}
});
}
}
Does AWS lambda supports mongoose middleware, I'm using .pre() to check data exists on save.
here is my function call for save
res = new cModel();
res.pre('save', function (next) {
cModel.find({name: company.name}, function (err, docs) {
if (!docs.length){
next();
}else{
console.log('company name exists: ',company.name);
next(new Error("Company Name exists!"));
}
});
}) ;
this is my function call to update
company_model.companySchema.pre('update', function (next) {
try {
cModel.find({ name: { $regex: new RegExp(`^${this.getFilter().name}$` , 'i') }}, function (err, docs) {
try {
if (!docs.length) {
next();
} else {
console.log('company name exists: ', this.getFilter().name);
next(new Error("Company Name exists!"));
}
} catch (e) {
console.error('error in cModel.find: ' + e.message);
}
});
} catch (e) {
console.error('error in pre save : ' + e.message)
}
});
eInside a pre('save',... hook, the reference to the current document is found under this. Here I've replaced company with this in your example.
const schema = new mongoose.Schema({})
schema.pre('save', function (next) {
cModel.find({name: this.name}, function (err, docs) {
if (!docs.length){
next();
} else {
console.log('company name exists: ', this.name);
next(new Error("Company Name exists!"));
}
});
});
const cModel = mongoose.model("cmodel", schema)
This error doesn't have anything to do with lambda, except that the execution environment in lambda seems to be swallowing the error in the async method. To see the error being thrown, you can wrap the contents of your callback in a try {...} catch (e) {...} block and log the error in the catch block:
const schema = new mongoose.Schema({})
schema.pre('save', function (next) {
try {
cModel.find({name: this.name}, function (err, docs) {
try {
if (!docs.length){
next();
} else {
console.log('company name exists: ', this.name);
next(new Error("Company Name exists!"));
}
} catch (e) {
console.error('error in cModel.find: ' + e.message)
}
});
} catch (e) {
console.error('error in pre save : ' + e.message)
}
});
const cModel = mongoose.model("cmodel", schema)
Update
Using .pre('update'... will have this referencing the query, not the document, as the document is never loaded. You can access parts of the query using getFilter() and getUpdate().
Here is an example to check if company exists before making an update:
const schema = new mongoose.Schema({})
schema.pre('update', function (next) {
let newName = this.getUpdate().name;
cModel.find({name: newName }, function (err, docs) {
if (!docs.length){
next();
} else {
console.log('company name exists: ', newName);
next(new Error("Company Name exists!"));
}
});
});
const cModel = mongoose.model("cmodel", schema)
I am trying learn nodejs and stumble upon this error
callback(null, removed);
TypeError: callback is not a function
It is a Steam trade bot, so when it send me an offer, I accept it but after that it crashes. What is wrong?
exports.removeOweNoTitle = (user, callback) => {
let file = 'data/users/' + user + '.json';
if(fs.existsSync(file)) {
let read = fs.createReadStream(file);
let data = "";
read.on('data', (chunk) => {
data += chunk;
});
read.on('end', () => {
let json;
try {
json = JSON.parse(data);
} catch(error) {
return callback(error);
}
let owe = {};
if(json.owe)
owe = json.owe;
else {
callback(null, 0);
return;
}
let removed = 0;
for(let game in owe) {
if(owe[game]) {
removed += owe[game];
owe[game] = 0;
}
}
let write = fs.createWriteStream(file, {flags: 'w'});
exports.clearNotifications(user, () => {
write.write(JSON.stringify(json), (error) => {
if(error)
return callback(error);
write.end();
});
return;
});
write.write(JSON.stringify(json), (error) => {
if(error)
return callback(error);
write.end();
});
write.on("finish", (callback, error) => {
callback(null, removed); //tady nebyl deklarován callback chyběl
});
});
} else {
generateUserFile(user);
callback(new Error('User\'s file is not defined!'), null);
}
}
I have a problem getting the result from a Cloud Function.
This is my Cloud Function:
exports.retrieveTrips = functions.https.onCall((data, context) => {
const uidNumber = context.auth.uid;
var arrayOfResults = new Array();
var idOfFoundDoc;
var query = admin.firestore().collection('Users').where('UID','==', uidNumber);
query.get().then(snapshot =>
{
snapshot.forEach(documentSnapshot =>
{
idOfFoundDoc = documentSnapshot.id;
});
var queryDoc = admin.firestore().collection('Users').doc(idOfFoundDoc).collection('Trips');
queryDoc.get().then(snapshot =>
{
snapshot.forEach(documentSnapshot =>
{
arrayOfResults.push(documentSnapshot.data());
});
console.log('ARRAY: ' , arrayOfResults);
return arrayOfResults;
})
.catch (err =>
{
console.log ('Error adding document: ', err);
});
})
.catch (err => {
//response.send('Error getting documents', err);
console.log ('Error getting documents', err);
});
And this is the code that I have in my application.
#IBAction func RetrieveTripsButton(_ sender: Any)
{
self.functions.httpsCallable("retrieveTrips").call() {(result, error) in
if let error = error as NSError? {
if error.domain == FunctionsErrorDomain
{
let message = error.localizedDescription
print ("Message: " + message)
}
return
}
print ("Result: -> \(type(of: result))")
print("Result.data type: \(type(of: result?.data))");
print ("Result.data -> \(result?.data)")
}
}
And this is the printed result.
Result: -> Optional<FIRHTTPSCallableResult>
Result.data type: Optional<Any>
Result.data -> Optional(<null>)
The console log is able to print arrayOfResults correctly. Furthermore, when I change this functions to onRequest and feed it the relevant information, the res.status(200).send(arrayOfResults) is able to display the array of JSON in the page.
If I placed the return arrayOfResults; outside of the .then function, I would get a result along with an empty array. My issue is similar to this problem here but I'm unable to receive even that when I return { text: "some_data" }; .
Any help would be great, thank you!
You have to chain the different promises and return the result of the promises chain, as follows.
Note that it is actually what the OP explains in his answer to the SO post you mention "The issue was that I forgot to return the actual promise from the cloud function".
exports.retrieveTrips = functions.https.onCall((data, context) => {
const uidNumber = context.auth.uid;
const arrayOfResults = new Array();
let idOfFoundDoc;
const query = admin.firestore().collection('Users').where('UID','==', uidNumber);
return query.get().then(snapshot => { // here add return
snapshot.forEach(documentSnapshot =>
{
idOfFoundDoc = documentSnapshot.id;
});
const queryDoc = admin.firestore().collection('Users').doc(idOfFoundDoc).collection('Trips');
return queryDoc.get(); // here add return and chain with then()
})
.then(snapshot => {
snapshot.forEach(documentSnapshot => {
arrayOfResults.push(documentSnapshot.data());
});
console.log('ARRAY: ' , arrayOfResults);
return { arrayOfResults : arrayOfResults }; //return an object
})
.catch (err => {
console.log ('Error getting documents', err);
//Here you may return an error as per the documentation https://firebase.google.com/docs/functions/callable#handle_errors, i.e. by throwing an instance of functions.https.HttpsError
});
});
I would also suggest that you look at these two videos from the Firebase team, about Cloud Functions and promises: https://www.youtube.com/watch?v=7IkUgCLr5oA and https://www.youtube.com/watch?v=652XeeKNHSk.