How to update spreadsheet values from a variable? - javascript

I've created a function with three parameters (the client, the value I'm looking for in a table, the value new value to update), but until know I don't know how to update the cell with the determined value.
So far, I succeeded to look for the value in the table, but I cannot update the final cell with the value in parameter of the function. What is the way to do that?
async function modif(client, id1, id2)
{
const gsapi = google.sheets({version:'v4',auth: client });
for (i = 0; i < 50; i++)
{
const opt1 = {spreadsheetId: 'XXX', range: 'Sheet1!A' + (3+i)};
let data1 = await gsapi.spreadsheets.values.get(opt1);
if (parseInt(id1) === parseInt(data1.data.values))
{
const opt2 = {
spreadsheetId: 'xxx',
range: 'Sheet1!B' + (3+i),
valueInputOption: 'USER_ENTERED',
resource:{values : id2}
};
let res = await gsapi.spreadsheets.values.update(opt2);
console.log("modifications OK");
return;
}
}
}
I am supposed to have an updated cell, however instead I receive an error message saying : Invalid value at 'data.values'. Error is at the line resource:{values : id2}
Does anyone know how to solve this little error (I guess), I spent 2 hours on this error yesterday without being able to solve it :(
Thanks a lot in advance for your help,

I finally found out what was the problem... When I looked at the documentation here : https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values, I discovered the parameter "values" is an array of arrays...
As a result I only had to change my syntax to goes from : resource:{values : id2} to : resource:{values : [[id2]]}
Cheers,

Related

How can I access multiply nested sub objects in javascript?

I have a larger code which handles and sorts data. In it I want to work with objects to keep it easier and better structured. I have multiple categories and all of them have different nested subobjects, which I have trouble accessing writing/reading.
I searched on the web, w3schools but couldn't find my mistake, so sry for this entry level question!
I wrote a test function to better understand objects!
function test(){
var report, time, name, date, value;
report = 'Income Statement';
time = 'Annually';
name = 'Revenue';
date = '2017';
value = '10000000';
data = {}
data[report] = {}
data[report][time] = {}
data[report][time][name] = {}
data[report][time][name][date] = value;
console.log(data);
}
As to my understanding what this code does is:
-create an empty object data
-create an empty subobject report
-create an empty subsubobject time
-create an empty subsubsubobject name
-gives the subsubsubobject name a key/value pair date:value
(at least that was my intention to do)
First I tried to skip creating empty objects and directly fill data{} with:
data = {}
data[report][time][name][date] = value; but he seems to cannot set properties to this.
So I created like above coded first empty subobjects for all subcategories, is this really necessary or am I falling for a simple syntax mistake?
However he still doesn't log me the desired output which would be:
{ 'Income Statement': { Annually: { Revenue: {2017:10000000} } } }
and instead gives me:
{ 'Income Statement': { Annually: { Revenue: [Object] } } }
Simply put.. what am I doing wrong? :D
Thanks in advance for any kind of help!
Best regards
I don't think you are doing anything wrong. I pasted same code in JS console and it is giving proper result.
Screenshot of console with result of function
Different ways to initialize object
Static Data
let data = {
'Income Statement': {
'Annually': {
'Revenue': {
'2017': '10000000'
}
}
}
}
document.querySelector("#data-result").innerHTML = JSON.stringify(data)
<div id="data-result"></div>
Dynamic Data
var report, time, name, date, value;
report = 'Income Statement';
time = 'Annually';
name = 'Revenue';
date = '2017';
value = '10000000';
let data = {
[report]: {
[time]: {
[name]: {
[date]: value
}
}
}
}
document.querySelector("#object-result").innerHTML = JSON.stringify(data)
<div id="object-result"></div>
You can also consider different ways to store same data.
Example -
let data = [{
report: 'Income Statement'
time: 'Annually'
name: 'Revenue'
date: '2017'
value: '10000000'
}]
So now, if you want data by date in future you can get that by using filter
let data_2017 = data.filter(x => x.date === '2017');
It is correct !! I received { Income Statement: { Annually: { Revenue: {2017:10000000} } } } at console as an output with your given code.
Are u trying to save that data in some variable using test() ??
If yes then you need to use return data at the end of the definition on the function test instead of consol.log(data).

How do I change \" back to " in javascript?

I'm a beginner to Node.js and MySQL so bear with me. The code below is in my routes for my localhost server and the database when saved at first is fine, but when I try to retrieve it and push it back into my database by storing the old one in a new array, it changes the "" to \"\". What I want is for it to be still "".
I've tried looking around the web for ways to change the formatted string quotes from \"\" back to "" but to no avail and I also tried formatting the score from string back to a number but I realized that even if I did that, it would still end up being a string when stored in the database and when I retrieve it, it would be the same.
let { score } = req.body;
let { date } = req.body;
score = Number(score);
var score_date = [score, date];
wMissing.findOne({
raw : true
}).then((missing) => {
var sessionID = missing.testSessionID;
registerPatient.findOne({
where: {
nric : sessionID
},
raw : true
}).then((patient) => {
var height = patient.height;
height = height / 100
var weight = patient.weight;
var bmiVar = (weight / (height * height)).toFixed(2);
// *This is where my problem starts*
if (missing.wMissingScore == null){
var newArray = score_date;
} else {
var newArray = [missing.wMissingScore];
newArray.push(score_date);
}
newArray = JSON.stringify(newArray);
wMissing.update({
bmi: bmiVar,
wMissingScore: newArray,
name: patient.fullname,
nric: sessionID,
datePlayed: date
}, {
where: {
nric: sessionID
}
}).then(() => {
res.redirect('workoutDiets');
}).catch(err => console.log(err));
The expected output is supposed to be [["2","24/7/2019"],["3","24/7/2019"]]
But instead I'm getting ["[\"2\",\"24/7/2019\"]",["3","24/7/2019"]]
I'm still unaware of any method to change back the \"\" to "" instead. can anyone please help me to improve on my code?
Actually, what's happening is that the first element of the array is being stored as a string, if you watch carefully, the second element is written correctly as an array of strings.
The problem is the first element, you're having a special case.
If i understand correctly ´´´missing.wMissingScore´´´ is a pure string
What you can do is:
´´´
if (missing.wMissingScore == null){
var newArray = score_date;
} else {
var formatedMissingScore= missing.wMissingScore.replace("\"", "").replace("[", "").replace("]", "").split(",");
var newArray = [formatedMissingScore];
newArray.push(score_date);
}
´´´
That way you're formatting your first element string so its not text anymore and should match what you are trying to get.
#charlietfl mentioned about JSON.parse() and it worked! I just changed my else statement to
var newArray = [JSON.parse(missing.wMissingScore)];
and it managed to save the score back to what it originally was.

In Firebase when using push() How do I pull the unique ID

I'm attempting to add/remove entries from a Firebase database. I want to list them in a table to be added/modified/removed (front end) but I need a way to uniquely identify each entry in order to modify/remove. Firebase adds a unique identifier by default when using push(), but I didn't see anything referencing how to select this unique identifier in the API documentation. Can this even be done? Should I be using set() instead so I'm creating the unique ID?
I've put this quick example together using their tutorial:
<div id='messagesDiv'></div>
<input type='text' class="td-field" id='nameInput' placeholder='Name'>
<input type='text' class="td-field" id='messageInput' placeholder='Message'>
<input type='text' class="td-field" id='categoryInput' placeholder='Category'>
<input type='text' class="td-field" id='enabledInput' placeholder='Enabled'>
<input type='text' class="td-field" id='approvedInput' placeholder='Approved'>
<input type='Button' class="td-field" id='Submit' Value="Revove" onclick="msgRef.remove()">
<script>
var myDataRef = new Firebase('https://unique.firebase.com/');
$('.td-field').keypress(function (e) {
if (e.keyCode == 13) {
var name = $('#nameInput').val();
var text = $('#messageInput').val();
var category = $('#categoryInput').val();
var enabled = $('#enabledInput').val();
var approved = $('#approvedInput').val();
myDataRef.push({name: name, text: text, category: category, enabled: enabled, approved: approved });
$('#messageInput').val('');
}
});
myDataRef.on('child_added', function(snapshot) {
var message = snapshot.val();
displayChatMessage(message.name, message.text, message.category, message.enabled, message.approved);
});
function displayChatMessage(name, text, category, enabled, approved, ) {
$('<div/>').text(text).prepend($('<em/>').text(name+' : '+category +' : '+enabled +' : '+approved+ ' : ' )).appendTo($('#messagesDiv'));
$('#messagesDiv')[0].scrollTop = $('#messagesDiv')[0].scrollHeight;
};
</script>
Now lets assume I have three rows of data:
fred : 1 : 1 : 1 : test message 1
fred : 1 : 1 : 1 : test message 2
fred : 1 : 1 : 1 : test message 3
How do I go about uniquely identifying row 2?
in the Firebase Database they look like this:
-DatabaseName
-IuxeSuSiNy6xiahCXa0
approved: "1"
category: "1"
enabled: "1"
name: "Fred"
text: "test message 1"
-IuxeTjwWOhV0lyEP5hf
approved: "1"
category: "1"
enabled: "1"
name: "Fred"
text: "test message 2"
-IuxeUWgBMTH4Xk9QADM
approved: "1"
category: "1"
enabled: "1"
name: "Fred"
text: "test message 3"
To anybody finding this question & using Firebase 3+, the way you get auto generated object unique ids after push is by using the key property (not method) on the promise snapshot:
firebase
.ref('item')
.push({...})
.then((snap) => {
const key = snap.key
})
Read more about it in the Firebase docs.
As a side note, those that consider generating their own unique ID should think twice about it. It may have security and performance implications. If you're not sure about it, use Firebase's ID. It contains a timestamp and has some neat security features out of the box.
More about it here:
The unique key generated by push() are ordered by the current time, so the resulting list of items will be chronologically sorted. The keys are also designed to be unguessable (they contain 72 random bits of entropy).
To get the "name" of any snapshot (in this case, the ID created by push()) just call name() like this:
var name = snapshot.name();
If you want to get the name that has been auto-generated by push(), you can just call name() on the returned reference, like so:
var newRef = myDataRef.push(...);
var newID = newRef.name();
NOTE:
snapshot.name() has been deprecated. See other answers.
snapshot.name() has been deprecated. use key instead. The key property on any DataSnapshot (except for one which represents the root of a Firebase) will return the key name of the location that generated it. In your example:
myDataRef.on('child_added', function(snapshot) {
var message = snapshot.val();
var id = snapshot.key;
displayChatMessage(message.name, message.text, message.category, message.enabled, message.approved);
});
To get uniqueID after push() you must use this variant:
// Generate a reference to a new location and add some data using push()
var newPostRef = postsRef.push();
// Get the unique key generated by push()
var postId = newPostRef.key;
You generate a new Ref when you push() and using .key of this ref you can get uniqueID.
As #Rima pointed out, key() is the most straightforward way of getting the ID firebase assigned to your push().
If, however, you wish to cut-out the middle-man, Firebase released a gist with their ID generation code. It's simply a function of the current time, which is how they guarantee uniqueness, even w/o communicating w/ the server.
With that, you can use generateId(obj) and set(obj) to replicate the functionality of push()
Here's the ID function:
/**
* Fancy ID generator that creates 20-character string identifiers with the following properties:
*
* 1. They're based on timestamp so that they sort *after* any existing ids.
* 2. They contain 72-bits of random data after the timestamp so that IDs won't collide with other clients' IDs.
* 3. They sort *lexicographically* (so the timestamp is converted to characters that will sort properly).
* 4. They're monotonically increasing. Even if you generate more than one in the same timestamp, the
* latter ones will sort after the former ones. We do this by using the previous random bits
* but "incrementing" them by 1 (only in the case of a timestamp collision).
*/
generatePushID = (function() {
// Modeled after base64 web-safe chars, but ordered by ASCII.
var PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
// Timestamp of last push, used to prevent local collisions if you push twice in one ms.
var lastPushTime = 0;
// We generate 72-bits of randomness which get turned into 12 characters and appended to the
// timestamp to prevent collisions with other clients. We store the last characters we
// generated because in the event of a collision, we'll use those same characters except
// "incremented" by one.
var lastRandChars = [];
return function() {
var now = new Date().getTime();
var duplicateTime = (now === lastPushTime);
lastPushTime = now;
var timeStampChars = new Array(8);
for (var i = 7; i >= 0; i--) {
timeStampChars[i] = PUSH_CHARS.charAt(now % 64);
// NOTE: Can't use << here because javascript will convert to int and lose the upper bits.
now = Math.floor(now / 64);
}
if (now !== 0) throw new Error('We should have converted the entire timestamp.');
var id = timeStampChars.join('');
if (!duplicateTime) {
for (i = 0; i < 12; i++) {
lastRandChars[i] = Math.floor(Math.random() * 64);
}
} else {
// If the timestamp hasn't changed since last push, use the same random number, except incremented by 1.
for (i = 11; i >= 0 && lastRandChars[i] === 63; i--) {
lastRandChars[i] = 0;
}
lastRandChars[i]++;
}
for (i = 0; i < 12; i++) {
id += PUSH_CHARS.charAt(lastRandChars[i]);
}
if(id.length != 20) throw new Error('Length should be 20.');
return id;
};
})();
You can update record adding the ObjectID using a promise returned by .then() after the .push() with snapshot.key:
const ref = Firebase.database().ref(`/posts`);
ref.push({ title, categories, content, timestamp})
.then((snapshot) => {
ref.child(snapshot.key).update({"id": snapshot.key})
});
If you want to get the unique key generated by the firebase push() method while or after writing to the database without the need to make another call, here's how you do it:
var reference = firebaseDatabase.ref('your/reference').push()
var uniqueKey = reference.key
reference.set("helllooooo")
.then(() => {
console.log(uniqueKey)
// this uniqueKey will be the same key that was just add/saved to your database
// can check your local console and your database, you will see the same key in both firebase and your local console
})
.catch(err =>
console.log(err)
});
The push() method has a key property which provides the key that was just generated which you can use before, after, or while you write to the database.
Use push() to get a new reference and key to get the the unique id of the it.
var ref = FirebaseDatabase.instance.ref();
var newRef = ref.push(); // Get new key
print(newRef.key); // This is the new key i.e IqpDfbI8f7EXABCma1t
newRef.set({"Demo": "Data"}) // Will be set under the above key
How i did it like:
FirebaseDatabase mFirebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference ref = mFirebaseDatabase.getReference().child("users").child(uid);
String key = ref.push().getKey(); // this will fetch unique key in advance
ref.child(key).setValue(classObject);
Now you can retain key for further use..

Unable to update mongoose model

I have a weird issue that is baffling me. I have a model:
var Model = new Schema({
name: String,
variations: Array
});
The variations entry looks like this:
[ {code: '', price: '' }, {code: '', price: '' }]
I need to add a new field - say "color". So I am doing this to batch update:
Model.find().exec(function(err, products) {
if (!err) {
products.forEach(function(p) {
for(var i = p.variations.length - 1; i >= 0; i--) {
p.variations[i]['color'] = 'red';
// This shows all existing variations
// with the new color feed - correct
console.log(p.variations[i]);
}
p.save(function(err) {
if (!err) {
console.log("Success");
} else {
console.log(err);
}
});
});
}
});
However the "color" field is not set - if I go through again and comment out the p.variations[i]['color'] = 'red'; line then it does not show. I can't seem to figure out why it's doing this. I have an onSave event that is triggered correctly so it's saving. I also do not have any check on the variations structure - i.e. there is no code that only allows code and price. I'm obviously missing something but after a couple of hours I ran out of ideas.
When you modify the contents of an untyped Array field like variations, you need to notify Mongoose that you've changed its value by calling markModified(path) on the modified document or a subsequent save() call won't save it. See docs.
for(var i = p.variations.length - 1; i >=0; i--) {
p.variations[i]['color'] = 'red';
}
p.markModified('variations');
p.save(function(err) { ...
You have to use the set function to change a property. The reasoning behind that is that mongoose has to mark the field as modified in order to be saved to the database.
for(var i = p.variations.length - 1; i >=0; i--) {
p.variations[i].set({"color":"red", "code":"herr"});
// or
p.variations[i].set("color":"red");
p.variations[i].set("code":"herr");
}
An alternative would be to change the field's value the old way, without going trought the setter, then manually mark it as modified: p.markModified('variations');
In my opinion you should always use the setter since this is more readable. You can just pass a json object containing all your changes in parameter and it will safely update the fields that you really want to change.

How to encode cookie with javascript/jquery?

I am working on an online shop together with my friend. He set a cookie for me with PHP with the amount of added products to the Cart. The cookie is called "cart", and the variable with the amount of the products is called "items".
And I have to read the cookie and get the value of "cart" back with javascript and print it in the HTML document, but I have no Idea how to use it, can you please help me? I have never worked with cookies or JSON before, but I think it should be done with JSON, can you please explain it to me how it works?
when I do : console.log(document.cookie);
I receive something like this: cart=%7B%22items%22%3A%7B%228%22%3A1%7D%7D;
And I have no idea how to encode it.
Thank you
That is the URL encoded equivalent of {"items":{"8":1}} which is the JSON string you want.
All you have to do is decode it and parse the JSON:
var cart = JSON.parse(decodeURIComponent(document.cookie.cart));
Then logging cart should give you an object with an 'items' property that you can access as needed.
EDIT:
As an example, here's a way to iterate through the items and determine the total number of items and the total of all their quantities.
var items_total = 0,
quantity_total = 0;
for (var prop in cart.items) {
items_total += 1;
quantity_total += cart.items[prop];
}
console.log("Total Items: " + items_total);
console.log("Total Quantities: " + quantity_total);
Looks like you just need to decode it, then you will want to parse/eval it to get a workable object:
var obj, decoded = decodeURIComponent(document.cookie.cart);
if(window.JSON && JSON.parse){
obj = JSON.parse(decoded);
} else {
eval('obj = ' + decoded);
}
// obj == {"items":{"8":1}};

Categories

Resources