Select Random cell that is not Blank - javascript

I am having a problem that my brain cannot figure out.
I have a script that I copied and modified that will Randomly select a cell that is not blank from reassign!A1:A10
in reassign Tab I have a Query that will filter another sheet if a checkbox is ticked
so in reassign!A1:A10 it will depend if how many checkbox are ticked
the output is it only selects the first cell which is A1
Script:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("reassign");
var range = sheet.getRange("A1:A10");
var values = range.getValues();
var newValue = "";
for(var i = 0; i < values.length; i++) {
if(values[i][0] != "") {
newValue = values[i][0];
break;
}
}
sheet.getRange("B2").setValue(newValue);
}
I am running out of ideas. Sorry
Thanks in advance
I tried researching for solutions, but I really can't figure it out.

This Script selects randomly but sometimes it selects blank cells
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("reassign");
var range = sheet.getRange("A1:A10");
var values = range.getValues();
var newValue = values[Math.floor(Math.random()*values.length)][0];
sheet.getRange("B2").setValue(newValue);
}

The explanation that you have provide is not clear to me at all. But perhaps this small change might make a difference.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("reassign");
var range = sheet.getRange("A1:A10");
var values = range.getValues();
var newValue = "";
for(var i = 0; i < values.length; i++) {
if(values[i][0] !== "") {
newValue = values[i][0];
break;
}
}
sheet.getRange("B2").setValue(newValue);
}
Random Selection of non blank values:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("reassign");
var range = sheet.getRange("A1:A10");
var values = range.getValues().flat().filter(e => e);
sheet.getRange("B2").setValue(values[Math.floor(Math.random() * values.length)]);
}

I'm not at the PC right now, but you may try to add this line before var newValue.....:
values = values.filter(function (n) {return (n != "")})

Related

Search and return data using getRange() and getValue

I am trying to create a sheet (using Google Sheets) for our volunteers to search for, update, and/or add mentoring information (javascript).
I started with the option to search (function onSearch) and it appears to work but the information does not appear in the sheet (attached FYI). I'd appreciate help in making this run.
date entry sheet
REVISED:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Form1");
var str = formSS.getRange("D3").getValues()[3]; //Search for info entered in Form1$D3
var datasheet = ss.getSheetByName("TRACKING");
var values = datasheet.getRange(2,1,2); //Datasheet where info will be retrieved
if (values == str) {
var values1 = values.getValues(); //// get the tracking data if it matchs search request
var i = 1;
myFunction().onSearch = i < values.length; i++;
{
var output = datasheet.getRange(); ///retrieve information from the Tracking spreadsheet and
//populate the information in the appropiate cells.
formSS.get("E8").datasheet.getValue(1),
formSS.getRange("E10").getdatasheet.getValue(2),
formSS.getRange("E12").datasheet.getValue(3),
formSS.getRange("E14").datasheet.getValue(4),
formSS.getRange("J8").datasheet.getValue(5),
formSS.getRange("J10").datasheet.getValue(6),
formSS.getRange("J12").datasheet.getValue(7),
formSS.getRange("J14").datasheet.getValue(8);
return }}}
function onSearch() {
var SEARCH_COL_IDX=0;
var RETURN_COL_IDX=0;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Form1");
`` var datasheet = ss.getSheetByName("TRACKING");
var str = formSS.getRange("D3").getValues()[3]; //column Index
var values = ss.getSheetByName("Form1").getDataRange().getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (row[SEARCH_COL_IDX] == str) {
RETURN_COL_IDX = i+1;
var values = [[formSS.getRange("E8").datasheet.getValue(1),
formSS.getRange("E10").getdatasheet.getValue(2),
formSS.getRange("E12").datasheet.setValue(3),
formSS.getRange("E14").datasheet.getValue(4),
formSS.getRange("J8").datasheet.getValue(5),
formSS.getRange("J10").datasheet.getValue(6),
formSS.getRange("J12").datasheet.getValue(7),
formSS.getRange("J14").datasheet.getValue(8)]];
}
}
}
Thanks for responding. No one had the answer, and I even read that what I was asking is not available in Google Sheets. I decided to use the filter function for each cell instead.
B3 is the search field TRACKING!C:C is the sheet to retrieve the
information Tracking!E:E is the matched column to return information.
I am new here and at programming but I hope this helps someone.
=IFERROR(FILTER(TRACKING!C:C,TRACKING!E:E=B3),TRUE)

