getRange : Cannot convert Nan to Class - javascript

I tried parseInt but i really don't know where is the right place to put it in the code :
Here's the code :
function projectTime(QuelProjet) {
var tabUsers = getUsersList();
var ss = SpreadsheetApp.getActive();
var ProjectSheet = ss.getSheetByName("Liste Projets");
for (i = 1; i < 13; i++) {
//Nombre de jours du mois
var date = new Date(i + "/01/" + year);
var numProjects = getProjectNumber();
var currentMonthSheet = getSheetByMonth(tabMonth[i - 1]);
for (l = 0; l < tabUsers.length; l++) {
var firstLine = 1 + (l + 1) * 10 - 10 + (l + 1) * numProjects - numProjects;
Logger.log("Fline " + l + " : " + firstLine);
var QuelPro = parseInt(QuelProjet);
Logger.log("Quelpro : " + QuelPro);
var nbDays = getNbJours(date);
var sommeproject = 0;
var som1 = new Array(1000);
for (k = 1; k < nbDays + 1; k++) {
var Row = parseInt(firstLine + QuelPro);
Logger.log("Row : " + Row + " QuelProjet : " + QuelPro);
var Column = k + 1;
Logger.log("Column : " + Column);
var range = currentMonthSheet.getRange(Row, Column);
som1[k] = range.getValues();
//sommeproject = sommeproject + currentMonthSheet.getRange(firstLine + QuelProjet, k + 1).getValues();
}
}
}
var sommeproject = 1;
sommeproject = sommeproject + som1;
return sommeproject;
}
The problem is in this line :
var range = currentMonthSheet.getRange(Row, Column);
QuelProjet is a argument that I put like an integer in the function* when i call it in the spreadsheet
Thanks for your time

If the error is that cannot convert NaN to class, it means that either variable Row or Column or both are not integers. Your issue comes from Row not being an integer.
Since I don't know what getProjectNumber(), I can't fully debug, but this methodology should let you debug.
Use: Logger.log(typeof(variable_name)) so that you can pinpoint where the issue is.
Log the types of the following variables after defining them: numProjects, firstLine, quelPro, and row.
the logger should log 'number' each time. When it doesn't you've found your error.
If all results are 'number' it's possible that your numbers are not whoel numbers since I don't know what getProjectNumber() returns, and the getRange() function needs whole numbers

Related

Javascript Auto Increment Code not working

