setFormula() in a FormResponse Sheet - google-apps-script

I am using GAS to generate a Google Form via Google Sheets. After the Form is generated and the "Responses" tab is added to the Sheet, the script adds a formula to cell E1 that is just supposed to copy the Timestamp from the A column to the E column. It looks like this:
ss.getSheets()[0].getRange("E1").setFormula("={\"Timestamp Moved\"; ARRAYFORMULA(IF($A$2:$A<>\"\",$A$2:$A,\"\"))}");
And shows this in the cell:
={"Timestamp Moved"; ARRAYFORMULA(IF($A$2:$A<>"",$A$2:$A,""))}
The formula drops into place just fine and looks right when I go to the Sheet and click on E1. However, whenever the Form is submitted, the "A$2:$A" moves down one row. So after the first submission, the formula in E1 changes to:
={"Timestamp Moved"; ARRAYFORMULA(IF($A$3:$A<>"",$A$3:$A,""))}
And so on. However, if I go into E1 and manually type the formula ={"Timestamp Moved"; ARRAYFORMULA(IF($A$2:$A<>"",$A$2:$A,""))} it works just fine. The A2 will stay A2 across all submissions.
The setFormula function is only running once, so it isn't like the GAS script is updating it. Any ideas why it is moving itself down?
EDIT
To minimally reproduce this, open GAS from within a Google Sheet and add this script:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.getSheets()[0].getRange("C1").setFormula("={\"Timestamp Moved\"; ARRAYFORMULA(IF($A$2:$A<>\"\",$A$2:$A,\"\"))}");
}
Next, from within the Sheet, select "Tools" and "Create a new form". Make a one question Form, then run the script. Go to the Responses tab and you should see this:
Then, fill out the Form once and you will now see this:
The timestamp is not moved and the formula shifts.

Google form response is inserted right after the row of the last response.
So the range changes from A2:A tp A3:A.
You should either add the formula after there is a response in row 2,
or use INDIRECT("A2:A") instead of A2:A.

Related

How to round a cell after user input in Google Sheets?

It should be a very simple function but I can't find anything that functions the way I need.
I want to have a cell where a number can be entered, then after its entered it is replaced by that number rounded to its nearest 0.25
For example:
I enter 5.26 into cell A1, after i press enter the cell now says 5.25
This should only happen with cell A1, so if i enter 5.26 elsewhere it will stay as 5.26
Any help? Thanks in advance and sorry if this a common question.
This can be achieve by using Google Apps Script and onEdit Trigger.
Follow these steps to achieve the desired goal.
In your Google Sheet, go to Tools -> Script editor.
Delete any code in the script editor and paste code provided below.
Click Save.
Go back to your Google Sheet and type numbers in cell A1.
Press enter and wait the value to change.
Code:
function onEdit(e) {
var range = e.range;
var input = e.value;
if(range.getA1Notation() == "A1" && !isNaN(input)){
var number = (Math.round(input * 4) / 4).toFixed(2);
range.setValue(number);
}
}
Demo:
Triggers let Apps Script run a function automatically when a certain
event, like opening a document, occurs. In your case, we need to use
onEdit since it runs automatically when a user changes the value of
any cell in a spreadsheet. Apps Script passes the
triggered function an event object that contains information about the
context in which the event occurred (usually named e).
In the demo above, I created a condition that will check if the edited cell is A1 and if the inputted value is number. If both satisfy the condition, the script will calculate the value and use range.setValue() to change the value of A1.
References:
Class Range
Range.setValue(value)
Simple Triggers
Event Object

Fill cell based on another sheets value

