Google Sheets: Forms edit with multiple questions fix duplicate answers - google-sheets

I have a form that has a Question that depending upon an answer will direct you to futher questions. The problem is, once you submit the form and then go back and edit your answer, if you choose another answer for the first question and it redirects to a new question because your first answer was different, the response in Google Sheets keeps both answers. How can I fix this so that it only shows the last answers? For example. When I first answer the question, I choose Option 1.
Then when I choose next I get these options.
Which once I submit will give the following response submission in Sheets.
Ok, so then if I go back and Edit my response like so...
It will redirect to a different question based on my first choice.
However, once I submit my final answer, this is what the subission looks like in Sheets.
The problem is, Column C and D answers are no longer relevant based upon the answer in Column B. How can I fix this so that Column C and D are blank as they should be and I only get the answer that is correct based upon the submission in Forms?
Thanks!

You can create a bound script in your Google Sheets with a Form Submit trigger.
Sample Code:
function formSubmission(e) {
Logger.log(JSON.stringify(e));
Logger.log(e.values);
var data = e.values;
var row = e.range.rowStart;
var sheet = SpreadsheetApp.getActive().getSheetByName('Form Responses 1');
if(data[1]=="Option 1"){
//Remove data under Follow-up Question2 and Amount 2 (Column E and F)
sheet.getRange(row,5,1,2).clearContent();
}else if(data[1]=="Option 2"){
//Remove data under Follow-up Question1 and Amount 1 (Column C and D)
sheet.getRange(row,3,1,2).clearContent();
}
}
Pre-requisite:
What it does?
Get the form submitted values using Sheets form submit event object values
Get the form submitted target row using range.rowStart
Get the active spreadsheet and sheet with the name Form Responses 1
Check the Option selected and delete specific columns depending on the option selected.
Output:

Here's how I finally was able to do what I needed Ron M's help:
function formSubmission(e) {
Logger.log(JSON.stringify(e));
Logger.log(e.values);
var data = e.values;
var row = e.range.rowStart;
var sheet = SpreadsheetApp.getActive().getSheetByName('Form Responses 1');
if(data[4]=="Debit"){
sheet.getRange(row,7,1,1).clearContent();
}else if(data[4]=="Credit"){
sheet.getRange(row,6,1,1).clearContent();
}
if(data[7]=="INCOME"){
sheet.getRange(row,10,1,14).clearContent();
}else if(data[7]=="HOME"){
sheet.getRange(row,9,1,1).clearContent();
sheet.getRange(row,11,1,13).clearContent();
}else if(data[7]=="LIVING"){
sheet.getRange(row,9,1,2).clearContent();
sheet.getRange(row,12,1,12).clearContent();
}else if(data[7]=="TRANSPORTATION"){
sheet.getRange(row,9,1,3).clearContent();
sheet.getRange(row,13,1,11).clearContent();
}else if(data[7]=="HEALTH"){
sheet.getRange(row,9,1,4).clearContent();
sheet.getRange(row,14,1,10).clearContent();
}else if(data[7]=="INSURANCE"){
sheet.getRange(row,9,1,5).clearContent();
sheet.getRange(row,15,1,9).clearContent();
}else if(data[7]=="EDUCATION"){
sheet.getRange(row,9,1,6).clearContent();
sheet.getRange(row,16,1,8).clearContent();
}else if(data[7]=="CHARITY/GIFTS"){
sheet.getRange(row,9,1,7).clearContent();
sheet.getRange(row,17,1,7).clearContent();
}else if(data[7]=="SAVINGS"){
sheet.getRange(row,9,1,8).clearContent();
sheet.getRange(row,18,1,6).clearContent();
}else if(data[7]=="OBLIGATIONS"){
sheet.getRange(row,9,1,9).clearContent();
sheet.getRange(row,19,1,5).clearContent();
}else if(data[7]=="ENTERTAINMENT"){
sheet.getRange(row,9,1,10).clearContent();
sheet.getRange(row,20,1,4).clearContent();
}else if(data[7]=="PETS"){
sheet.getRange(row,9,1,11).clearContent();
sheet.getRange(row,21,1,3).clearContent();
}else if(data[7]=="SUBSCRIPTIONS"){
sheet.getRange(row,9,1,12).clearContent();
sheet.getRange(row,22,1,2).clearContent();
}else if(data[7]=="VACATION"){
sheet.getRange(row,9,1,13).clearContent();
sheet.getRange(row,23,1,1).clearContent();
}else if(data[7]=="MISCELLANEOUS"){
sheet.getRange(row,9,1,14).clearContent();
}
}

Related

