How to get google sheets to reorder based on ranking - google-apps-script

I have created a Google Sheet that has a "days since" rank based on differences from todays date to date of the last "incident".
These days update automatically, but what I want is to have a ranking system where the Google Sheet reorders if the date of someone's last incident changes.
Is this possible? I have attached the link below, but it is a very simple formula as of now.
Row D: =today()-C3
https://docs.google.com/spreadsheets/d/12SUfrB7XuqGlfxjvaePHJTGaZz_FhjiWhLxjPMAM2jI/edit?usp=sharing

If you don't want to use Google Apps Script you may duplicate this table (in sheet2 for example) and have it's content duplicated there within sort() function.
Lets say you put
=sort(Sheet1!A3:D8,4,0) in A3 cell of new Sheet2
I know it's not exactly the goal...

I believe your goal as follows.
You want to automatically sort the data with the column "C" when users edited the cells "C3:C8".
The table of the data is the cells "A3:D8".
From your tag of google-apps-script, I thought that your direction includes to use Google Apps Script.
In this case, I would like to propose to use OnEdit simple trigger for achieving your goal. The sample script is as follows
Sample script:
Please copy and paste the following script to the container-bound script of the Spreadsheet and save it.
function onEdit(e) {
const range = e.range;
const sheet = range.getSheet();
if (sheet.getSheetName() == "Sheet1" && range.getRow() >= 3 && range.getRow() <= 8 && range.getColumn() == 3) {
sheet.getRange("A3:D8").sort({column: 3, ascending: true});
}
}
When you edit the cells "C3:C8", the script is automatically run by the OnEdit simple trigger, and the data is sorted with the column "C".
Result:
When your shared Spreadsheet is used with above sample script, the following result can be obtained.
Note:
When you want to sort with the column "D", please modify above script as follows.
From
sheet.getRange("A3:D8").sort({column: 3, ascending: true});
To
sheet.getRange("A3:D8").sort({column: 4, ascending: false});
References:
Simple Triggers
sort(sortSpecObj)

Related

To copy Cell values from a range and paste it in a single row of another sheet

Wanted to accomplish below mentioned task,
Having 2 Sheets(Sheet1 and Sheet 2)
On clicking the Checkbox on Sheet 1:J1, data present in the table form on the Sheet 1 should get pasted in the single row of Sheet2
For e.g Product 1 data (P1) to the Product 1 Column, Product 2 data (P2) to the Product 2 Column and so on...
For every new submit, new data to be recorded on the next row of Sheet2.
SS link:https://docs.google.com/spreadsheets/d/1tmnDOMyupjeO8d65qHQsxb5KrrKeq7pMYIE8h2VmEJ4/edit?usp=sharing
Thanks in advance
I believe your goal is as follows.
When a checkbox of "H1" of "Sheet1" is checked, you want to copy the values from the cells "A3:G6" to the columns "B" to "AC" in one row of "Sheet2".
And, you want to copy "B1" and "B10" of "Sheet1" to the columns "A" and "AD" of "Sheet2".
In your Spreadsheet, there are no merged cells.
In this case, how about the following sample script?
Sample script:
function onEdit(e) {
const range = e.range;
const sheet = range.getSheet();
if (sheet.getSheetName() != "Sheet1" || range.getA1Notation() != "H1" || !range.isChecked()) return;
const srcRange = sheet.getRange("A3:G6");
const [[b1], , , , , , , , , [b10]] = sheet.getRange("B1:B10").getValues();
const values = [b1, ...srcRange.getValues().flat(), b10];
const dstSheet = e.source.getSheetByName("Sheet2");
dstSheet.appendRow(values);
range.uncheck();
// srcRange.clearContent();
}
This script is automatically run with the simple trigger of OnEdit trigger. So, when you use this script, please check the checkbox of "H1" of "Sheet1". By this, the script is run. When you directly run the script, an error like Cannot read property 'range' of undefined occurs. Please be careful about this.
If you want to clear the source range after the values were copied, please use srcRange.clearContent();.
Note:
This sample script is for your sample Spreadsheet. So, when you changed your Spreadsheet, this script might not be able to be used. Please be careful about this.
Reference:
Simple Triggers

How to get Google Sheets reorder based on points?

