So I've created sort of radio button chooser table with check boxes so I can pick which line I want and that brings the value from this line out to the result cell...
this is the basic principle:
this way which ever checkbox I click, the value of that cell becomes 1 (TRUE) rather than 0 (FALSE), and using SUMPRODUCT formula, every line is multiplied by the boolean checkbox so if the checkbox is not checked, the production is zeroed, and if the checkbox is checked, the value remains.
In this example on B8 I get:
B8 = A2*B2 + A3*B3 + A4*B4 = 0*3 + 1*8 + 0*12 = 8
That works well as long as the values are numbers..
Now I'm trying to do the same but with string values..
something like this:
Any idea?
Solution:
Use IF to get corresponding Col B
JOIN the resulting array
Sample:
=ARRAYFORMULA(TEXTJOIN(",",1,IF(A2:A4,B2:B4,)))
I used the checkbox and Google Apps Script, where column A (1) and column B (2) contain the checkboxes. For example:
function onEdit(evt) {
var range = evt.range;
var val = range.getValue();
var row = range.getRow();
var col = range.getColumn();
// -------------------------------------
// --- Cannot be both add and delete ---
// -------------------------------------
if (col == 1) {
if (val) {
SpreadsheetApp.getActiveSheet().getRange(row,2).setValue('FALSE');
}
}
else if (col == 2) {
if (val) {
SpreadsheetApp.getActiveSheet().getRange(row,1).setValue('FALSE');
}
}
}
I would like to share my codes. Please run onStart() for setting up radio boxes as well.
function onEdit(e) {
// radio button
var ss = SpreadsheetApp.getActiveSpreadsheet();
var gsheetrange = gsheet.getDataRange().getValues();
var rowcount = gsheetrange.length; // find end of row
for(var i = 0; i <= rowcount; i++) { // start from 0.
if (i==gedited){
gsheet.getRange(gedited, 2).setValue("true");
}
else
{
gsheet.getRange(i, 2).setValue("false");
}
}
}
Related
I'd like to have a user click/highlight a column (or a checkbox at the top of the column, then click a single button to run the script on all checked columns.
var values1 = "Pass";
// Where to look for Auto:
var enabledDisabled = sheet.getRange("B3:B140").getValues();
var testResultsRange = sheet.getRange("AL3:AL140");
var testResults = testResultsRange.getValues();
// Keyword to look for in Auto: column
var putValues = [];
for (var i = 0; i < enabledDisabled.length; i++) {
if (enabledDisabled[i][0] === "Yes") {
putValues.push([values1]);
} else {
putValues.push([testResults[i][0]]); // Push the existing cell value
}
}
// Put value1 inside row, column# for test result
testResultsRange.setValues(putValues);
Instead of hardcoded ranges, I'd like it to run on every column that is checked, basically.
Any help would be hugely appreciated!
One solution I usually use is to put checkboxes on the first row of the columns, then with onEdit I run the script by clicking on the checkbox and by detecting the column by getColumn ()
function onEdit(event){
var sh = event.source.getActiveSheet();
var cel = event.source.getActiveRange();
if (sh.getName()=='mySheet' and cel.getValue()){
var col = cel.getColumn()
// run your script in column 'col'
cel.setValue(!cel.getValue())
}
}
so the task is that I need to highlight or scan for duplicate values in a column BUT for the last say 5 rows, eg if I have the data
1. 1
2. 5
3. 7
4. 2
5. 2
6. 3
7. 4
8. 2
9. 3
so in the end, only 5th,6th,8th and 9th row should be highlighted. I can easily do this using the script over here
function myFunction() {
// List the columns you want to check by number (A = 1)
var CHECK_COLUMNS = [1];
// Get the active sheet and info about it
var sourceSheet = SpreadsheetApp.getActiveSheet();
var numRows = sourceSheet.getLastRow();
var numCols = sourceSheet.getLastColumn();
// Create the temporary working sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var newSheet = ss.insertSheet("FindDupess");
// Copy the desired rows to the FindDupes sheet
for (var i = 0; i < CHECK_COLUMNS.length; i++) {
var sourceRange = sourceSheet.getRange(1,CHECK_COLUMNS[i],numRows);
var nextCol = newSheet.getLastColumn() + 1;
sourceRange.copyTo(newSheet.getRange(1,nextCol,numRows));
}
// Find duplicates in the FindDupes sheet and color them in the main sheet
var dupes = false;
var data = newSheet.getDataRange().getValues();
data.length;
for (i = data.length-1; i > data.length-4; i--) {
for (j = i-1; j > data.length-6; j--) {
if (data[i].join() == data[j].join()) {
i;
j;
dupes = true;
sourceSheet.getRange(i+1,1,1,numCols).setBackground("red");
sourceSheet.getRange(j+1,1,1,numCols).setBackground("red");
}
}
}
// Remove the FindDupes temporary sheet
ss.deleteSheet(newSheet);
// Alert the user with the results
if (dupes) {
Browser.msgBox("Possible duplicate(s) found and colored red.");
} else {
Browser.msgBox("No duplicates found.");
}
};
Now, what I want to do is that when I add a new row I want the code/formula to run again automatically and select the "now previous 5 rows". Like if I add another row
1. 1
2. 5
3. 7
4. 2
5. 2
6. 3
7. 4
8. 2
9. 3
10. 3
It should now highlight 6th,9th and 10th row. Hopefully, I have made it clear.
P.S I also used this formula
=UNIQUE(FILTER(A:A,ARRAYFORMULA(ROW(A:A)>COUNT(A:A)-5+1)))
But first, it doesn't highlight the rows secondly it doesn't return the duplicate values but all the unique values
you can resolve it without script with just two CF rules:
white background: =SUBTOTAL(3,$A$1:$A1)<=COUNTA(A:A)-5
red background: =COUNTIF(QUERY(A:A,"limit 5 offset "&(COUNT(A:A)-5)),A1)>1
I have been searching for a while and trying to work together a script from various answered topics that will allow me to adjust an adjacent cells content based on the data entered. I cannot seem to get it to work properly and need some help steering the ship the right direction. Here is what I am trying to accomplish:
--If the value of cell A2:A is a six digit number AND the value of cell D2:D (same row) is "MATCH" then the value for cell B2:B should be set to "ANN"
--If the value of cell A2:A is a six digit number AND the value of cell D2:D (same row) is "NO MATCH" then the value for cell B2:B should be set to "ANN" and a drop-down data validation list of ['ANN','RNW'] populate WITH the default value of the list set to "ANN"
--If the value of cell A2:A has a length of seven or greater characters then a drop-down data validation list of ['1DY','RNW','NEW'] populate WITH the default value of the list set to "1DY"
Is it even possible to set the value of a data validation cell to a specific, default value? This is important as when the user is entering data they will more than likely accept the default value. If they don't want the default value then they can select a value from the drop-down list.
I built a test sheet which shows the what the sheet should look like when data is filled out in column A and the associated values in column B.
My test is here: https://docs.google.com/spreadsheets/d/1p8sq63S-vSU1FKFLjtr2ZypItN5viXotoZL0Ki2PoQM/edit?usp=sharing
Here is the cobbled together script I was attempting to build (I too find it funny). This is my first attempt to right a Google Script to run on a spreadsheet.
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var aSheet = ss.getActiveSheet();
var aCell = aSheet.getActiveCell();
var aColumn = aCell.getColumn();
var aRow = aCell.getRow();
//var licenseStatus = aSheet.getRange(aRow, aColumn+9).getValue();
// The row and column here are relative to the range
// getCell(1,1) in this code returns the cell at B2, B2
var licenseTypeCell = aSheet.getRange(aRow, aColumn+1);
if (aColumn == 1 && aSheet.getName() == 'Onsite') {
if (isnumber(aCell) && (len(aCell) <= 6)) {
var rule = SpreadsheetApp.newDataValidation().requireValueInList(['ANN','RNW']).build();
licenseTypeCell.setValue("ANN");
licenseTypeCell.setDataValidation(rule);
} else {
var rule = SpreadsheetApp.newDataValidation().requireValueInList(['1DY','RNW','NEW']).build();
licenseTypeCell.setValue("1DY");
licenseTypeCell.setDataValidation(rule);
}
}
}
Any help/guidance would be greatly appreciated.
You are on the right track, few minor changes. Below you will find some new function to be used in your code.
1) getValue() You get your cell using var aCell = aSheet.getActiveCell() i.e the cell that was edited. But to get the value of the cell you will need to do the following aValue = aCell.getValue()
2) isNaN() To check if the aValue (as determined above) is a number or not. You will use a function called isNaN(aValue). Google script uses javascript platform and hence we need to use functions from javascript. This is different from an inbuilt function you use in a google spreadsheet. It returns True if the value is Not A Number(NAN). Hence, we use a not operator(!) to flip the return value, like so
if(!isNaN(aValue))
3) Number of digits There is no len function in google scripts, hence to determine if the number is 6 digits long you can do the following
if(aValue < 1000000)
Your final code will look something like this:
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var aSheet = ss.getActiveSheet();
var aCell = aSheet.getActiveCell();
var aColumn = aCell.getColumn();
var aRow = aCell.getRow();
//var licenseStatus = aSheet.getRange(aRow, aColumn+9).getValue();
// The row and column here are relative to the range
// getCell(1,1) in this code returns the cell at B2, B2
var licenseTypeCell = aSheet.getRange(aRow, aColumn+1);
var aValue = aCell.getValue()
if (aColumn == 1 && aSheet.getName() == 'Main') {
if (!isNaN(aValue) && aValue < 1000000) {
var matchCell = aSheet.getRange(aRow, aColumn+3).getValue()
//The above gets value of column D (MATCH or NO MATCH)
if(matchCell == "MATCH"){ //Check if Col D is MATCH
licenseTypeCell.setValue("ANN");
}
else{
var rule = SpreadsheetApp.newDataValidation().requireValueInList(['ANN','RNW']).build();
licenseTypeCell.setValue("ANN");
licenseTypeCell.setDataValidation(rule);
}
} else {
var rule = SpreadsheetApp.newDataValidation().requireValueInList(['1DY','RNW','NEW']).build();
licenseTypeCell.setValue("1DY");
licenseTypeCell.setDataValidation(rule);
}
}
}
Also, note the addition of the following lines to check for col D Value
var matchCell = aSheet.getRange(aRow, aColumn+3).getValue()
//The above gets value of column D (MATCH or NO MATCH)
if(matchCell == "MATCH"){ //Check if Col D is MATCH
licenseTypeCell.setValue("ANN");
}
I'm not sure if this is even possible, and to be quite honest, I haven't tried many things because I wasn't sure where to even start. I'm using the Script Editor from Google Sheets, btw. I know there are SpreadsheetApp.getRange() and another to get the values or something like that. But what I want is a bit specific.
Is there a way to grab all the cell data in a given row and put it into an array? The rows will vary in size, that's why I can't do an exact range.
So for example, if I were to have rows have these values:
abc | 123 | 987 | efg
blah| cat | 654
I want to be able to grab those values and place them into an array like ["abc", "123", "987, "efg"]. And then if I run the function on the next row, it'd be ["blah", "cat", "654"].
Actually, it can be placed into any data type as long as there's a delimiter I'd be able to use.
Thank you in advance!
This is easier to achieve without a script, with the formula =filter(1:1, len(1:1)) returning all values in nonempty cells in row 1, etc.
From a script, you can do something like this:
function flat_nonempty() {
var range = SpreadsheetApp.getActiveSheet().getRange("A:A"); // range here
var values = range.getValues();
var flat = values.reduce(function(acc, row) {
return acc.concat(row.filter(function(x) {
return x != "";
}));
}, []);
Logger.log(flat); // flat list of values, no blanks
}
The range here can have one row or multiple rows.
Is this useful for you?
When there are abc | 123 | 987 | efg, blah| cat | 654 and abc | | 987 | efg at row 1, row 2 and row 3, myFunction(1), myFunction(2) and myFunction(3) return [abc, 123.0, 987.0, efg], [blah, cat, 654.0] and [abc, , 987.0, efg].
function myFunction(row){
var ss = SpreadsheetApp.getActiveSheet();
var values = ss.getRange(row, 1, 1, ss.getLastColumn()).getValues();
var c = 0;
for (var c = values[0].length - 1; c >= 0; c--){
if (values[0][c] != "") break;
}
values[0].splice(c + 1, values[0].length - c - 1);
return values[0];
}
Adapted from https://developers.google.com/apps-script/reference/spreadsheet/sheet#getDataRange()
You can loop and create your array directly if you do want an array. Here I am illustrating creating for all the rows, but if you know the row you want, you could do without the outer loop (and just set i to the desired row).
function rowArr() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// This represents ALL the rows
var range = sheet.getDataRange();
var values = range.getValues();
for (var i = 0; i < values.length; i++) {
var row = [];
for (var j = 0; j < values[i].length; j++) {
if (values[i][j]) {
row.push(values[i][j]);
}
}
Logger.log(row);
}
}
I have 30 columns and 1000 rows, I would like to compare column1 with another column. IF the value dont match then I would like to colour it red. Below is a small dataset in my spreadsheet:
A B C D E F ...
1 name sName email
2
3
.
n
Because I have a large dataset and I want to storing my columns in a array, the first row is heading. This is what I have done, however when testing I get empty result, can someone correct me what I am doing wrong?
var index = [];
var sheet = SpreadsheetApp.getActiveSheet();
function col(){
var data = sheet.getDataRange().getValues();
for (var i = 1; i <= data.length; i++) {
te = index[i] = data[1];
Logger.log(columnIndex[i])
if (data[3] != data[7]){
// column_id.setFontColor('red'); <--- I can set the background like this
}
}
}
From the code you can see I am scanning whole spreadsheet data[1] get the heading and in if loop (data[3] != data[7]) compare two columns. I do have to work on my colour variable but that can be done once I get the data that I need.
Try to check this tutorial if it can help you with your problem. This tutorial use a Google AppsScript to compare the two columns. If differences are found, the script should point these out. If no differences are found at all, the script should put out the text "[id]". Just customize this code for your own function.
Here is the code used to achieve this kind of comparison
function stringComparison(s1, s2) {
// lets test both variables are the same object type if not throw an error
if (Object.prototype.toString.call(s1) !== Object.prototype.toString.call(s2)){
throw("Both values need to be an array of cells or individual cells")
}
// if we are looking at two arrays of cells make sure the sizes match and only one column wide
if( Object.prototype.toString.call(s1) === '[object Array]' ) {
if (s1.length != s2.length || s1[0].length > 1 || s2[0].length > 1){
throw("Arrays of cells need to be same size and 1 column wide");
}
// since we are working with an array intialise the return
var out = [];
for (r in s1){ // loop over the rows and find differences using diff sub function
out.push([diff(s1[r][0], s2[r][0])]);
}
return out; // return response
} else { // we are working with two cells so return diff
return diff(s1, s2)
}
}
function diff (s1, s2){
var out = "[ ";
var notid = false;
// loop to match each character
for (var n = 0; n < s1.length; n++){
if (s1.charAt(n) == s2.charAt(n)){
out += "–";
} else {
out += s2.charAt(n);
notid = true;
}
out += " ";
}
out += " ]"
return (notid) ? out : "[ id. ]"; // if notid(entical) return output or [id.]
}
For more information, just check the tutorial link above and this SO question on how to compare two Spreadsheets.