I have a spreadsheet on Google sheets with 2 sheets, Sheet1 and Sheet2. On Sheet1 I have 2 columns (ID1 and Result1), in which are filled. On Sheet2 I have 2 columns (ID2 and Result2), in which ID2 is filled and Result2 is filled with the word "empty".
Sheet1 in my real spreadsheet is getting data from Google Forms, so every time Sheet1 receives a value on ID1 and Result1, it should search for the ID1 value on Sheet2's ID2 and when finding, paste Result1 value in Result2 in the row it's was found.
Result2 would then only be updated when there's new data on Sheet1 submitted from the form.
I created this editable form and spreadsheet to make it easier to understand (I also added a note explaining it in there). You can see the form here and the spreadsheet here.
In cell B2 of your second sheet I entered the following:
=VLOOKUP(A2,Sheet1!A:B,2,FALSE)
I guess VLOOKUP on Google-Sheets does allow reference across worksheets?
FYI, when entering the formula, after enter the first argument which is your look up criteria, you can click your sheet1 and highlight column A and B, then go back to your sheet2 (with the second argument automatically filled by the system) to finish the formula with the third (result range column position within the look up range) and fourth argument (TRUE for approximate match and FALSE for exact match) and hit Enter to exit the formula.
After looking through the current answers and comments I think I understand what you are looking for.
Answer:
You can do this in Google Apps Script by creating a function that is bound to your Google Form which collects the latest response and does the data processing, and making it run on Form submission.
Steps to take:
Firstly, on your Form, you will need to create a bound script. From the menu in the top right of the Form edit page, click ⋮ > Script editor, which will open a new script page.
From there you can make a script which will automatically do this for you, and make an Installable Trigger which runs when you need.
Code:
After opening the Script Editor, you will see a ready-to-edit function that looks like this:
function myFunction() {
}
Replace the entire script with the following code:
function onSubmit(e) {
var responses = FormApp.getActiveForm().getResponses();
var response = responses[responses.length - 1].getItemResponses();
var connectedSheet = SpreadsheetApp.openById('<your-sheet-id>').getSheets();
var sheet2 = connectedSheet[1];
var result2Column = sheet2.getRange('A1:A').getValues();
for (var i = 0; i < result2Column.length; i++) {
if (response[1] == result2Column[0]) {
sheet2.getRange('B' + (i +1)).setValue(response[0]);
}
}
}
Make sure to replace <your-sheet-id> with the unique ID of your Google Sheeet - you can find this in the URL of the sheet between the d/ and /edit like so:
https://docs.google.com/spreadsheets/d/<your-sheet-id>/edit
Run the script by pressing the play button (►) and authorise the application to run.
Then go to Edit -> Current Project's Triggers and set up a new installable trigger with the following settings:
Choose which function to run: onSubmit
Choose which deployment should run: Head
Select event source: From form
Select event type On form submit
Explanation:
This script will run each time a new form submission is made automatically - it will take the ID from the form response and search Sheet2 for it. If it's found, then the response given for result will be put in Sheet2 also, next to the corresponding ID.
References:
Google Apps Script Installable Triggers
do it simply like this:
=ARRAYFORMULA(IFERROR(VLOOKUP(A2:A, Sheet1!A:B, 2, 0)))
or reset by checkbox:

Running scripts resetting active cell

I'm fairly new to Google Scripts, and I'd like to use onEdit to trigger a function whenever a cell is edited. While I've got it working, it resets the active cell to A1 when it runs, so if someone tries to enter more than one value at a time, e.g. cells C4, D4, E4) - while they are entering a value into E4 the selection will reset to A1.
Cheers
Edit: Here's a spreadsheet showing the problem.
On further inspection, it looks like running any script (I also have a delete row function and an insert row function) will reset active cell to A1. This may not be the technical term, but if you have for example D4 selected, then running a script will change selection to A1
In your code, you're resetting the active sheet, which reloads the page when the script is triggered.
Here's your current code:
// Get the active workbook
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Get the first sheet in the workbook
var sheet = ss.getSheets()[0];
// Reload that first sheet
SpreadsheetApp.setActiveSheet(ss.getSheets()[0]);
Remove the third line where .setActiveSheet() is called and the problem will go away.

How to add date to empty cell by default if none specified in Google Form, on form submit with App Script?

