How can I reference specific cells in Google script to loop, and to return values to specific cells, like the example shown below in VBA.
How would this be written in Google script?
For j = 1 To 20 Step 2
For i = 1 To 20
g = Worksheets("Notes").Cells(i + 15, j + 2).Value
h = Worksheets("Notes").Cells(4, j + 2).Value
l = Worksheets("Notes").Cells(5, j + 2).Value
If Worksheets("Notes").Cells(i + 15, j + 2).Value <> "" Then
etc.
You may use simple for loops in javascript to loop through the cells
//get the sheet object
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Notes');
for(j=0; j<=20; j++){
for(i=0; i<=20; i++){
g = sheet.getRange(i + 15, j + 2).getValue();
//...
//...
//and so on
}
}
this is an example:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Notes');
var lastrow=sheet.getLastRow();
var lastcolumn=sheet.getLastColumn();
//In Google Script you should specify the range you want I/O from
var range=sheet.getRange(1,1,lastcolumn,lastrow);
//Return 2D Array for all range Values
var all = range.getValues();
for(var j=0; j<=20; j++){
for(var i=0; i<=20; i++){
//Return each value
var all = range.getCell(i + 15, j + 2).getValue();
}
}
A Better way is not to call getCell each time as you have already got the data.
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Notes');
var lastrow=sheet.getLastRow();
var lastcolumn=sheet.getLastColumn();
//In Google Script you should specify the range you want I/O from
var range=sheet.getRange(1,1,lastcolumn,lastrow);
//Return 2D Array for all range Values
var values = range.getValues(); //2D array of row and column values
for(var r=0; r < values.length; r++){
for(var c=0; c < values[r].length; c++) {
//Return each value
var value = value[r][c]; //row, column
}
}
Related
I am very new to programming and I am trying to locate two consecutive values within a 1-d array in google sheets and the answers need to be highlighted in bold in the google sheet. The first value should be greater than 5 (located for example in cell D10) and the next value should be less than 4.99 (and located in E10). I have tried two methods but can't seem to get the Code to work - I don't know if I am over-complicating the problem or not. The first method was to make the row into 2 separate arrays of elements so that if element J is greater than 5, and element k (which looks at the element next to J) is less than 4.99.
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var ui2 = SpreadsheetApp.getUi();
var data1 = ss.getRange(10,2,1,20).getValues()[0]; //Variable 1 - to find the ON value B10:U10
var data2 = ss.getRange(10,3,1,20).getValues()[0]; //to find the OFF value;
var onA = 5.00;
var on = data1 > onA;
var offA = 4.99;
var off = data2 < offA;
for(var i = 0; i < 20; i++){
for(var j = 0; j < 20; j++){
if(data1[i] < 5.00 && data2[j] < 4.99){
ss.getRange(10,2,1,20).setValue(data1[i]).setFontSize(12).setFontWeight("bold");
ss.getRange(10,3,1,20).setValue(data2[j]).setFontSize(12).setFontWeight("bold");
break;
}
else {
ui2.alert("the values are not found");
break;
}}}}
My other method was not search the cells as a single array - this works but once I add a message to a else statement to state the values are not found it would repeat this alert for the same number of times as the loop.
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var ui2 = SpreadsheetApp.getUi();
for(var j = 2; j < 22; j++){ // j is column number
for(var k = j+1; k < 23; k++){
var result = ss.getRange(10,j).getValue();
var result2 = ss.getRange(10,k).getValue();
var resulta = result > 5.00;
var resultb = result2 < 4.99;
if (resulta == true && resultb == true) {
ss.getRange(10,j).setValue(result).setFontSize(12).setFontWeight("bold");
ss.getRange(10,k).setValue(result2).setFontSize(12).setFontWeight("bold");
break;
} else {
break;
ui2.alert('Values not found');
}}}}
Any help would be amazing and very greatly appreciated!
Try this:
function findconsecutives() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet1')
const rg=sh.getRange(10,2,1,20);
const vs=rg.getValues()[0];
for(let i=0;i<vs.length-1;i++) {
if(vs[i]<5 && vs[i+1]<4.99) {
sh.getRange(10,i+2,1,2).setFontSize(12).setFontWeight('bold');
break;
}
}
ss.toast('not found');
}
I just changed the fontsize and fontweight to the cells that meet the requirements if you want to change feel free. I don't want to.
I am building a web app which contains a DOM table. This is my code that should create a table from an array:
function create_table() {
var tablediv=document.getElementById('icon-table');
var table = document.createElement("table");
var grid = [[15][15]];
var template = "pixel-{1}-{2}";
table.className = "icon-table";
tablediv.appendChild(table);
for (var i = 0; i < 16; i++) {
var tr = document.createElement("tr");
table.appendChild(tr);
for (var j = 0; j < 16; j++) {
var td = document.createElement("td");
td.className = "icon-pixel";
td.id="pixel-"+ i + "-" + j;
td.style.backgroundColor = "rgb(255,255,255)"; // no dash - css attribute name becomes camelCase
grid[i][j] = td;
td.addEventListener("click", setpixel)
td.addEventListener("mousedown", pinselpixel)
tr.appendChild(td);
}
}
}
The assignment grid[i][j] = td; fails during the first loop iteration.
On the console in my browser the output says:
TypeError: undefined is not an object (evaluating 'grid[i][j] = td')
what am I missing?
There's a couple of problems here. First, you seem to be under the impression that
[[15],[15]]
will create an an array with two sub-arrays, each with 15 keys.
Instead, what that actually gives you is an array with two sub-arrays each containing one key each, with the value 15.
You probably meant this:
[new Array(15), new Array(15)]
Passing an integer to the array constructor creates the slots; passing it to an array literal simply adds that value to the array.
Even then, this approach isn't ideal. Yes, you're containing 15 (actually you presumably meant 16) slots, but they're just undefined slots right now, so this line will fail, since you can't treat undefined as an array:
grid[i][j] = td; //grid[i] == undefined, not an array
Better this (truncated for brevity):
for (var i = 0; i < 16; i++) {
grid[i] = []; //<-- create the row array in the loop
var tr = document.createElement("tr");
table.appendChild(tr);
for (var j = 0; j < 16; j++) {
var td = document.createElement("td");
grid[i][j] = td; //<-- now we can append the column cell
tr.appendChild(td);
}
}
you are trying to loop over an array of array which has 2 elements inside. Each element is (like i said) an array, with a single entry - in your case 15.
Afterwards you are trying to iterate from 0 up to 15.
So your iterations should at first loop over grid array and afterwards over grid's elements up to their length.
but in my opinion it is not necessary to loop over an array here. just do the following:
var myGrid = []
for (var i = 0; i < 16; i++) {
for var k = 0; k < 16; k++) {
//do your stuff
myGrid[i][k] = td
}
}
this should work
The method of intializing the two dimensional array is wrong.
Please use the below method to initialize.
var grid = new Array(15);
for (var i = 0; i < 16; i++) {
grid[i] = new Array(15);
}
First we create the rows of the array (15 rows), then using a for loop we initialize 15 columns for each row. Then the code works fine!
function create_table() {
var tablediv=document.getElementById('icon-table');
var table = document.createElement("table");
var grid = new Array(15);
for (var i = 0; i < 16; i++) {
grid[i] = new Array(15);
}
var template = "pixel-{1}-{2}";
table.className = "icon-table";
tablediv.appendChild(table);
for (var i = 0; i < 16; i++) {
var tr = document.createElement("tr");
table.appendChild(tr);
for (var j = 0; j < 16; j++) {
var td = document.createElement("td");
td.className = "icon-pixel";
td.id="pixel-"+ i + "-" + j;
td.style.backgroundColor = "rgb(255,255,255)"; // no dash - css attribute name becomes camelCase
grid[i][j] = td;
td.addEventListener("click", function(){console.log("clicked");})
td.addEventListener("mousedown", function(){console.log("mousedown");})
tr.appendChild(td);
}
}
}
create_table();
<div id="icon-table"></div>
Your grid initialization is wrong. As mentioned by some comments:
var grid = [[15][15]];
is equivalent to:
const arr = [15]; // array with one element, 15
var grid = arr[15]; // 16th element, which doesn't exist
You probably instead want:
var grid = new Array(15).fill(new Array(15));
Which will give you a two-dimensional array that is 15 "wide" and 15 "tall".
That said, you really don't need to prefill your grid unless it is a requirement for some other reason (like you are printing out a chessboard or something that always has a fixed size).
Can change to this and try it?
var grid = [[15][15]];
to
var grid = [new Array(15), new Array(15)];
I have 4 sheets in my GoogleSheets spreadsheet.
I need the code below to run on every sheet EXCEPT the one called "MRS summary".
I can't seem to get that 'for' loop (the one with the 'g' variable) to work though, because the code only runs for the ACTIVE sheet. But I do know that the Logger.log(g) line is picking up the right indexes...so I think the 'for g' loop is working in the sense that it knows what sheets to look at, but the rest of the code only does what it's supposed to do on the ACTIVE sheet....but I need it to run on every sheet except the one called "MRS summary". Any thoughts?
function SearchCols()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
skip = ['MRS summary'];
for (var g = 0, len3 = sheets.length; g < len3; g++)
{
var name = sheets[g].getName()
if (skip.indexOf(name) > -1) continue;
{
var expen = ss.getSheetByName("MRS summary")
var sheet1 = expen.getRange("A13:A210").getValues();
var searchCol1 = expen.getRange ('B13:B210').getValues();
var searchCol2 = expen.getRange ('A13:A210').getValues();
var searchCol3 = expen.getRange('C13:C210').getValues();
var searchCol4 = expen.getRange('D13:D210').getValues();
var searchCol = ss.getRange('A13:A210').getValues();
var searchVal = ss.getRange('B4').getValue();
for (var i = 0, len = searchCol2.length; i < len; i++)
for (var j = 0, len2 = searchCol1.length; j < len2; j++)
{
if (searchCol2[j][0] == searchVal && searchCol1[j][0] ==
searchCol[i][0])
{
col1[g].getRange(i + 13, 4).setValue(searchCol3[j][0])
col1[g].getRange(i + 13, 5).setValue(searchCol4[j][0])
}
}
}
Logger.log(g);
}
}
I want to display duplicates found from the sheet in a Browser.Msg box and send the duplicate strings via email.
Additionally extra column could be written to that row where status "DUPLICATE - YES" would be written. However just to get it via email / in a popup would be enough.
I have tried logging the data. I have tried setting variables.
function checkDuplicates() {
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange("DATA!F2:F"); // Set Any Range
// "A:A" is for Column A
// And if you want to check duplicates for whole sheet then try this:
// var dataRange = sheet.getDataRange();
var data = dataRange.getValues();
var numRows = data.length;
var numColumns = data[0].length;
var dupes = false;
var okdupes0 = 0;
var nodupes0 = 0;
var totbookings0 = 0;
var formats = [];
var values = [];
for (var i = 0; i < numRows; i++) {
formats[i] = [];
for (var j = 0; j < numColumns; j++) {
formats[i][j] = 'WHITE';
if (data[i][j] != '') {
values.push([data[i][j], i, j]);
}
}
}
var numValues = values.length;
for (var k = 0 ; k < numValues - 1; k++) {
if (formats[values[k][1]][values[k][2]] == 'WHITE') {
for (var l = k + 1; l < numValues; l++) {
if (values[k][0] == values[l][0]) {
formats[values[k][1]][values[k][2]] = 'RED';
formats[values[l][1]][values[l][2]] = 'RED';
var dupes = true;
}
}
var okdupes = okdupes0++;
}
var totbookings = totbookings0++;
}
if (dupes) {
// var okdupes = okdupes -1;
var nodupes = totbookings - okdupes;
var emailAddress = "myemail#gmail.com"; // First column
var message = + nodupes + " Duplicate voucher(s) has been found from the system. Duplicate vouchers has been marked with red color."; // Second column
var subject = "System: " + nodupes + " Duplicate Voucher(s) Found!";
MailApp.sendEmail(emailAddress, subject, message);
Browser.msgBox('Warning!', ''+ nodupes +' Possible duplicate voucher(s) has been found and colored red! Please contact the rep who has made the sale. '+ totbookings +' bookings has been scanned through for duplicates.', Browser.Buttons.OK);
} else {
Browser.msgBox('All good!', 'No duplicate vouchers found.', Browser.Buttons.OK);
}
dataRange.setBackgroundColors(formats);
}
You could convert the array of values to a string, then use match to count occurrences.
This code works to find duplicates, even from a two dimensional array. It doesn't determine what cell the duplicate came from. The values of all the duplicates are put into an array.
function findDups() {
var testArray = [['one','two','three'],['three','four','five']];
var allDataAsString = testArray.toString();
Logger.log('allDataAsString: ' + allDataAsString);
//Create one Dimensional array of all values
var allDataInArray = allDataAsString.split(",");
var pattern;
var arrayOfDups = [];
for (var i = 0;i<allDataInArray.length;i++) {
var tempStr = allDataInArray[i];
// the g in the regular expression says to search the whole string
// rather than just find the first occurrence
var regExp = new RegExp(tempStr, "g");
var count = (allDataAsString.match(regExp) || []).length;
Logger.log('count matches: ' + count);
if (count > 1 && arrayOfDups.indexOf(tempStr) === -1) {
arrayOfDups.push(tempStr);
};
};
Logger.log('arrayOfDups: ' + arrayOfDups);
Browser.msgBox('Thest are the duplicate values: ' + arrayOfDups);
//To Do - Send Email
};
The above example code has a hard coded two dimensional array for testing purposes. There are two occurrences of an element with the value of 'three'.
I'm trying to code a simple piece of javascript that reads in a CSV (pasted into a textarea on a webpage) and generates SQL insert statements but I keep getting undefined values when I reference the 2D array..
Please help!
var ret = "";
//alert("called");
//split the textarea into rows of text
var lines = text.split("\n");
//the first line of text is the table name
var table = lines[0];
//the second line of text is an array of the attribute names
var attrnames = lines[1].split(",");
var values = new Array();
//create a new array for each attribute
for (var i = 0; i < attrnames.length; i++) {
//the length of each array is the total number of rows
//of text - 2 (title row and attr row)
values.push(new Array(lines.length - 2));
}
//for each subsequent row, push the values to the appropriate arrays
for (var i = 2; i < lines.length; i++) {
//get the current row (value, value, value, value)
var thisrow = lines[i].split(",");
for (var j = 0; j < attrnames.length; j++) {
//add the j-th attribute (thisrow[j]) to its array (values[j])
values[j].push(thisrow[j]);
}
}
var insertIntoTable = "";
var tableName = "";
var attrList = "";
var valueList = "";
var lead = "";
//loop through each row
for (var k = 2; k < lines.length; k++) {
// --- ONE STATEMENT ---
//create the statements
insertIntoTable = "insert into table `";
tableName = table;
attrList = "` (";
valueList = "(";
for (var i = 0; i < attrnames.length; i++){
attrList += "`" + attrnames[i] + "`,";
}
//trim the last comma, then add the closing parenthesis.
attrList = attrList.substring(0, attrList.length-1) + ") ";
lead = insertIntoTable + tableName + attrList;
for (var i = 0; i < attrnames.length; i++) {
//this always points to undefined
valueList += "'" + values[i][k-2] + "', ";
}
lead += (" values " + valueList);
lead = lead.substring(0, lead.length-2) + ");\n";
ret += lead;
}
alert(ret);
In JavaScript you do not need to set the length of arrays. They are more like ArrayLists or something; read more at MDN's documentation.
When you do
var x = new Array(10); // array with "length" set to 10
x.push("somevalue");
then the value will be inserted at x[10] - at the end of the list. Log it in the console to see it yourself.
So either you drop the push() and use absolute indizes instead, or initialize the array as empty - best with the array literal syntax: []. The relevant area of your code should then look like this:
//create a new empty array for each attribute
for(var i = 0; i<attrnames.length; i++){
values.push([]);
}
You are making an array of length n, where n is the number of rows, and then you are pushing on n more elements of data. Start with 0 length arrays and you will be fine:
//create a new array for each attribute
for(var i = 0; i<attrnames.length; i++){
values.push(new Array(0)); // or '[]' -> the length of each array **will be** the total number of rows of text-2 (title row and attr row)
}
I would add caution that pasted data will be prone to lots of errors and potential security issues, such as SQL injection attacks. Aside from that, what happens if you have extra \ns at the end of your data? You will end up with more undefined data.