I need help with my table.
I need to reorder my table (range: DY23:DZ33) in points by descending order.
But when I run my script I get an error: Cannot read property 'range' of undefined at onEdit(Code:2:19)
The code:
function onEdit(e) {
const range = e.range;
const sheet = range.getSheet();
if (sheet.getSheetName() == "Test1" && range.getRow() >= 23 && range.getRow() <= 33 && range.getColumn() == 131) {
sheet.getRange("DY23:EA33").sort({column: 131, ascending: true});
}
}
The tabel: https://docs.google.com/spreadsheets/d/1v9oqRNfmsVvrpZmiolOIyyuGx-OALyIYPPOXsa5znRg/edit#gid=1473685733
NB! Please forgive me for my poor english.
Issue and workaround:
I think that your error of Cannot read property 'range' of undefined at onEdit is due to that you might directly run the function onEdit. I think that this might be the reason for your current issue.
In your script, when the cells of "EA23:EA33" are edited, the script is run. But when I saw your sample Spreadsheet, the cells of "EA23:EA33" are the formulas. In this case, when the values by the formulas are changed, the function onEdit is not run. I think that this might be the reason for your 2nd issue.
And also, when you directly sort the cells of "EA23:EA33" using the sort method, the ranges of formulas in the cells are changed. By this, the values are changed. I think that this might be the reason for your 3rd issue.
When you want to run the script using the script editor, the button, and the custom menu, it is required to change the function without using the event object. So how about the following modification?
Modified script:
function sample() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Test1");
const range = sheet.getRange("EA23:EA33");
const formulas = range.getFormulas();
const mFormulas = formulas.map(([ea]) => [ea.replace(/=SUM\(([A-Z]+)([0-9]+)\+([A-Z]+)([0-9]+)\)/i, "=SUM($$$1$$$2+$$$3$$$4)")]);
if (JSON.stringify(formulas) != JSON.stringify(mFormulas)) range.setFormulas(mFormulas);
SpreadsheetApp.flush();
sheet.getRange("DY23:EA33").sort({ column: 131, ascending: true });
}
In this modified script, you can directly run this function with the script editor.
In this modified script, the formulas of cells of "EA23:EA33" are changed by the absolute reference. And the cells "DY23:EA33" are sorted. By this, the formulas can work by the sort.
References:
getFormulas()
setFormulas(formulas)

Date stamp script not working with arrayformula

I'm trying to use a simple date stamp script in Google Sheets that will input today's date upon edit of another column but then will not change thereafter. I also have an array formula set on the column the script is looking at for the edits and it appears the array formula is preventing the script from working properly. Here is the formula:
={"Triggered";arrayformula(IFS(E2:E="","",C2:C>=E2:E,"✅",TRUE,""))}
And this is the script:
function onEdit(e) {
var sh = e.source.getActiveSheet();
if(sh.getName() !== "Watchlist" || e.range.columnStart !== 8) return;// 1 is A, 2 is B, 3 is C, etc
var o = e.range.offset(0, 1)
if(!o.getValue()) o.setValue(new Date())
}
Any help with what I'm doing wrong is appreciated. Thanks.
Unfortunately, according to the official documentation :
An installable edit trigger runs when a user modifies a value in a
spreadsheet.
Even when the output of the arrayformula is updated, the cell still contains the same formula. Therefore, the onEdit trigger won't fire since there wasn't any edit action by the user.
Read also the discussion here.

Run google script when specific cell has specific number

I have a sheet called 'Admin' where I created a drop down with 4 options. Upon selecting the drop down, the 'trigger' column (3) will display a number.
In scripts, I have 4 scripts written and tested, but I want these to run based on the value displayed in the 'Trigger' column above:
Could anyone help me write this script, as I have tried numerous scripts but cannot seem to get anywhere close?
The sheet id is:
https://docs.google.com/spreadsheets/d/1doHHOSc3GkMX5jVayU63-PDXQ1Q4s4CepbMW6uXS3DY/edit?usp=sharing
My thanks in advance,
Brendon
I believe your goal as follows.
You want to run the function of the function name corresponding to the cell "C2" of the sheet "Admin".
For example, the value of cell "C2" is 1, you want to run the function of One().
In your case, how about using the OnEdit event trigger? But from your script, I think that it is required to use the OnEdit event trigger as the installable trigger.
Sample script:
Please copy and paste the following script to the script editor and install the OnEdit event trigger to the function of installedOnEdit.
function installedOnEdit(e) {
var range = e.range;
var sheet = range.getSheet();
if (sheet.getSheetName() == "Admin" && range.getA1Notation() == "A2") {
var functions = {1: One, 2: Two, 3: Three, 4: Four};
functions[range.offset(0, 2).getValue()]();
}
}
By above settings, when you change the dropdown list of the cell "A2" on the sheet "Admin", the function corresponding to the value of cell "C2" is run.
Note:
In this modification, it supposes that your functions of One, Two, Three and Four work fine. Please be careful this.
When you modified the function names you want to run, please also modify var functions = {1: One, 2: Two, 3: Three, 4: Four};.
Reference:
Installable Triggers
Added:
When you want to directly run the function of installedOnEdit with the script editor, at first, please check the following points.
In this case, it is required to fix the cell for using the function. So in your case, it supposes that the cell of "C2" on the sheet of "Admin" are always used. When you use other cells, please modify the following script for your situation. Please be careful this.
Modified script:
function installedOnEdit(e) {
var functions = {1: One, 2: Two, 3: Three, 4: Four};
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Admin");
var value = sheet.getRange("C2").getValue();
functions[value]();
}

Custom function won't refresh as inputs are changed

