I have a sheet document, where people will input their name and it will randomly assign them to a group.
My intention was to do it through a button that will request an input and randomly assign a cell. For that i used:
function displayPrompt() {
var ui = SpreadsheetApp.getUi();
var result = ui.prompt("Please enter your name");
Logger.log(result.getResponseText());
}
Now i need to assign that input to a random group and cell in that group in a specific range e.g. (C10:C16, F10:F16, I10:I16), so there are 3 groups each with 6 cells
Any help?
EDIT:
I got close with this script:
function displayPrompt() {
var ui = SpreadsheetApp.getUi();
var result = ui.prompt("Please enter your name");
var response = result.getResponseText();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("E12:G18");
var values = range.getValues();
var rangeGroups = [[], [], []];
var emptyCells = [];
for (var row = 0; row < values.length; row++) {
for (var col = 0; col < values[row].length; col++) {
var cellValue = values[row][col];
if (cellValue == "") {
emptyCells.push([row, col]);
} else {
var group = Math.floor(col / 3);
rangeGroups[group].push(cellValue);
}
}
}
var randomGroup = Math.floor(Math.random() * 3);
var randomCell = Math.floor(Math.random() * emptyCells.length);
var cellCoordinates = emptyCells[randomCell];
range.getCell(cellCoordinates[0], cellCoordinates[1]).setValue(response);
Logger.log(response);
}
But it only fills 2 columns (groups) and then throws an error probably when it wants to fill the 3rd one
Related
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 != "")})
I have a code that I have compiled from some other codes but it is not doing quite what I want. The idea is to cycle through each row searching for a keyword (TRUE) and send an email to the email address listed in column A with the message in column B. Unfortunately, I'm not skilled enough to work this through myself.
function findAndSendMail() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reminder');
var search = "TRUE"
var lastRow = ss.getLastRow();
var range = ss.getRange(1,5,lastRow); //define range for column E
//find all occurrences of "TRUE" in column E and push range to array
var ranges = range.createTextFinder(search).findAll();
var message = '';
//loop through each range
for (i = 0; i < ranges.length; i++) {
var row = ranges[i].getRow();
var lastCol = ss.getLastColumn();
var values = ss.getRange(row, 1, 1, lastCol).getValues(); //get all values for the row
var emailAddress = values[0][0]; //column A
var reminder = values[0][1]; //column B
var sendvalidation = values[0][4]; //column E
if (sendvalidation = true) {
message+=Utilities.formatString("**This is an automated message.**\n\n"+reminder+"\n\n**This is an automated message.**");
}
var subject = 'General Reminder';
if (message) {
MailApp.sendEmail(emailAddress, subject, message);
}
}
}
I want one email for each row with only the information from that row. What I am currently getting is one email with the first row, then another email with the first and second row, then another email with the first, second and third row, etc.
Based on the question, it sounds like you have a spreadsheet and you want it to send the content in col B to the recipient in col A if col E = "TRUE". I'm a bit of a novice myself, but here is how I would approach this situation. What we're doing here is pulling all the data in the spreadsheet into an array, then looping over that array pushing rows into a new array if col E = "TRUE." We then loop over the new array, and send an email for each row with its data.
`function findAndSendMail() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reminder');
var data = ss.getDataRange().getValues();
var emails = [];
for(var i = 0; i < data.length; i ++) {
// Make sure this points at the column you want to check
if(data[i][4] === "TRUE") {
emails.push(data[i]);
}
}
for(var j = 0; j < emails.length; j ++) {
var row = emails[j];
var emailAddress = row[0];
var reminder = row[1];
if(reminder !== "") {
var message = "**This is an automated message.**\n\n"" + reminder + "\n\n**This
is an automated message.**";
var email = {
to: emailAddress,
subject: "General Reminder",
body: message
};
MailApp.sendEmail(email);
}
}
} `
Figured it out on my own. The code I stole from was set up differently, so I was able to get it to work by removing some conditionals.
function findAndSendMail() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reminder');
var search = "TRUE"
var lastRow = ss.getLastRow();
var range = ss.getRange(1,5,lastRow); //define range for column E
//find all occurrences of "TRUE" in column E and push range to array
var ranges = range.createTextFinder(search).findAll();
//loop through each range
for (i = 0; i < ranges.length; i++) {
var row = ranges[i].getRow();
var lastCol = ss.getLastColumn();
var values = ss.getRange(row, 1, 1, lastCol).getValues(); //get all values for the row
var emailAddress = values[0][0]; //column A
var reminder = values[0][1]; //column B
var sendvalidation = values[0][4]; //column E
var message = reminder;
var subject = 'General Reminder';
MailApp.sendEmail(emailAddress, subject, "**This is an automated message.**\n\n"+message+"\n\n**This is an automated message.**");
}
}
So I have this project I am working on where I need to create a Google Form based on names in a Google Sheet. The way it basically needs to flow is for every name in the sheet should be an option as a drop down in section one and then have a section created for each name. When the person selects their name in the first section they should then be sent to the section titled their name. For example, Name 1 should go to the section titled Name 1, Name 2 to Name 2, etc. The code below will create a Google Form and create sections with the names. The issue that arouses is it will not add the names to a drop down list (it will create a drop down list with no options) and will also not set a destination based on the answers. Any thoughts?
function RecommendationForm(){
var form = FormApp.create('FANS Recommendation Form');
form.setTitle('FANS Recommendation Form')
.setConfirmationMessage('Thanks for responding!')//SET CONFIRMATION MESSAGE LATER
.setAllowResponseEdits(false)
.setAcceptingResponses(true);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Teacher and Email List');
var startRow = 2;
var numRows = 200;
var dataRange = sheet.getRange(startRow, 1, numRows, 4)
var data = dataRange.getValues();
var whoAreYou = form.addListItem();
whoAreYou.setTitle('Who are you?')
var nameBreak = []
var nameChoice = []
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var name = row[0];
var recNumber = row[2]
if (name != ""){
if (recNumber != 0){
nameBreak[i] = form.addPageBreakItem().setTitle(name);
nameChoice[i] = name
}}};
whoAreYou.setChoices([
whoAreYou.createChoice(nameChoice,nameBreak)
])
}
You got the syntax of the setChoices function wrong. You need to create an array of choices like so:
var choices = []
choices[i] = whoAreYou.createChoice(name,form.addPageBreakItem().setTitle(name))
Then you can use this array in setChoices method to set all your choices.
whoAreYou.setChoices(choices)
for more details have a look here
Below is the modified code that incorporates these changes,
function RecommendationForm(){
var form = FormApp.create('FANS Recommendation Form');
//var form = FormApp.openByUrl("https://docs.google.com/forms/d/11oaebH_BeFLAkpGjqs5EykqtNxXXaabuVCTk3uuc12s/edit")
form.setTitle('FANS Recommendation Form')
.setConfirmationMessage('Thanks for responding!')//SET CONFIRMATION MESSAGE LATER
.setAllowResponseEdits(false)
.setAcceptingResponses(true);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet9');
var startRow = 2;
var numRows = 10;
var dataRange = sheet.getRange(startRow, 1, numRows, 4)
var data = dataRange.getValues();
var whoAreYou = form.addListItem();
whoAreYou.setTitle('Who are you?')
var nameBreak
var nameChoice
var choices = []
var choiceCounter = 0
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var name = row[0];
var recNumber = row[2]
if (name != ""){
if (recNumber != 0){
nameBreak = form.addPageBreakItem().setTitle(name);
nameChoice = name
choices[choiceCounter] = whoAreYou.createChoice(nameChoice,nameBreak) // Create a array of choices with the navigation item
choiceCounter++; // This counter will be independent of i counter and will be have no breaks.
}}
};
whoAreYou.setChoices(choices) //Set Choices with the choice array.
Logger.log(form.getEditUrl())
Logger.log(form.getPublishedUrl())
}
Hope this helps!
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);
}
Spreadsheet-1: Data present in Spreadsheet-1,
Name apple android windows linux
Germany 3 4 6 7
America 4 1 6 2
Sweden 1 6 1 6
Paris 5 0 2 4
Spreadsheet-2: Data present in Spreadsheet-2,
Date Name apple android windows linux
I am able to copy the data from spreadsheet1 to spreadsheet2 by using the below google script.
function Daily() {
var SpreadSheetKeyA = "mykey1";
var SpreadSheetKeyB = "mykey2";
var sheet1 = SpreadsheetApp.openById(SpreadSheetKeyA).getSheetByName("Showstopper");
var sheet2 = SpreadsheetApp.openById(SpreadSheetKeyB).getSheetByName("Daily");
var data = sheet1.getRange(5,11,40,6).getValues();
var time = new Date ().toJSON().slice(0,10);;
for (var r = 0; r < data.length; r++) {
data[r].unshift(time);
sheet2.appendRow(data[r]);
}
}
The data present in spreadsheet1 is dynamic i.e, the number of rows can vary. Now whenever I run the script again so as to update the spreadsheet2 data is being appended after blank rows. I would like enhance the above script so that it should avoid blank rows or only copy rows with data.
Can anyone help me with this please
This should work if all blanks are at the bottom of the source and there is nothing else below the data.
function triggerOnTime() {
var SpreadSheetKeyA = "MY key";
var SpreadSheetKeyB = "MY key";
var sheet1 = SpreadsheetApp.openById(SpreadSheetKeyA).getSheetByName("Source Name");
var sheet2 = SpreadsheetApp.openById(SpreadSheetKeyB).getSheetByName("Target Name");
var startRow = 5;
var data = sheet1.getRange(startRow,11,sheet1.getLastRow() - startRow + 1,5).getValues();
var time = new Date ().toJSON().slice(0,10);;
for (var r = 0; r < data.length; r++) {
data[r].unshift(time);
}
if(data.length > 0 ) {
sheet2.insertRowsAfter(sheet2.getLastRow(), data.length);
sheet2.getRange(sheet2.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
}
If for whatever reason the above conditions cannot be met and you need to hardcode the number of rows to 40 you might try the following:
function triggerOnTime() {
var SpreadSheetKeyA = "MY key";
var SpreadSheetKeyB = "MY key";
var sheet1 = SpreadsheetApp.openById(SpreadSheetKeyA).getSheetByName("Source Name");
var sheet2 = SpreadsheetApp.openById(SpreadSheetKeyB).getSheetByName("Target Name");
var startRow = 5;
var data = sheet1.getRange(5,11,40,6).getValues();
var time = new Date ().toJSON().slice(0,10);;
for(var i = data.length - 1; i > -1; i--) {
if(data[i].join("").length == 0) data.splice(i, 1);
}
for (var r = 0; r < data.length; r++) {
data[r].unshift(time);
}
if(data.length > 0 ) {
sheet2.insertRowsAfter(sheet2.getLastRow(), data.length);
sheet2.getRange(sheet2.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
}