I need to redefine script on Google Sheets

I need help with this script. Basically is working, but running on the same ranges for the whole sheets ("A4:V50") and I need it to run different ranges in each sheet.
Thanks!
function clearIPs() {
var ss = SpreadsheetApp.getActive();
var allsheets = ss.getSheets();
for (var i = 0; i < 46; i++) {
var sheet = allsheets[i]
sheet.getRange("A4:V50").clearContent();
}
}
Create some type of Settings Objects. For example:
var Settings = {
Sheet1 : "A4:V50",
Sheet2 : "A4:B20"
}
And then in your code you can use this information like so:
for (var i = 0; i < 46; i++) {
var sheet = allsheets[i];
// lets get the right settings for that sheet
var sheetNumber = i + 1;
var range = Settings["Sheet" + sheetNumber];
// if there is no value for that sheet, lets add a default
if( !range ){
range = "A1:B20";
}
// now we can use that reference
sheet.getRange( range ).clearContent();
}

Trying to paste Values from formula Google App Script

This is just a snippet of my code from Google App Script which iterates through each row in columns 1, 2, 3. If an edit is made in column 3, an incremental ID will be generated and a concatenation of the same row and different columns will also be generated - in this case Column D, E, and F. I am struggling with figuring out a way to change the formulas into values. What am I missing here?
// Location format = [sheet, ID Column, ID Column Row Start, Edit Column]
var locations = [
["Consolidated Media Plan",1,9,3]
];
function onEdit(e){
// Set a comment on the edited cell to indicate when it was changed.
//Entry data
var range = e.range;
var col = range.getColumn();
var row = range.getRow();
// Location Data
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
function getNewID(){
function IDrange(){
var dataRange = sheet.getDataRange();
var lastRow = dataRange.getLastRow();
return sheet.getRange(IDrowStart,IDcol,lastRow-IDrowStart).getValues();
};
//Get largest Value in range
function getLastID(range){
var sorted = range.sort();
var lastIDval = sorted[sorted.length-1][0];
return lastIDval;
};
//Stores leading letters and zeroes and trailing letters
function getLettersNzeroes(id){
//Get any letters or zeroes.
var re = new RegExp("^([a-zA-Z0])$");
var letterZero = [];
for(char = 0; char < id.length; char++){
if(re.test(id[char])){
letterZero.push([char,id[char]]);// [[position, letter or zero]]
};
};
// Categorize letters and zeroes into start and end blocks
var startLetterZero = "",
endLetter = "",
len = letterZero.length - 1;
for(j = 0; j < letterZero.length; j++){
if(letterZero[j][0] === j){
startLetterZero += letterZero[j][1];
}else if(letterZero[j][1] !== "0" && letterZero[len][0] - (len - j) == letterZero[j][0]){
endLetter += letterZero[j][1];
};
};
var startNend = {"start":startLetterZero,"end":endLetter};
return startNend;
};
//Gets last id number. Adds 1 an checks to set if its new length is greater than the lastNumber.
function getNewNumber(id){
var removeZero = false;
var lastNum = parseInt(id.replace(/\D/g,''),10);//Remove letters
var newNum = (lastNum+1).toString();
if(lastNum.toString().length !== newNum.length){
var removeZero = true;
};
var newNumSet = {"num":newNum, "removeZero": removeZero};
return newNumSet
};
var lastID = getLastID(IDrange());
var lettersNzeroes = getLettersNzeroes(lastID);
var newNumber = getNewNumber(lastID);
//If the number is 9,99,999,9999 etc we need to remove a zero if it exists.
if(newNumber.removeZero === true && lettersNzeroes.start.indexOf("0") !== -1.0){
lettersNzeroes.start = lettersNzeroes.start.slice(0,-1);
};
//Rejoin everything together
var newID = lettersNzeroes.start +
newNumber.num +
lettersNzeroes.end;
return newID;
};
for(i = 0; i < locations.length; i++){
var sheetID = locations[i][0],
IDcol = locations[i][1],
IDrowStart = locations[i][2],
EditCol = locations[i][3];
var offset = IDcol - EditCol;
var cell = sheet.getActiveCell();
if(sheetID === sheet.getName()){
if(EditCol === col){
//ID Already Exists the editing cell isn't blank.
if(cell.offset(0,offset).isBlank() && cell.isBlank() === false){
var newID = getNewID();
cell.offset(0,offset).setValue(newID);
cell.offset(0,-1).setFormulaR1C1('=concatenate(R[0]C[-1],"_",INDEX(Glossary!K:K,MATCH(R[0]C[2],Glossary!J:J,0)))');
};
};
};
};
};
EDIT:
This is my full code, I have been unsuccessful with trying to retrieve just the values of the formula within the same (i.e, If C9 gets edited, a formula with the values specific to the 9th row should be populated)
Also, I've tried to add an index/match formula to the concatenation formula at the bottom of the code - it works as expected on the google sheets, but when I run it with the script it pastes the correct formula but it returns a #NAME? error message. However, when I copy and paste the exact same formula in the cell, it works perfectly, any idea what could be causing this error?
This works for me. I know it's not exactly the same thing but I didn't have access to getNewId()
function onEdit(e) {
var sh=e.range.getSheet();
if(sh.getName()!='Sheet1')return;
//e.source.toast('flag1');
if(e.range.columnStart==3 && e.range.offset(0,1).isBlank() && e.value) {
//e.source.toast('flag2');
e.range.offset(0,1).setValue(e.value);
e.range.offset(0,2).setFormulaR1C1('=concatenate(R[0]C[-1],"_",R[0]C[-2],"_",R[0]C[-3],"_",R[0]C[-4])');
}
}

