I am new to Google Script and i got stuck.
The code below works perfectly, but it takes more than 10 min to loop through all named ranges.
It clears the content of cells, but not the one with green backgrounds.
function deletNoGreenCells() {
var namedRange = ['HaM','BeM','LoM']
for (var k=0; k<namedRange.length; ++k) {
var range=SpreadsheetApp.getActiveSpreadsheet().getRangeByName(namedRange[k])
for( var i = 1; i < range.getNumRows()+1; ++i){
for(var j = 1; j<range.getNumColumns()+1;++j){
if (range.getCell(i, j).getBackground()!= "#93c47d") {
range.getCell(i, j).clearContent()
}}}}}
How can i get this faster?
Cheers!
Thank You Matthew for the link to call getBackgrounds, wich leeds me to this solution:
function deletNoGreenCells() {
var namedRange = ['HaM','BeM','LoM']
for (var k = 0; k < namedRange.length; ++k) {
var range =SpreadsheetApp.getActiveSpreadsheet().getRangeByName(namedRange[k])
var backgrounds = range.getBackgrounds();
for(var i = 0; i < range.getNumRows(); ++i) {
for(var j = 0; j<range.getNumColumns(); ++j) {
if (backgrounds[i][j] != "#93c47d") {
range.getCell(i+1, j+1).clearContent()
}
}
}
}
}
Now it runs only 5 seconds. Thanks!
I haven't tried this, but if you're just clearing the data from the non-green cells you might be able to do this:
Call getData on the range to get an array containing all the values
Call getBackgrounds on the range to get the corresponding array of background colours
Use the backgrounds array to update the data array, blanking out the elements you want to clear
Call setData on the range, passing back the modified array
It seems likely that reading and writing the data in big blocks like this will be quicker.
I need to make a grid that looks like this in javascript using one function:
x---------
xx--------
xxx-------
xxxx------
xxxxx-----
xxxxxx----
xxxxxxx---
xxxxxxxx--
xxxxxxxxx-
xxxxxxxxxx
and this:
x---------
xx--------
xxx-------
xxxx------
xxxxx-----
xxxxx-----
xxxx------
xxx-------
xx--------
x---------
//Build Matrix
function initMatrix(max) {
var myMatrix = [];
var i;
for(i = 0; i < row; i++){
myMatrix.push([]);
var j;
for(j = 0; j < col; j++) {
if(j < max) {
myMatrix[myMatrix.length - 1].push('*');
} else {
myMatrix[myMatrix.length - 1].push('-');
}
}
}
return myMatrix;
}
More of this code can be viewed here
https://jsfiddle.net/0yc7acev/
Thanks in advanced for the help!
Hi I've made you this document that explains how to do this and has both solutions: https://tonicdev.com/tonic/stars-example . Let me know if you have any questions!
Edit: I realized after the fact that you wanted them in a matrix, not a string, so I've made a slight modification to put them in a matrix for you: https://tonicdev.com/tonic/stars-matrix (the old one still shows how to put them all in string).
The solution at the end is just:
function drawStars(starCounts)
{
return starCounts.map(function (starCount)
{
return (new Array(starCount + 1).join("*") +
new Array(lineLength - starCount + 1).join("-")).split("")
});
}
where starCounts is an array.
So I`m working ona simple JS code. We just started to learn about functions.
I need to make a function named "printStars".
I need to take a number from the user and accourding that number print "*".
This is what I did:
<script>
function printStars()
{
var n = Number(prompt("Insert number of stars:","0.."));
for (i = 0; i < n; i++)
{
document.write("*");
}
}
var stars = printStars();
document.write(stars);
</script>
In the end I get my result with a minus of getting "undefined".
I would love to get some help, and an explanation why is keep happening.
Thanks guys!
jsfiddle demo
function printStars(){
var n = prompt("Insert number of stars:","0..");
var stars='';
for (i = 0; i < n; i++){
stars+='*';
}
$('body').html(stars) //jsfiddle does not allow document.write()
//document.write(stars);
}
//call the function
printStars();
You don't need this
document.write(stars);
You just need this:
// This will make you function to be evaluated and
// the code in your function will be executed.
printStars();
function printStars()
{
var n = Number(prompt("Insert number of stars:","0.."));
for (i = 0; i < n; i++)
{
document.write("*");
}
}
printStars();
I am trying to build a simple script to work with a Google Spreadsheet that looks like this:
It shows me which of my clients use which modules of each layer. Each client may use how many modules he wants to.
What I need to do is count how many clients have all the modules installed (or the three layers, it's the same).
I've tried to do this using the built-in functions but have not succeed.
Now I'm trying to do my own function, that looks like this:
function countTotalModByClient(values) {
var quantMod=0;
var quantClient=0;
for (var i=0; i<values.length; i++) {
for(var j=0; j<values.length; j++) {
if(values[i][j]=="X") {
quantMod++;
}
}
if(quantMod==15) { // total number of modules
quantClient++;
}
quantMod=0;
}
return quantClient;
}
But it always return the same result: 0.
At my sheet, I'm calling the function like this: =countTotalModByClient(B3:P6)
P.S.: Sorry about the magic number in the code, I´ll fix this. =)
This should be possible with a standard formula (although maybe a little complex).
=countif(ArrayFormula(MMULT(--(B3:P6="X"), transpose(column(B3:P2)^0))), 15)
should return the number of clients with a count of 15 in their row..
Can you check if that works ?
Or if you prefer a custom function, give this a try:
function countTotalModByClient(values) {
var quantClient = 0;
for (var i = 0; i < values.length; i++) {
if (values[i].countItem("X") === 15) quantClient += 1;
}
return quantClient;
}
Array.prototype.countItem = function (item) {
var counts = {};
for (var i = 0; i < this.length; i++) {
var num = this[i];
counts[num] = counts[num] ? counts[num] + 1 : 1;
}
return counts[item] || 0;
}
Example spreadsheet
I'm really sorry if anything like this has been posted here before but I couldn't find anything, I'm kinda new to the site still!
So for a while now I've been learning a bit about game development through html5 and javascript and I stumbled upon making tileset maps, I now have a tileset and an 2D array that I want to put certain tiles in (the number varies between 6 and 10 in this case).
I figured it could be a cool function to make the map choose between a small set of similar tiles so I don't have to specifically number every tile in the array(just define the type)
The method I have currently is probably the best for being able to define types but I want something that looks a bit cleaner and/or information to why my "cleaner" version dosen't work.
var ground = [
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()]];
function tile() {
var y = (Math.random() * 5 | 0) + 6;
return y;
}
This is the code I've been using so far, I have to edit every element of the code with the tile() function to get a random number in each one, what I wanted to have was something like this:
for (var i = 0 ; i < 15; i++) {
for (var j = 0; j < 9; j++) {
ground[[i],[j]] = (Math.random() * 5 | 0) + 6;
}
}
to fill the array without having to add the function to each spot.
I have a feeling that I'm missing a return function or something along those lines but honestly I have no idea.
You were thinking in the right direction but there are some errors in your code ;)
You have to initialize the array first before you can push elements into it.
And you were counting i++ twice
Javascript
var ground = []; // Initialize array
for (var i = 0 ; i < 15; i++) {
ground[i] = []; // Initialize inner array
for (var j = 0; j < 9; j++) { // i++ needs to be j++
ground[i][j] = (Math.random() * 5 | 0) + 6;
}
}
Maybe even better (reusable)
function createGround(width, height){
var result = [];
for (var i = 0 ; i < width; i++) {
result[i] = [];
for (var j = 0; j < height; j++) {
result[i][j] = (Math.random() * 5 | 0) + 6;
}
}
return result;
}
// Create a new ground with width = 15 & height = 9
var ground = createGround(15, 9);
Here's a quick example. I've created a function that will take in a width and height parameter and generate the size requested. Also I placed your tile function inside generate ground to keep it private, preventing other script from invoking it.
var ground = generateGround(10, 10); //Simple usage
function generateGround(height, width)
{
var ground = [];
for (var y = 0 ; y < height; y++)
{
ground[y] = [];
for (var x = 0; x < width; x++)
{
ground[y][x] = tile();
}
}
return ground;
function tile()
{
return (Math.random() * 5 | 0) + 6;
}
}
http://jsbin.com/sukoyute/1/edit
Try removing the comma from...
ground[[i],[j]] = (Math.random() * 5 | 0) + 6;
...in your 'clean' version. Also, your incrementing 'i' in both for loops:
for (var i = 0 ; i < 15; i++) {
for (var j = 0; j < 9; i++) {
Hopefully these changes make it work for you :)