App Script getValue() Returning Empty Strings - javascript

I'm having an issue with my script that I created. I wanted to be able to archive metrics for work on a weekly basis. Everything works as expected, except when I try to pull values from my overview tab.
The cells that I am trying to grab values from are the results of various calculations that give me a good idea of my progress; I at first thought it may have something to do with my use of ARRAYFORMULA.
Here is an example of one of the cells:
=ARRAYFORMULA({
"Total Number of Attempts";
IFERROR(
COUNTA(
Metrics!$F$2:$F
),
0
)
})
In this particular array formula, the formula is typed into cell E21, the "Total Number of Attempts" appears in E21, and I would be pulling the value from E22.
My thought was that since I haven't put any data in the cell myself, the script was treating it like a blank cell and returning an empty string. However, I tested what happens when I do put values in the cell and I get the same empty string returned.
I don't see anything logically wrong with my code, so I must be missing something with the way that Google Sheets/App Script operates. Below, you will find my code for the archiveData() function:
/*
This function will be set up with a trigger
It will run every week, depositing the current values into their correct columns in the
Archive tab.
*/
function archiveData() {
// Grab the sheet names
var archive = SpreadsheetApp.getActive().getSheetByName('Archive');
var data = SpreadsheetApp.getActive().getSheetByName('Overview');
// Get the week number
var d = Utilities.formatDate(new Date(), "GMT", "w");
// Initialize row/column number for sheets to loop through
row = 2;
column = 1;
// Starting at A2, if the cell is filled, advance to the next cell in column
// If not, it will break out of loop and continue
while(archive.getRange(row, column).getValue() != "") {
row++;
}
// Place the week number in Column A
archive.getRange(row, column).setValue(d);
// Add a variable to store a row, column pair
var metric = [];
// Loop through the remaining columns
while(column <= 18) {
var addData = false;
// If the column is already populated, move to the next column
if(archive.getRange(row, column).getValue() != "") {
column++;
} else {
addData = true;
// Use a switch case to select the correct row, column pair for the correct metric on the
// Overview tab
switch(column) {
case 2:
// Total Avg Number of Tracks Missed on First Attempt
metric = [3, 14]; // C14
break;
case 3:
// Total Avg Number of Attempts Per Task
metric = [5, 14]; // E14
break;
case 4:
// Total Avg Number of Tasks Per Week
metric = [7, 14]; // G14
break;
case 5:
// Avg Number of Tracks Missed on First Attempt in Last 5 Tasks
metric = [3, 17]; // C17
break;
case 6:
// Avg Number of Attempts Per Task in Last 5 Tasks
metric = [5, 17]; // E17
break;
case 7:
// Avg Number of Tasks Per Week in Last Two Weeks
metric = [7, 17]; // G17
break;
case 8:
// Total Number of Tracks
metric = [3, 22]; // C22
break;
case 9:
// Total Number of Attempts
metric = [5, 22]; // E22
break;
case 10:
// Total Avg Tracks Per Week
metric = [7, 22]; // G22
break;
case 11:
// Total Number of Tracks in last 5 Attempts
metric = [3, 25]; // C25
break;
case 12:
// Total Number of Attempts in last 5 Tasks
metric = [5, 25]; // E25
break;
case 13:
// Avg Number of Tracks Per Week in Last Two Weeks
metric = [7, 25]; // G25
break;
case 14:
// Total Number of Tracks This Week
metric = [7, 28]; // G28
break;
case 15:
// Longest Task
metric = [5, 31]; // E31
break;
case 16:
// Shortest Task
metric = [5, 34]; // E34
break;
case 17:
// Total Avg Task Time
metric = [7, 31]; // G31
break;
case 18:
// Avg Task Time in Last 5 Attempts
metric = [7, 34]; // G34
break;
// this shouldn't run
default:
"ERROR";
break;
}
}
if(addData) {
console.log(metric[0], metric[1]); // This correctly shows the row, column pair
var metricData = data.getRange(metric[0], metric[1]).getValue();
console.log("metricData: ", metricData); // This shows metricData is an empty string
archive.getRange(row, column).setValue(metricData);
column++;
}
}
}

Related

How do i round a variables value down to a whole number in JS?