Loop through range and set values

I would like to create a loop that goes through the range A1:A150 and sets the cell value to =readmessage(Sheet2!A1) with A1 changing dynamically with each cell. So with A2 it reads, Sheet2! A1.
function storeValue() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange("A1:A150");
for (var i = 1; i < range.length; i++) {
range.setValue("=readMessage(Sheet2!"+range+")");
}
}
This doesn't work, nothing is written into the cells in the range.
I'm guessing it's something to do with range.setValue.
Don't confuse values with formulas. For values there is setValue(value) and for formulas there is setFormula(formula).
By the other hand var range = sheet.getRange("A1:A150"); assigns a Range object to the range variable. To get get it address use getA1Notation()
This should work if I understood you correctly:
function storeValue(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
for (var i = 1; i < 150; i++) {
range = sheet.getRange("A"+i);
range.setValue("=readMessage(Sheet2! A"+i+")");
} }
Otherwise comment below.

How can I change the background color for only the rows that are "true"?

How can I change the background color for only the rows that were (true) as per function checkDate(row) on the originating sheet "Pasco"? Is this possible?
A little bit about the script:
A date range is inputted through function getDateRange(), all rows in sheet "Pasco" is checked for if they meet that date range through function checkDate(row). If it does meet the date range (true), function filterRows() essentially filters the rows from "Pasco" sheet, and moves them over to another sheet "Copy of Pasco".
Another way of asking my question, how can I get a range of all the rows that were "true" in sheet "Pasco". If "Pasco" wasn't sorted by date, this could mean multiple ranges, right? Once I have a range I'd be able to change background easy.
If you are to test the script, please create two sheets, 'Pasco' and 'Copy of Pasco'. In 'Pasco' Starting from row 2, place some dates down column I (column 8). To see the filtering in action. 'Copy of Pasco' will be deleted/created on each run.
Thank you for your time =)
var globalStartDate;
var globalEndDate;
function getDateRange(){
var startui = SpreadsheetApp.getUi();
var startprompt = startui.prompt('Start Date', 'Enter a date in m/d/y format', startui.ButtonSet.OK_CANCEL);
var startdate = new Date(startprompt.getResponseText());
var startdatemilliseconds = startdate.getTime();
Logger.log(startdate);
Logger.log(startdatemilliseconds);
globalStartDate = startdatemilliseconds;
var endui = SpreadsheetApp.getUi();
var endprompt = endui.prompt('End Date', 'Enter a date in m/d/y format', endui.ButtonSet.OK_CANCEL);
var enddate = new Date(endprompt.getResponseText());
var enddatemilliseconds = enddate.getTime();
Logger.log(enddate);
Logger.log(enddatemilliseconds);
globalEndDate = enddatemilliseconds;
}
function checkDate(row) {
Logger.log(row[8].getTime() <= globalEndDate && row[8].getTime() >= globalStartDate);
return (row[8].getTime() <= globalEndDate && row[8].getTime() >= globalStartDate); // Check column H
}
function filterRows() {
var Spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = Spreadsheet.getSheetByName('Pasco');
var sheetdelete = Spreadsheet.getSheetByName('Copy of Pasco');
Spreadsheet.deleteSheet(sheetdelete);
Spreadsheet.setActiveSheet(sheet1);
Spreadsheet.duplicateActiveSheet();
var headers = 1; // # rows to skip
var sheet2 = Spreadsheet.getSheetByName('Copy of Pasco');
var range = sheet1.getDataRange();
var data = range.getValues();
var headerData = data.splice(0,headers); // Skip header rows
getDateRange();
var filteredData = data.filter( checkDate );
var outputData = headerData.concat(filteredData); // Put headers back
Logger.log(filteredData)
sheet2.clearContents(); // Clear content, keep format
// Save filtered values
sheet2.getRange(1, 1, outputData.length, outputData[0].length).setValues(outputData);
}
Sorry I don't have time to read through your code and give you a complete answer but you could just add a loop to go through the sheet and set the background colour of each row with 'true'.
In my script below I assume 'true' is in column A.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var data = sheet.getRange(1, 1, sheet.getLastRow()).getValues();
var lastCol = sheet.getMaxColumns();
for (var i = 0; i < data.length; i ++){
if(data[i][0] == true){
sheet.getRange(i + 1, 1, 1, lastCol).setBackground('Yellow');
}
}
}
EDIT
Insert this code after you call getDateRange() in the filter rows function.
var lastCol = sheet1.getMaxColumns();
for(var i = headers; i < data.length ; i++){
if(data[i][8].getTime() <= globalEndDate && data[i][8].getTime() >= globalStartDate){
sheet1.getRange(i, 1, 1, lastCol).setBackground('Yellow');
}
}
Your filter rows function should now look like this:
function filterRows() {
var Spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = Spreadsheet.getSheetByName('Pasco');
var sheetdelete = Spreadsheet.getSheetByName('Copy of Pasco');
Spreadsheet.deleteSheet(sheetdelete);
Spreadsheet.setActiveSheet(sheet1);
Spreadsheet.duplicateActiveSheet();
var headers = 1; // # rows to skip
var sheet2 = Spreadsheet.getSheetByName('Copy of Pasco');
var range = sheet1.getDataRange();
var data = range.getValues();
var headerData = data.splice(0,headers); // Skip header rows
getDateRange();
var lastCol = sheet1.getMaxColumns();
for(var i = headers; i < data.length ; i++){
if(data[i][8].getTime() <= globalEndDate && data[i][8].getTime() >= globalStartDate){
sheet1.getRange(i + headers, 1, 1, lastCol).setBackground('Yellow');
}
}
var filteredData = data.filter( checkDate );
var outputData = headerData.concat(filteredData); // Put headers back
Logger.log(filteredData)
sheet2.clearContents(); // Clear content, keep format
// Save filtered values
sheet2.getRange(1, 1, outputData.length, outputData[0].length).setValues(outputData);
}

Categories

Resources