I need to generate 1000 images each with different numbers. Doing this is found a script online which works fine, but it doesn't work with 00 in front of the increments.
I can't just add 00 in front of every number because when it hits 10 it's doing 0010 instead of 010 like I want it to.
That means I need to change the code a bit. And it's probably REALLY basic, but I just can't figure it out. There is no log sadly, because I am running the script in Photoshop.
Here is the code I have trouble with. And underneath is the result:
for (var i=1; i <= numImages; i++) {
if(layer.textItem.contents < 10) {
layer.textItem.contents = "00" + i.toString();
} else if(layer.textItem.contents >= 10) {
layer.textItem.contents = "0" + i.toString();
} else {
layer.textItem.contents = i.toString();
}
SavePNG(directory + imageName + '_'+ i +'.png');
};
Any assistance is highly appreciated! I don't need to be fed by a spoon! I need to learn from my mistakes!
Here is the entire code in the script (Forgot to add this, edited afterwards)
var imageName = 'Oppmoteskjema';
var numImages = 15;
function SavePNG(saveFile){
var pngOpts = new ExportOptionsSaveForWeb;
pngOpts.format = SaveDocumentType.PNG
pngOpts.PNG8 = false;
pngOpts.transparency = false;
pngOpts.interlaced = false;
pngOpts.quality = 10;
activeDocument.exportDocument(new File(saveFile),ExportType.SAVEFORWEB,pngOpts);
}
var layer = activeDocument.layers[0];
if (layer.kind == 'LayerKind.TEXT') {
for (var i=1; i <= numImages; i++) {
layer.textItem.contents = i.toString();
var str = "" + i;
var pad = "000";
var ans = pad.substring(0, pad.length - str.length) + str;
SavePNG(directory + imageName + '_'+ ans +'.png');
}
};```
You could try it this way:
for (var i=1; i <= numImages; i++) {
var str = "" + i;
var pad = "000";
var ans = pad.substring(0, pad.length - str.length) + str;
layer.textItem.contents = ans;
SavePNG(directory + imageName + '_'+ ans +'.png');
};
You can change pad template as you wish. The output of this will be:
1 -> 001
97 -> 097
999 -> 999
1234 -> 1234
If you're just trying to manipulate a variable based off the index of the loop then the below would suffice.
for (var i = 1; i <= 1000; i++) {
// Result will be '00' | '0' | ''
const result = i < 10 ? '00' : i < 100 ? '0' : '';
// The result is prepended to the current index
// Aka (001, 010, 100)
const contents = result + i;
// Set the text item object contents to value of contents
layer.textItem.contents = contents;
// Saves the Image
SavePNG(directory + imageName + '_' + contents + '.png');
}
This
i < 10 ? '00' : i < 100 ? '0' : ''
Is a ternary operator btw, it's essentially a shorthand if statement.
You can add the number to a string of zeroes, and then slice the resulting string based on desired length:
var template = "0000";
var num = 0;
var targetNumber = 1000;
for(let i = 0; i <= targetNumber; i++) {
// add i to the template. Javascript will automatically to this type-coerceon since we're adding string + number
let numStr = template + i;
// strip leading zeroes to match the template length
numStr = numStr.slice(numStr.length - template.length);
console.log(numStr);
}

Javascript: Dynamically rendering a list [Beginner]

I'm building a word count tracker and would like to show how many words needed per day to reach a target within 30 days. For example if someone enters in 50,000 as their target, they'll have to complete 1667 words per day. I want to create a list element that would say:
Day 1: 1667
Day 2: 3334
Day 3....etc.
My current plan was to create an array that contained the list elements, but the script seems to be causing the site to break entirely! I'm not sure what's going on here.
let wordsPerDay = 0;
function wordsPerDayF(x) {
wordsPerDay = x / 30;
wordsPerDay = Math.round(wordsPerDay)
document.getElementById('wordsNeeded').innerHTML = wordsPerDay.toString();
};
// Above functions finds the word count needed per day
let milestones = []
let finalMilestones = [];
function createMilestones() {
let newWordCount = wordsPerDay;
for (let w = 1; w <= 30; w++) {
milestones.push(newWordCount)
newWordCount += newWordCount;
};
let count = 1;
for (let z = 0; z = milestones.length; z++) {
finalMilestones.push("Day " + count + ": " + milestones[z]);
count++;
};
};
function final() {
createMilestones();
let str = '<ul>'
finalMilestones.forEach(function(item) {
str += '<li>' + item + '</li>';
});
str += '</ul>';
document.getElementById("wordsNeeded").innerHTML = str;
};
final();
<div id="wordsNeeded"></div>
I'm new to coding, so apologies if this code is rough or hard to understand.
z = milestones.length should be z < milestones.length.
You never call wordsPerDayF().
newWordCount += newWordCount will double the word count each day, but that's not what you really want. You just want to add newWordCount to a total. You can also use w * newWordCount to get the total for each day.
let wordsPerDay = 0;
function wordsPerDayF(x) {
wordsPerDay = x / 30;
wordsPerDay = Math.round(wordsPerDay)
document.getElementById('wordsNeeded').innerHTML = wordsPerDay.toString();
};
// Above functions finds the word count needed per day
let milestones = []
let finalMilestones = [];
function createMilestones() {
let newWordCount = wordsPerDay;
for (let w = 1; w <= 30; w++) {
milestones.push(newWordCount * w)
};
let count = 1;
for (let z = 0; z < milestones.length; z++) {
finalMilestones.push("Day " + count + ": " + milestones[z]);
count++;
};
};
function final() {
wordsPerDayF(50000);
createMilestones();
let str = '<ul>'
finalMilestones.forEach(function(item) {
str += '<li>' + item + '</li>';
});
str += '</ul>';
document.getElementById("wordsNeeded").innerHTML = str;
};
final();
<div id="wordsNeeded"></div>

Storing concatenated numbers as string in a 2D array. Result remains "undefined"

I am a novice programmer. I am creating a 2D battleship game. I have successfully randomised the spawn points of said ships and I have an idea on how to proceed next.
I am using a 2D ship array to store the ships coordinates and the last address in each row would be its status: 0=floats, 1=single hit, 2=two hits and so on. But I ran into a problem and need help. I seem to be unable to store anything to said array. as you can see in my code board[][] works but ship[][] doesn't.
I am having an error in this segment:
var z = 1; //set to 1 for debugging purposes. z is supposed to be the length of each battleship.
ship[c][z] = 1; // for debug only. line to be removed during final iteration
console.log("c z = " + c + " " + z);
console.log("ship c z = " + ship[c][z]);
if(c == 0)
{
for(z = 0; z < 4; z++)// this for loop is for battlehsip. more for loops to be added one for each ship type.
{
console.log("a b = " + a + " " + b);
ship[c][z] = ("" + a + b);
console.log("sketchy array " + ship[c][z]);
a++;
console.log("Z = " + z);
}
}
and this is the console output(trimmed):
Loop start
i = 0
rn = 7
rn = 0
x y =7 0
board x y = 1
Board 7 0
C = 0
rng = 0
VH = 0
c z = 0 1
ship c z = undefined
a b = 7 0
sketchy array undefined
Z = 0
a b = 8 0
sketchy array undefined
Z = 1
a b = 9 0
sketchy array undefined
Z = 2
a b = 10 0
sketchy array undefined
Z = 3
This is my full code. Maybe this will clear out what I am trying to achieve. feel free to correct my existing logic.
var vhposition = 0;
var x = 0;
var y = 0;
var guess;
var guesses
var fsunk;
var userchoices = [];
var board = [];
var ship = []; //ship array. converted to 2D array to hold ship status and X
Y coordinates.
function createboard()
{
for (var i = 0; i < 10; i++)
{
board[i] = [];
}
return board;
}
function fleet()
{
for(var i = 0; i < 10; i ++)
ship[i] = [];
}
function rng() //Generates Random Numbers
{
var rn = Math.floor(Math.random() * 10);
console.log("rn = " + rn);
return rn;
}
function rngesus()
{
var rng = Math.floor(Math.random() * 2);
console.log("rng = " + rng);
return rng;
}
function play() // onclick function
{
console.log("game start");
bhit = 0; //battleship hit counter set to zero
c1hit = 0; //cruiser hit counter set to zero
//console.log("sunk array = " + sunk[0] + " " + sunk[1]);
fsunk = 0; //fleet status
createboard();
fleet();
var i = 0;
while(i < 10) // generates random points for ship spawn
{
ship[i] = 0; //overkill to ensure no residual data
console.log("Loop start"); //makes reading console easier
console.log("i = " + i);
spawn(i); //i acts as the ship id that is being worked on
i++;
}
//game();
}
function spawn(j) // ship positon generated, i think
{
x = rng();
y = rng();
console.log("x y =" + x +" "+ y);
board[x][y] = 1;
console.log(" board x y = " + board[x][y]);
position(x, y, j);
}
function position(a,b,c)
{
console.log("Board " + a + " " + b);
console.log("C = " + c);
vhposition = rngesus(); //returns 0 or 1 for ship orienetation. maybe later will add 4 way
console.log("VH = " + vhposition);
var z = 1; //set to 1 for debugging purposes. z is supposed to be the length of each battleship.
ship[c][z] = 1; // for debug only. line to be removed during final iteration
console.log("c z = " + c + " " + z);
console.log("ship c z = " + ship[c][z]);
if(c == 0)
{
for(z = 0; z < 4; z++)// this for loop is for battleship. more for loops to be added one for each ship type.
{
console.log("a b = " + a + " " + b);
ship[c][z] = ("" + a + b);
console.log("sketchy array " + ship[c][z]);
a++;
console.log("Z = " + z);
}
}
}
//function game()
{
//to be continued...
}
function userinput()// this works fine
{
guess = prompt("Enter the grid coordinates. Do not use space. X-coordinates 0-6, Y-coordinates 0-6.");
console.log("users input = " + guess);
while(guess < 0 || guess > 99 || userchoices.includes(guess)) //checks user input for repeated strikes or out of range. Suggest better way if possible. this is just bad code
{
alert("You have entered an invalid coordinate.");
guess = prompt("Try Again!");
}
guesses++; //increments no of guessess
userchoices.push(guess); //add users guess to array
return guess;
}
Sorry for the long question/post.
Thank you.
function position is called from spawn, spawn is called from play and in play you assign 0 to ship[i] ? So the ship is no longer a 2D array.

Can J2V8 execute anonymous function?

I'm trying to execute this piece of javascript code
(function() {
var z = '';
var b = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
for (var i = 0; i < b.length; i += 2) {
z = z + parseInt(b.substring(i, i + 2), 16) + ',';
}
z = z.substring(0, z.length - 1);
eval(eval('String.fromCharCode(' + z + ')'));
})();
but I got this error:
undefined:1: ReferenceError: document is not defined
If I assign the function to a variable, I haven't neither error nor result.
var a = function() {
var z = '';
var b = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
for (var i = 0; i < b.length; i += 2) {
z = z + parseInt(b.substring(i, i + 2), 16) + ',';
}
z = z.substring(0, z.length - 1);
eval(eval('String.fromCharCode(' + z + ')'));
};
Have you got any idea on how run this script with J2V8?
Thank you in advance
I'll be honest, I don't know what the JS is supposed to do. You have an eval wrapped in an eval, and the function has no return statement. Plus, xxxxx doesn't appear to be a valid input.
Having said all that, if I remove the wrapped eval, use a number for the the variable b and return the result, it works fine for me.
#Test
public void testExample2() {
String jsCode = "(function() {\n"
+ "var z = '';\n"
+ "var b = '12345678';\n"
+ "for (var i = 0; i < b.length; i += 2) {\n"
+ " z = z + parseInt(b.substring(i, i + 2), 16) + ',';\n"
+ "}\n"
+ "z = z.substring(0, z.length - 1);\n"
+ "return eval('String.fromCharCode(' + z + ')');\n"
+ "})();";
Object result = v8.executeScript(jsCode);
System.out.println(result);
}

Grade Statistics Calculator

I'd like to get some help on my javascript code. I made a grade statistics calculator that shows results on:
Min – Max student grade
Min – Max student average
Min – Max course grade
Min – Max course average grade
You can access it live here --> http://jsbin.com/qirefe/edit?html,css,js,output and press the "Show Results" button to see my output. (You can change the names and the grades to get a different output)
My problem is that I cannot figure out why it doesn't show the correct course names on the Min - Max course grade, although it displays the grades right. Also I cannot figure out why it calculates wrongly the min and max course average grade and displays the corresponding courses name wrong..
Any help will be very appreciated :)
The .js code:
var Course0 = Array(6);
var Course1 = Array(6);
var Course2 = Array(6);
var Student = Array(6);
var CMap = [Course0, Course1, Course2];
var NMap = ["Course0", "Course1", "Course2"];
var showResults = function () {
var Rows = document.getElementsByClassName("srow");
for (var i = 1; i < Rows.length - 1; i++) {
var values = Rows[i].getElementsByTagName("input");
Student[i - 1] = values[0].value;
for (var j = 1; j < values.length; j++) {
CMap[j - 1][i - 1] = values[j].value;
}
}
var MinID = MaxID = AvgMinID = AvgMaxID = 0;
var Min = Max = AvgMin = AvgMax = undefined;
for (var i = 0; i < Student.length; i++) {
var c0 = Course0[i];
var c1 = Course1[i];
var c2 = Course2[i];
var lessonMin = Math.min(c0, c1, c2);
var lessonMax = Math.max(c0, c1, c2);
if ((lessonMin <= Min) || (typeof Min === "undefined")) {
MinID = i;
Min = lessonMin;
}
if ((lessonMax >= Max) || (typeof Max === "undefined")) {
MaxID = i;
Max = lessonMax;
}
var Avg = Math.avg(c0, c1, c2);
if ((Avg < AvgMin) || (typeof AvgMin === "undefined")) {
AvgMinID = i;
AvgMin = Avg;
}
if ((Avg > AvgMax) || (typeof AvgMax === "undefined")) {
AvgMaxID = i;
AvgMax = Avg;
}
}
var Wrapper = document.getElementById("student-results");
Wrapper.innerHTML = "";
Wrapper.innerHTML += "<span>The Student with lower grade is: " + Student[MinID] + ", Equals To " + Min + "</span>";
Wrapper.innerHTML += "<span>The Student with higher grade is: " + Student[MaxID] + ", Equals To " + Max + "</span>";
Wrapper.innerHTML += "<hr />";
Wrapper.innerHTML += "<span>The Student with lower average grade is: " + Student[AvgMinID] + ", Equals To " + AvgMin + "</span>";
Wrapper.innerHTML += "<span>The Student with higher average grade is: " + Student[AvgMaxID] + ", Equals To " + AvgMax + "</span>";
var CourseMin = CourseMinID = CourseMax = CourseMaxID = CourseAvgMin = CourseAvgMinID = CourseAvgMax = CourseAvgMaxID = 0;
CourseMin = CourseMax = CourseAvgMin = CourseAvgMax = undefined;
for (var i = 0, j = 0; i < Student.length; i++, j += .5) {
var c0 = Course0;
var c1 = Course1;
var c2 = Course2;
var CheckMin = Math.min(c0[i], c1[i], c2[i]);
if (CourseMin > CheckMin || (typeof CourseMin === "undefined")) {
CourseMin = CheckMin;
CourseMinID = i;
}
var CheckMax = Math.max(c0[i], c1[i], c2[i]);
if (CourseMax < CheckMax || (typeof CourseMax === "undefined")) {
CourseMax = CheckMax;
CourseMaxID = parseInt(j);
}
var Avg = Math.avg(c0[i], c1[i], c2[i]);
if (Avg < CourseAvgMin || (typeof CourseAvgMin === "undefined")) {
CourseAvgMin = Avg;
CourseAvgMinID = j;
}
if (Avg > CourseAvgMax || (typeof CourseAvgMax === "undefined")) {
CourseAvgMax = Avg;
CourseAvgMaxID = parseInt(j);
}
}
console.log(CourseMaxID);
Wrapper.innerHTML += "<hr />";
Wrapper.innerHTML += "<span>The Course with lower grade have: " + NMap[CourseMinID] + ", Equals To " + CourseMin + "</span>";
Wrapper.innerHTML += "<span>The Course with higher grade have: " + NMap[CourseMaxID] + ", Equals To " + CourseMax + "</span>";
Wrapper.innerHTML += "<hr />";
Wrapper.innerHTML += "<span>The Course with lower average grade have: " + NMap[CourseAvgMinID] + ", Equals To " + CourseAvgMin + "</span>";
Wrapper.innerHTML += "<span>The Course with higher average grade have: " + NMap[CourseAvgMaxID] + ", Equals To " + CourseAvgMax + "</span>";
return null;
};
Math.avg = function () {
var Avg = 0;
var table = arguments;
for (var i = 0; i < table.length; i++) {
Avg += parseFloat(table[i]);
}
return parseFloat(Avg / table.length);
};
After examining the output of CourseMaxID and CourseMinID in the console, CourseMinID has an index of 3, but NMap only has 3 values (indexed as 0, 1, 2). So I believe this is why, for example, you are seeing:
"The Course with lower grade have: " + NMap[CourseMinID] + ", Equals To " + CourseMin; is undefined -- because the index is out of bounds.
Here's a fix for your issues with CourseMinID and CourseMaxID:
Change the definition of CourseMinID to Math.floor(j)-1;
And change CourseMaxID to be equal to Math.ceil(j);
Your call to parseInt() on a float value didn't appear to be having the intended consequence.
I'm not entirely sure why you're choosing to increment j by 0.5 each time, but from observation I noticed that for CourseMax/CourseMinID, you wanted to use the computations I noted above.
Another note, for the course average values, you are in fact outputting the student's averages. So you will want to change your logic there. It looks to me like you are giving the horizontal row of grades as parameters to the average function:
var Avg = Math.avg(c0[i], c1[i], c2[i]);
That's not what you want to parse in to Avg for course average grades. I would define another Avg function (let's call it newAvg() here) that takes as input a single array (not multiple arguments), and then call Math.Min/Math.Max on newAvg(c0), newAvg(c1), newAvg(c2).
Here's an updated jsbin link with working functionality for course averages. Overview of changes: newAvg() has been defined to take in and operate on one parameter. Keep track of indices of CourseAvgMax and CourseAvgMin. Note that I've removed some of the other operations you had earlier in this jsbin link to make it easier for me to isolate what I was working on. Hope you find it useful!

Categories