I have more than 20k form responses (google sheet and google form) where some guys have selected the wrong data which is visible in my responses. How I know its wrong is because they needed to select the activity (an attribute) but they selected the similar activity name (let's call it X) which was for the previous year and this year's activity (let's call it Y) should have been the different one.
I know that after a certain date all the X activities are Y, so I need to modify the data while importing it from the responses.
I tried conditional formatting on the data but then the importrange doesn't work, it needs cells to be empty to work.
I learned about query statements but it doesn't allow UPDATE.
Please help me do this, I am okay if we need to use a macro. I'm looking for something like this (note that the following is the logic I'm looking for and not the actual code):
if date>"a date" and FC==X:
FC=Y
#FC being the column I wanna modify
Edit: I am unable to share the table as its confidential. Can tell you that first column is date/time of form and then there are 149 columns, one of them I need to modify based on the date. Let's Assume it has just 2 columns, A: date, B: activity (has 20 activities). So, if they have filled "X" activity after then change that activity to Y. I hope it helps in understanding.
Edit 2: Have put a dummy file as asked. So now the problem statement is after 21 May 2022 (inclusive) all "6" activity must be "2"
Try
function onOpen() {
SpreadsheetApp.getUi().createMenu('⇩ M E N U ⇩')
.addItem('👉 Update', 'myFunction')
.addToUi();
}
function myFunction() {
// parameters
var param = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Param')
var from = param.getRange('A2').getValue()
var before = param.getRange('B2').getValue()
var after = param.getRange('C2').getValue()
// data
var sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var range = sh.getDataRange()
var data = range.getValues()
data.filter(r => (r[0] >= from && r[1] == before)).forEach(r => r[1] = after)
range.setValues(data)
}
To avoid hardcoding and potential issue with dates, I put all parameters in a new tab called "Param" as follows
I am sorry if I made the wrong question, I'm getting started with Google Sheets and wanted to figure out how to work on some kind of score calculator based on IF conditionals. Here is the example:
It's going to be used on a Form Responses sheet (I don't want to use the Google Form's Quiz option) where I'll need to answer some Y/N questions, in the "Total" column, there is going to be a final score out of 100 based on the "Yes" or "No" answer.
Let's say that the Row # 2 is a submission from a Google Form, and let's say that every submission has by default a score of 100. What the "No" is doing is deducting 10 points from that initial score of 100.
I started with something like =MINUS("100", IF(A2= "No", 10)) but it only works with one cell.
Thank you so much!
Try this formula in E2:
=MINUS(100, COUNTIF(A2:D2, "No") * 10)
Output:
Update:
If you want to use the column header as reference for deduction points, You can use this Custom Function:
To write a custom function:
Create or open a spreadsheet in Google Sheets.
Select the menu item Tools > Script editor.
Delete any code in the script editor.
For this case, simply copy and paste the code below into your script editor
Click Save save.
Code:
function SCORE(range) {
var map = range.shift();
var data = range;
var result = [];
for(var i = 0; i < data.length; i++){
var tally = 0;
for(var j = 0; j < data[0].length; j++){
if(data[i][j] == "No"){
tally = tally + map[j];
}
}
result.push([100+tally])
}
return result;
}
To call the custom function
Click the cell where you want to use the function.
Type an equals sign (=) followed by the function name and any input value — for example, =SCORE(A1:D4) — and press Enter.
The cell will momentarily display Loading..., then return the result.
Example Usage:
Note: You must always include the column header(deduction points) in your range.
Reference:
COUNTIF
Custom Function
I have got a dictionary from an URLfetch. What I want to do is write the values in the row the script is launched from, but I don't know how to navigate trough the cells.
So how to get the range of the cell a function is launched from?
Thanks
function separate(Json) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("JsonData");
// cell = range of the cell the function is launched from
sheet.getRange(x).setValue(0."currentvalue")
// where x is the value on the b columns of the same row
sheet.getRange(y).setValue(0."marketcap")
// where y is the value on the c columns of the same row
// repeating this for every value of the dictionary that I want in my sheet.
return Json.O."id" // write the id in the cell in which the function is launched from
}
Here is how I want to call the function
Dictionary in a list taken into argument as Json
I assume that you have the data being written vertically right now. If your goal is to write it horizontally, then you can use TRANSPOSE() around your function to transmute your column into a row-
UPDATE
The solution above will work in a formula based approach. If you want to use an Apps Script approach, you could do the following. First you have to familiarize yourself with Range.getValues() and Range.setValues(). The first method will read values from a given range. In this scenario it should be used to load the dictionary values into Apps Script and save them into an array. At this point you have an array with the dictionary values stored in a column-life fashion, but since you want them in a row-like fashion you should transpose the array. To do it easily you can use the function at the bottom. Now you can safely take your row-like array and paste it into the Sheet with Range.setValues(). Please write back with any doubt about this second answer.
function transposeArray(array) {
return array[0].map((col, i) => array.map(row => row[i]));
}
Process maker 4 – first time using this.
So I have a main screen and a nested screen with the values I want to calculate
I've tried calcs with the variable and the corresponding property no luck then I move on to default value for the control input called "form_input_2"
var N1 = this.FA00_detallea_cant_ADT;
var N2 = this.FA00_detallea_precioag_ADT;
var total = N1 * N2;
return total;
how to call and convert (maybe) the correct values so this simple thing can work
You are quite close to the solution.
I have created a simple screen with three Line Inputs: Value1, Value2 and Total with variable names - input1, input2 and inputTotal.
For Total Input:
In Default Value, I have used Javascript with following code:
return this.input1 * this.input2
I didn't use variables to store the values entered by the users and instead I just returned the value.
This is the final output:
I hope this helps. Thank!
I want a formula to generate random data of birth dates for a specific years (Example: 1995 to 2002) and make it Array like this:
Sheet URL: https://docs.google.com/spreadsheets/d/1XHoxD-hNmpUOMVm_u-cz-4ESrabodsrS0fIfaN-n4js/edit
That might not be the best approach but it will get you closer to what you want:
=DATE(RANDBETWEEN(1995,2002),RANDBETWEEN(1,12),RANDBETWEEN(1,31))
There are two issues with this approach:
you might get a day that does not exist for the particular month. For example, 2/28/2021 exists, but 2/29/2021 does not exist.
I wasn't able to generate an array but only drag down formulas. When I generate an array, the same random numbers are used and as a result the dates are the same.
For the first issue, you can use isdate to check if the random date returned is correct. For example, 2/29/2021 is a wrong date (I hardcopied that date).
but I guess you can filter out the FALSE cases.
I really hope other people can come up with a better approach.
You could try (as I demonstrated in your sheet):
=ARRAY_CONSTRAIN(SORT(SEQUENCE(DATE(1992,12,31)-DATE(1900,1,1),1,DATE(1900,1,1)),RANDARRAY(DATE(1992,12,31)-DATE(1900,1,1)),1),COUNTA(A2:A),1)
SEQUENCE(DATE(1992,12,31)-DATE(1900,1,1),1,DATE(1900,1,1)) - Is used to create an array of valid numeric representations of true dates between 1-1-1900 and 31-12-1992.
SORT(<TheAbove>,RANDARRAY(DATE(1992,12,31)-DATE(1900,1,1)),1) - Is used to sort the array we just created randomly.
ARRAY_CONSTRAIN(<TheAbove>, COUNTA(A2:A),1) - Is used to only return as many random birth-dates we need according to other data.
Note that this is volatile and will recalculate upon sheet-changes and such. Also note that this is just "slicing" a given array and may fall short when you try to use it on a dataset larger than the given array.
As Google Sheets can deal with dates as integers (~ number of days since 1900), choosing a random date between two dates can be a single call to RANDBETWEEN (with the output formatted as Date).
With your initial date written in B1 and your end date in B2, the formula is simply:
=RANDBETWEEN($B$1,$B$2)
You can paste this formula in as many cells as you want, to generate N different random dates.
Of course, as other answers involving random generators in your sheet, the formula will be recomputed at each change. My suggestion to overcome this would simply be to copy/paste the output, using the "Paste special > Values only" option (right click or "Edit" menu).
Script Solution
Just for sake of completeness, here is a solution using a script
Initial Considerations
This cannot function like a in sheet function/formula.
https://developers.google.com/apps-script/guides/sheets/functions
Custom function arguments must be deterministic. That is, built-in spreadsheet functions that return a different result each time they calculate — such as NOW() or RAND() — are not allowed as arguments to a custom function. If a custom function tries to return a value based on one of these volatile built-in functions, it will display Loading... indefinitely.
A custom function cannot affect cells other than those it returns a value to. In other words, a custom function cannot edit arbitrary cells, only the cells it is called from and their adjacent cells. To edit arbitrary cells, use a custom menu to run a function instead.
So a normal script is needed.
The Script
/**
* Sets the values of a range to random dates.
*/
function generateRandomBdays(range, start, end) {
let height = range.getHeight();
let width = range.getWidth();
let output = [];
for (let i = 0; i != height; i++) {
let row = [];
for (let j = 0; j != width; j++) {
row.push(randomBday(start, end));
}
output.push(row)
}
range.setValues(output);
}
/**
* Generates a random date beween start and end
*/
function randomBday(start, end) {
if (start < 2000) start = start - 1900
start = new Date(`${start}`);
if (end < 2000) end = end - 1900
end = new Date(`${end}`);
let bday = new Date(
start.getTime() + (Math.random() * (end.getTime() - start.getTime()))
);
return bday;
}
/**
* Gets active selection and fills with random dates
*/
function main(){
let file = SpreadsheetApp.getActive();
let sheet = file.getActiveSheet()
let range = sheet.getActiveRange();
// ============
generateRandomBdays(range, 1995, 2002); // Change these years to your liking
// ============
}
/**
* Creates menu when sheet is opened.
*/
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Generate Birthdays')
.addItem('Generate!', 'main')
.addToUi();
}
Which works like this:
Installation
You will have to copy it into your script editor and then run one of the functions to authorize the script with the permissions it needs. Then next time you open the sheet you should have the menu available.
Alternatively you can delete the onOpen function and just use it from the script editor.
Within the main function, customize the range of years you need.
References
Apps Script
Overview of Spreadsheet Service in Apps Script