I have a time log form that has a date field I do not want to have to fill out every time as 90% of the time the date would be today's date. (Sometimes you will be entering something from another day and need to change it).
When an entry is added column A is always going to have something, so it should check to see if A is empty and if that same rows D is empty it will input today's date into D.
Some of the example's I have looked at were for onEdit of cell change it, but I could not get it to work with a form submit or even just have it automatically check all the cells in D and if empty put today's date (Only when B has value).
I have a function to sort the sheet right now that is called when on form submit/onEdit happens and would like to stick the new formula in the bottom of the same one (unless that is bad practice). The reason for this is less functions to have to add to the trigger list.
A: Timestamp | B: What | C: Paid? | D: Date
You can try using Date from Google spreadsheets function list which Google Sheets offers.
And, as mentioned in Custom Functions in Google Sheets, if the available functions aren't enough for your needs, you can also use Google Apps Script to write custom functions then use them in Google Sheets just like a built-in function.
To get started, guidelines for custom functions and samples can be found in the given documentations.
You can use Google Apps Script with onFormSubmit trigger which will populate the said cell with default date.
Here is a sample code which will populate the current date in Column 4 of the row in question.
function onFormSubmit(e) {
//edit responses sheet name
var responseSheetName = 'Form Responses 2';
//Edit colmn number, column in which the date has to be autopopulated
var column = 4;
//Get target row number
var row = e.range.rowStart;
//If no date, pouplate the cell with current date
if(!e.values[column-1]){
SpreadsheetApp.getActive().getSheetByName(responseSheetName).getRange(row, column).setValue(new Date())
}
}
In order to setup the above code, open the Spreadsheet which contains the form responses. Go Tools > Script Editor. This will open script editor window. Paste above code and edit the responseSheetName and column . Now Save it.
After saving it, setup an on form submit trigger.
To setup the trigger, follow these steps.
From the script editor, choose Resources > Current project's triggers.
Click the link that says: No triggers set up. Click here to add one now.
Under Run, select the name of function onFormSubmit which you want to trigger.
Under Events, select From spreadsheet.
Select On form submit
Optionally, click Notifications to configure how and when you will be contacted by email if your triggered function fails.
Click Save.

CopyTo: How to push data/copy a cell from one google spreadsheet to another google spreadsheet using google apps script?

I look for a solution to copy a specific cell value in the Source spreadsheet from tab "Sum all" to another Spreadsheet to the Target Spreadsheet Tab "Copy all". It should work every time i change the Value of Cell G10. Access to the Target sheet is granted before i enter any Value to G10.
(Source Tab Name is "Sum all:G10" - Sheet has 10 different Tabs)
(Target Tab Name is "CopyData:T12" - Sheet has 10 different Tabs)
Easy way
Use the built-in IMPORTRANGE() function in Google Apps:
In your Target cell, type the following formula
=IMPORTRANGE("FILE_ID_HERE","Sum all!G10:G10")
The syntax for this function is
=IMPORTRANGE("FILE_ID","SHEET_NAME!RANGE_START:RANGE_END")
When you first type in this function, you'll get an error in the cell. Simply click on it and select "Allow" to link the two sheets together. This error will occur even if it is the same spreadsheet. This function can link two separate spreadsheets, too, as long as you have edit access to both.
Hard Way
I'm assuming from your question that you want to copy values to and from the same spreadsheet document, but to different cells that are located on different sheets of the spreadsheet. The Google Apps Script API calls tabs "sheets" and the overall document "spreadsheet".
First, open the script editor
Open your spreadsheet that you'd like to make this script for.
Select "Tools" in the toolbar, then "Script Editor"
Second, make a function for onEdit.
Making a function named onEdit will create a function that runs every time the edit trigger is fired, using a no-authorization "simple trigger". Google Sheets automatically sends this event every time a cell is edited by a user. The argument e for the function is the event passed by the trigger.
function onEdit(e) {
// Get the sheet named "Sum all" from the active spreadsheet (i.e. the one you are editing)
var source = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sum all");
// Returns the active cell
var cell = source .getActiveCell();
// Compare to see if its the right cell you're looking for
// getRow and getColumn methods return integers for the row and column of the cell
// A = 1, B = 2, ... G = 7
if (cell.getRow() == 10 && cell.getColumn() == 7) {
// If its the right cell, copy to the other cell
var target = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CopyData");
// set the value of the desired cell in the target sheet
target.getRange("T12").setValue(cell.getValue());
}
}
Third, save the script
Save the script, reload the file, and test it out.
If your tabs are on different spreadsheets
Change this line:
var target = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CopyData");
to this:
var target = SpreadsheetApp.openById("FILE_ID").getSheetByName("CopyData");
and insert the file ID for the target spreadsheet where I've written FILE_ID.
You will also need to use an "installed trigger", since a simple trigger cannot open a remote spreadsheet. To do this, change the name (so it is no longer a simple trigger function), and follow the steps here