Force Dropdowns to Display in B2:B When Adjacent Cell in A2:A Has Data

In this sample Google Sheet that you can edit, I'm trying to configure the data validation dropdown menus in B2:B to only display when the adjacent cells in A2:A have data in them. As you can see in my spreadsheet, I have the data validation configured alright, but it inserts dropdown menus all the way down column B, even if there's no data next to it in Column A, and I don't want that.
How can I configure this to where Data Validation dropdown menus only display when there is data in adjacent cells in column A?
Thanks for your help!
You need a script
function onEdit(event){
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if (r.getColumn() == 1 && s.getName() == 'Dropdowns'){
r.offset(0,1).clearContent()
if (r.getValue() == ''){
r.offset(0,1).clearDataValidations();
}
else{
var lists = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Colors');
r.offset(0,1).setDataValidation(SpreadsheetApp.newDataValidation()
.setAllowInvalid(true)
.requireValueInRange(lists.getRange('A2:A'+lists.getLastRow()), true)
.build());
}
}
}

Sorting data in a sheet with added information Google Sheets

My work has a Google Form where different information is inputted. All this information is then automatically put into a Google Sheet. We will call it "All data sheet".
"All data sheet" has multiple sheets in it, one with all of the data and then one for each type of data which needs to be given to different people. One of those is called 'Caretaker'.
I then have a second Google Sheet (example called 'Sorting') that pulls everything from the 'Caretaker' sheet onto 'Import_range'.
This allows the caretaker to see everything that needs fixing with the oldest thing at the top and the newest at the bottom.
The caretaker would like the newest at the top.
I can easily make another sheet (see 'Sorted') that uses the sort function to put the newest at the top.
However, he would also like another column where he can either check a box to show it's done or write an x.
When new data appears, the checked box does not move down.
Is there any way to sort the data but also have an input column which stays with the sorted data?
Link to example.
You have to use Google Apps Script.
Try this:
To start, go to Tools and click Script editor.
Delete the code in Code.gs
Paste the code provided below and save
Refresh your Spreadsheet and Custom Menu will pop up in the Menu
Go To Custom Menu and Click Update Sorted Sheet
First execution will require user's authorization. Once you authorized the script, make sure to rerun the Custom Menu.
The code below will create a Custom Menu in your Spreadsheet. Clicking the custom menu will execute a function that will update the Sorted Sheet and retain its checkbox values.
I also added comments to explain the function of each line in the code.
Code:
function updateSorted() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("Import_range");
var sortedSh = ss.getSheetByName("Sorted");
/* Use this if the Import_range is from different spreadsheet
var iSS = SpreadsheetApp.openById("Insert Sheet ID here");
var sh = iSS.getSheetByName("Insert Sheet name here");
and comment the var sh = ss.getSheetByName("Import_range"); above*/
/*
Check if the Sorted Sheet has data.
If true, compare Sorted Sheet and Import_range data
else, copy Import_range data to Sorted Sheet.
*/
if(sortedSh.getLastRow() > 1){
var sData = sortedSh.getRange(2, 1, sortedSh.getLastRow()-1, 5).getValues(); //remove unnecessary data
var sDataFiltered = sData.filter(e => e[4]); //get Date column of Sorted sheet
var sDates = sortedSh.getRange(2, 5, sortedSh.getLastRow()-1, 1).getValues().flat();
var sDatesFiltered = sDates.filter((a) => a); //remove unnecessary data
var importDates = sh.getRange(2, 4, sh.getLastRow()-1, 1).getValues().flat(); //get Date column of Import_range
//convert dates to String format
var arr1 = sDatesFiltered.map( dateString => String(dateString))
var arr2 = importDates.map( dateString => String(dateString))
var difference = arr2.filter(x => !arr1.includes(x)); //get the difference between arr1 and arr2
difference.forEach(dates => {
var index = arr2.indexOf(dates); //get new entry position in Import_range
var newEntry = sh.getRange(index+2, 1, 1, 4).getValues().flat(); //get row data of new entry from Import_range
newEntry.unshift(false); //append false in the beggining of the array
sDataFiltered.push(newEntry); //append new entry to sDataFiltered array
})
var range = sortedSh.getRange(2, 1, sDataFiltered.length, 5);
range.setValues(sDataFiltered); //set the values of Sorted sheet using the sDataFiltered array as data
sortedSh.getRange(2, 1, sDataFiltered.length, 1).insertCheckboxes(); //get the checkbox range and insert checkbox
range.sort({column: 5, ascending: false}); //sort the data by Date column
}else{
var range = sh.getRange(2, 1, sh.getLastRow()-1, 4);
var data = range.getValues();
data.forEach(row => {
row.unshift(false)
})
var sortedRange = sortedSh.getRange(2, 1, data.length, 5);
sortedRange.setValues(data);
sortedSh.getRange(2, 1, data.length, 1).insertCheckboxes();
sortedRange.sort({column: 5, ascending: false});
}
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Custom Menu')
.addItem('Update Sorted Sheet', 'updateSorted')
.addToUi();
}
Examples:
Populating Empty Sorted Sheet:
Updating Import_range sheet, clicking checkboxes and updating Sorted Sheet:
Implementing Time Driven Triggers:
Open your Apps Script project.
At the left, click Triggers alarm.
At the bottom right, click Add Trigger.
Select and configure the type of trigger you want to create.
Click Save.
For time driven, your trigger setup should somehow look like this:
The example trigger above will update the sheet every minute. The down side of using time driven trigger is the quota limit. Gmail accounts are limited to 90 minutes of total runtime. Exceeding quotas will result to errors. See Quotas for Google Services.
Using Buttons: Alternative to Custom Menu
To create a user friendly button in your Sheet
Go to Insert -> Drawing
Draw the desired button shape and style.
Click Save and Close
Move the button to your desired position
Right click, click the 3 vertical dots and select Assign script
Type updateSorted and click OK
Click the button to run
Note: If you decided to use buttons and want to remove the Custom Menu in your sheet, just remove the onOpen function in your Apps Script.
References:
Google Apps Script on Sheets
Custom Menu
Simple Triggers
Class Sheet
Class Range
Class Spreadsheet
Installable Trigger