I'm creating a calculator that takes weight, location, and quantity as a parameter. I have the prices set as key value pairs, and when a weight is entered it will iterate over the object array, find the key that is equal to it, and display a message of the price using the value. The problem i'm running into is whenever a number is entered that isn't a whole number, nothing is displayed back. The following is my code:
const calculateRate = () => {
let price
let ausWeight = {
1: 19, 2: 25, 3: 25, 4: 28, 5: 28, 6: 31.5, 7: 35, 8: 38.5, 9: 42, 10: 45.5, 11: 49, 12: 52.5, 13: 56, 14: 59.5,
15: 63, 16: 66.5, 17: 70, 18: 73.5, 19: 77, 20: 80.5};
let inputWeight = Object.keys(ausWeight)
let inputValue = Object.values(ausWeight)
let x = Math.floor(weight);
console.log(x)
for (var i = 0; i < inputWeight.length; i++){
if (x === inputWeight[i] && region.value === 'Australia') {
price = `Estimated delivery cost is $${inputValue[i] * quantity}`;
setShowResults(true)
setPrice(price);
}
}
}
As you can see, i'm setting x to equal to weight rounded down with Math.floor(), but i'm not getting an output. You can also see that i'm logging the value of x to the console and it's giving the result i'm expecting when i look at it through dev tools. For context, this is a functional react component, with weight being set by setState().
Any idea's on how to fix this would be appreciated. Thanks.
You simply compare a string with a number.
By using Object.keys, you get an array of strings. But later you take a strict comparing.
To overcome this, you need to convert the string value into a number
x === +inputWeight[i]

print histogram in javascript?

I have a query that checks the size in kb of my mongo collection documents, which looks like this:
db.myCollection.find().forEach(function(obj)
{
var size = Object.bsonsize(obj)
print('document id: ' + obj._id + ' size: ' + size/1024)
});
and it prints:
document id: 57b6e0561a7b8900011bafhr size: 463.248046875
but I want to print an histogram that looks like:
bigger than 100kb -> 1,000,000 docs
bigget than 200kb -> 500,000 docs
bigger than 300kb -> 300,000 docs
...
max doc 750kb
how can I do this in javascript?
You can try something simple, like this:
// an array of 100 random numbers 0-100
var arr = [];
for(var i=0;i<100;i++)
arr.push(Math.random()*100)
// reducing the array to "histogram"
// does not create empty bins
arr.reduce(function(acc,cur){
var k = Math.floor(cur/10)*10; // creates bins of 0-9, 10-19, 20-29,..., 90-99
if (!(k in acc)) acc[k]=0; // creates a bin if neccessary
acc[k]++; // increments the bin
return acc;
},[]);
Output (keys denote bins, values are element counts):
0: 10
10: 12
20: 4
30: 8
40: 8
50: 10
60: 12
70: 12
80: 10
90: 14

What is the answer for this Javascript while statement?

In javascript I came across this code from a tutorial website and the answer that was given was 900 but I have 109 for the answer. Please explain how do you get the answer and what are the steps taken.
var amount = 0;
var i = 1;
while (I<10) {
amount = amount + 100;
I++;
}
alert("The value is:" + amount);
it is indeed 900. btw, your I should be lowercase i in the while loop.
so amount=0 at the start and i=1.
then you enter the while loop if i < 10, which it is cause i=1 at this point.
then the inside of the loop gets executed: amount becomes 100 because 0+100 = 100
then i gets incremented, so i is now 2 and the loop happens again and again til i becomes 10 in which it exits the loop since 10 is not less than 10.
you'll find that this loops "insides" executes 9 times, (adding 100 to the value of amount each time) giving the final total of amount = 900
var amount = 0;
var i = 1;
while (i<10) {
amount = amount + 100;
i++;
}
alert("The value is:" + amount);
You can analyze this by walking through it line by line and listing out the values at each line.
(I'm assuming s/I/i/ - JavaScript is case-sensitive. If it wasn't just a typo or copy/paste error, you will likely get an error.)
Line 1: amount = 0
Line 2: i = 1
Line 3: i<10, so go to line 4.
Line 4: amount = 100, i = 1
Line 5: amount = 100, i = 2
Line 6: i<10, so go to line 4
Line 4: amount = 200, i = 2
Line 5: amount = 200, i = 3
etc., which is how you end up at amount = 900.

Calculating change to a customer