I have a custom function that finds the value of another cell and displays it. When the source cell is changed, the function does not reflect.
https://docs.google.com/spreadsheets/d/1wfFe__g0VdXGAAaPthuhmWQo3A2nQtSVUhfGBt6aIQ0/edit?usp=sharing
Refreshing google sheets
function findRate() {
var accountName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(1,1).getValue(); //determine the account name to use in the horizontal search
var rateTab = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Rates'); //hold the name of the rate tab for further dissection
var rateNumColumns =rateTab.getLastColumn(); //count the number of columns on the rate tab so we can later create an array
var rateNumRows = rateTab.getLastRow(); //count the number of rows on the rate tab so we can create an array
var rateSheet = rateTab.getRange(1,1,rateNumRows,rateNumColumns).getValues(); //create an array based on the number of rows & columns on the rate tab
var currentRow = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveCell().getRow(); //gets the current row so we can get the name of the rate to search
var rateToSearch = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(currentRow,1).getValue(); //gets the name of the rate to search on the rates tab
for(rr=0;rr<rateSheet.length;++rr){
if (rateSheet[rr][0]==rateToSearch){break} ;// if we find the name of the
}
for(cc=0;cc<rateNumColumns;++cc){
if (rateSheet[0][cc]==accountName){break};
}
var rate = rateSheet[rr][cc] ; //the value of the rate as specified by rate name and account name
return rate;
}
If I change a rate in the rate tab, I need the custom function to recognize the new rate and update its value
You want to recalculate the custom function of =findRate(), when the cells of the sheet name of Rates are edited.
If my understanding is correct, how about adding the following sample script? Please think of this as just one of several answers.
Solution:
In order to recalculate the custom function, in this answer, the formula of =findRate() is overwritten by the script running with the OnEdit event trigger (in this case, it's the simple trigger.). By this, the recalculate is executed. But, when the formula is directly replaced by the same formula, the recalculate is not executed. So I used the following flow.
Retrieve all ranges of cells which have the formula of =findRate() from the sheet of "Projected Revenue".
Clear the formulas of the ranges.
Put the formulas to the ranges.
By this flow, when the cell of the sheet of "Rates" is edited, the custom function of =findRate() is recalculated by automatically running onEdit().
Sample script:
Please copy and paste the following script to the script editor. Then, please edit the cells of sheet name of Rates. By this, onEdit() is automatically run by the OnEdit event trigger.
function onEdit(e) {
var range = e.range;
if (range.getSheet().getSheetName() == "Rates" && range.rowStart > 1 && range.columnStart > 1) {
var sheetName = "Projected Revenue"; // If you want to change the sheet name, please modify this.
var formula = "=findRate()";// If you want to change the function name, please modify this.
var sheet = e.source.getSheetByName(sheetName);
var ranges = sheet.createTextFinder(formula).matchFormulaText(true).findAll().map(function(e) {return e.getA1Notation()});
sheet.getRangeList(ranges).clearContent();
SpreadsheetApp.flush();
sheet.getRangeList(ranges).setFormula(formula);
}
}
Note:
onEdit(e) is run by the OnEdit event trigger. So when you directly run onEdit(e), an error occurs. Please be careful this.
In this sample script, as a sample, even when the row 1 and column "A" of the sheet of "Rates" are edited, the custom function is not recalculated. If you want to modify this and give the limitation of range you want to edit, please modify the above script.
References:
Simple Triggers
Class TextFinder
Class RangeList
flush()
If I misunderstood your question and this was not the result you want, I apologize.
Added:
The proposal from TheMaster's comment was reflected to the script. When sheet.createTextFinder(formula).matchFormulaText(true).replaceAllWith(formula) can be used, also I think that the process cost will be much reduced. But in my environment, it seemed that the formulas are required to be cleared once to refresh the custom function, even if flush() is used. So I have proposed above flow.
But, now I could notice a workaround using replaceAllWith() of TextFinder. So I would like to add it. The flow of this workaround is as follows.
Replace all values of =findRate() to a value in the sheet of Projected Revenue using replaceAllWith()..
In this case, as a test case, the formulas are replaced to sample.
Replace sample to =findRate() using replaceAllWith().
By this flow, I could confirm that =findRate() is recalculated. And also, it seems that flush() is not required for this situation.
Sample script:
Please copy and paste the following script to the script editor. Then, please edit the cells of sheet name of Rates. By this, onEdit() is automatically run by the OnEdit event trigger.
function onEdit(e) {
var range = e.range;
if (range.getSheet().getSheetName() == "Rates" && range.rowStart > 1 && range.columnStart > 1) {
var sheetName = "Projected Revenue";
var formula = "=findRate()";
var tempValue = "sample";
var sheet = e.source.getSheetByName(sheetName);
sheet.createTextFinder(formula).matchFormulaText(true).replaceAllWith(tempValue);
sheet.createTextFinder(tempValue).matchFormulaText(true).replaceAllWith(formula);
}
}