Multiple data validations in google sheets problem

I have a dropdown menu in A1 but I want it to reject input if B1 says "Closed". It won't let me keep the dropdown box as soon as I create the data validation for rejecting input. How do I fix this?
It is not possible to add 2 different data validation criteria in the selected range.
One workaround that you could do is to use data validation to have a drop-down menu and create an onEdit() function in Apps Script that will reject the inputs.
Sample Code:
function onEdit(e){
var cell = e.range;
var col = e.range.getColumn();
var ui = SpreadsheetApp.getUi();
//Check if current edited cell is in column 1 and if the cell besides the current cell is Closed
if(col == 1 && cell.offset(0,1).getValue() == "Closed"){
//Display warning message
ui.alert(
'Warning',
'You cannot modify cells that are closed, returning the original value of the cell',
ui.ButtonSet.OK
)
//return cell to its original value
cell.setValue(e.oldValue);
}
}
What it does?
Check if the modified cell is in column 1 and verify if the adjacent cell on its right has the value "Closed"
If true, display a warning message and return the cell to its original value
Output:
I used Range.offset(rowOffset, columnOffset) to get the value of the cell on the right side of the current cell by using +1 as column offset.
Additional Reference:
Container-bound Scripts
Google Sheets events

Prevent Duplicate Google form submissions which add to a google sheet

I have a google form which reflects its submissions to a google sheet, is there anyway i can prevent a duplicate phone number to be added in the google sheet?
you can use triggers which fires on every form submit and somewhat the following script to do whatever you want.
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActive().getSheetByName('sheet1') //change sheet name
var range = sheet.getRange("C").getValues(); // assuming mobile is 3rd field so C
var res = e.response.formResponses.getItemResponses();
var mobile = res[2].getResponse(); // if mobile is 3rd field res[2] (0 indexed)
for(i = 0; i < range.length; i++) {
if(mobile==range[i][0]) // mobile number found, delete it if more than one found?
}
You may also want to check out this for help.

Display a Message box based on a value in a cell in Google spreadsheet

I am trying to display a browser message box based on a particular value in range. I tried with the following
function onEdit(e){
var sheet = SpreadsheetApp.getActiveSheet();
var panType = sheet.getRange("A4:A100").getValues();
if (panType=="CSF");
Browser.msgBox('Make sure you enter the PAN No in the alloted slot');
}
But the problem is, with each and every edit in any cell, the message box pops up.
The said range A4:A100 has a validation dropdown with options like "New" and "CSF". So whenever the value CSF is chosen, the dialogue box should popup.
Thanks
You just need to check if it is the xorrect sheet, column, and value. Event has these values. If they match, show your messagebox.
function onEdit(event){
var sheet = event.source.getActiveSheet().getName()
var editedCell = event.range.getSheet().getActiveCell();
if(sheet=="Sheet1"){
if(editedCell.getColumn() == 1 && event.value=="CSF"){
Browser.msgBox('Make sure you enter the PAN No in the alloted slot');
}}}

Resources