I'm trying to make a function that creates a table to show the amount of change for each currency needed, eg. $50;1 $20;2 50cents;1 and so on. This function I just need to return the amount due, and number of each currency, the table will be displayed in another function.
What's the best way to go about this?
due = $40
values = new Array(100,50,20,10,0.5,0.2,0.1);
function calculateChange(due, values)
The algorithm is very simple: You have an array of banknote and coin denominations, sorted in descending order. Look at the denominations in that order and see how many coins of that denomination you have to give out. Reduce the leftover change accordingly.
Here's one implementation that returns a dictionary whose keys are the denominations and whose values indicate how many items of that denomnation are included in the change. Items ehose value is zero are not included in the dictionary:
function change(amount, coins) {
var res = {};
for (var i = 0; amount > 0 && i < coins.length; i++) {
var value = coins[i];
if (value <= amount) {
res[value] = Math.floor(amount / value);
amount -= value * res[value];
}
}
return res;
}
For example:
c = change(431, [5000, 2000, 1000, 500, 200, 50, 20, 10, 5, 2, 1]);
// c == { 1: 1, 10: 1, 20: 1, 200: 2 }
Note how the coin denominations are given in cents throughout. If you use the more natural-seeming dollar representation, you'll get floating-point numbers and you may run into rounding issues. (Numbers in Javascript are floating-point numbers, but if they represent integers in a certain range, which should suffice for your problem, they are accurate.)

Self adjusting random list

I have a grid of 9 columns by 3 rows (so each column has 3 slots). A minimum of one slot in every column must be marked and no more than 3 can be marked. A mark is represented by a 1,2 or 3 digit.
There must always be 15 marked slots in total. To achieve this I tried the following:
var valueLeft = 15;
while (valueLeft > 0)
{
var ranValue = utils.getRandomInt(1,3);
console.log('slots remaining: ' + (valueLeft - ranValue));
if (ranValue >= valueLeft)
{
ranValue = valueLeft;
}
valueList.push(ranValue);
valueLeft -= ranValue;
}
console.log(valueList);
But this often gives me an array of numbers with less than 9 elements inside. I can see that my logic is flawed but I am pulling my hair out trying to figure out how I can get it to always give a set of 9 elements which all add up to 15.
For example what I might end up with is:
[2, 1, 1, 1, 1, 2, 3, 1, 2, 1]
When what I need for example is:
[2, 2, 1, 1, 1, 1, 3, 2, 2]
or
[2, 2, 1, 2, 1, 1, 3, 2, 1]
and so on.
Any advice appreciated. Feel free to flame me for my poor sense of logic :)
This answer shows a similar approach to many of those already posted, but I feel as though they're making it too complicated. It can be very straightforward:
function pad(list, size) {
var total = list.length;
while (total != size) {
var i = utils.getRandomInt(0, 8);
if (list[i] < 3) {
list[i]++;
total++;
}
}
return list;
}
var valueList = pad(new Array(1,1,1,1,1,1,1,1,1), 15);
You don't need a lot of cases. Just -- as many others have already said -- init the array with 1's. Then, simply add one to random elements (whose value isn't already 3) until the total is 15.
why don't you do this:
start off with an array that looks like this: 1,1,1,1,1,1,1,1,1
then make a function that picks a random number between 0 and 8 6 times.
if the same number has been picked more than twice, skip it and pick a new one
then correlate those 6 numbers to the index of the array and add 1 for each time it picks that number.
var i; var valueList = new Array(1,1,1,1,1,1,1,1,1);
for(i=0;i<6;i++)
{
var ranNum = utils.getRandomInt(0,8);
if(valueList[ranNum]<3) valueList[ranNum]+=1;
else i--;
}
just tested it, changed <=6 to <6 and it's working for me. Good luck!
Following logic should work. You should select a random value (within 1-3) such that choosing that would not lead us to not able to select a random value for further slots.
var gridLeft = 9
var valueLeft = 15
while(gridLeft>0) {
var ranValue
while(true) {
ranValue = utils.getRandomInt(1,3);
if (valueLeft-ranValue > 3*(gridLeft-1))
continue;
else if (valueLeft-ranValue < 1*(gridLeft-1))
continue;
else
break;
}
valueList.push(ranValue);
valueLeft -= ranValue;
gridLeft -= 1
}

Categories

Resources