I have a cell (A1) that updates automatically and I would like to use the next cell (B1) to return the max value seen by cell A1. I know nothing about scripts so I google it and found the following script that works but only if A1 doesn't have a formula in it (manually enter a number in the cell but I don't want that). Is there a way to make this work?
function recordMax() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("A1:B1");
var values = range.getValues()[0];
range.setValues([[values[0], Math.max(values[0], values[1])]]);
}
Instead of of changing the values of A1:B1 just change the value of B1.
function recordMax() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("A1:B1");
var values = range.getValues()[0];
sheet.getRange("B1").setValue(Math.max(values[0], values[1]));
}
Related
I'm trying to calculate to cells but not working. This is my code :
function total() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("sheet1");
var cell = sheet.getRange("A3");
var calculate = cell.setFormula("=SUM(A1+A2)");
return calculate
}
My cell is A1 AND A2 I want to put result in cell A3 by add "=total()".
not working but if run from script it work.
I want to put =total() in cell A3 and work without see my formula in sheet.
I wand to send copy of my sheet to people and he can read and edit it.
I don't need people to see my formulas.
or any another way to hide my formulas from people
You need to calculate the result in the script:
function total() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("sheet1");
var values = sheet.getRange("A1:A2").getValues();
var value = values[0][0] + values[1][0];
return value;
}
Alternatively, you can
Calculate normally with formulas in another spreadsheet
Use IMPORTRANGE to import the data from that spreadsheet such that only values but not formulas are display in the cells
However, he cannot make changes to the range directly.
He need to first copy and paste by values.
Your custom formula is returning the return value of the function Range.setFormula(formula), which is a Range. And you want a number. For this you need the values of both cells "A1"and "A2".
Furthermore, if you are using this custom formula to set a value in cell "A3" and not a formula then you can just have the custom formula return the value.
Example:
function total() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("sheet1");
var values = sheet.getRange("A1:A2").getValues();
var value = values[0][0] + values[1][0];
return value;
}
I'm trying to create a data snapshot on google sheets that will automatically run when a specific cell is edited. How should I do that? I'm not from coding background but so far I've found 2 sources and tried to combine them but when I tested it out, it's giving me error. I want to copy values from A2 to E2 of Snapshot sheet and append row every time B2 is changed. Please advise.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Snapshot");
var source = sheet.getRange("A2:E2");
var values = source.getValues();
if(e.range.getA1Notation() == 'B2'){
sheet.appendRow(values[0]);
}}
The B2 in Snapshot is a formula which displays the value of F1 in Receipt sheet. So, the onEdit is not triggered on change of name.
The name changes in F1
I tried the below code and it is working
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var rsht=ss.getSheetByName("Receipt");
var sheet = ss.getSheetByName("Snapshot");
var source = sheet.getRange("A2:E2");
var values = source.getValues();
if(e.range.getA1Notation() == 'F1'){
sheet.appendRow(values[0]);
}}
I'm trying to build a script that will allow me to copy and value paste a range from tab "robert" to tab "brendan". However, the range in "robert" is dynamic, so sometimes it will need to copy and paste A1:M3 or A1:M20. I'd also like it to append to the the first rows of the destination. So when run, the script looks for values on the source tab (robert), copies them, and pastes their values at the top of the destination (brendan) without overwriting existing data.
So far I've worked with the below script from a different thread:
function moveValuesOnly() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getRange('Robert!A1:M100');
source.copyTo(ss.getRange('Brendan!A4'), {contentsOnly: true});
source.clear();
}
The problem here is the script range is static, and it overwrites anything in the destination. I do like the clearing of the source though and the values paste. Any help would be greatly appreciated!
Define the range using variables. Use getLastRow() and getLastColumn() Instead of hard-coding it.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var robWs = ss.getSheetByName("Robert");
var brenWs = ss.getSheetByName("Brendan");
var robLr = robWs.getLastRow()
var robLc = robWs.getLastColumn()
//range starts at row 1 and column 1 (A1), you may need to change accordingly
var vals = robWs.getRange(1,1,lr,lc).getValues;
//paste range also starts at A1. you can find the lr on this sheet and start the range there
brenWs.getRange(1,1,lr,lc).setValues(vals);
function moveValuesOnly() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Robert');
var rg=sh.getActiveRange();//copies active range for source
var vA=rg.getValues();
dsh=ss.getSheetByName('Brendan');
dsr=4;//destination start row
dsc=1;//destination start col
dsa=2;//destination number of rows to append to
drg=dsh.getRange(dsr,dsc,rg.getHeight(),rg.getWidth());
var dvA=drg.getValues();
vA.forEach(function(r,i){
if(i<dsa){
r.forEach(function(c,j){
//only write data in destination for these rows if destination value is null
if(dvA[i][j]='') {
dvA[i][j]=c;
}
});
}else{
dvA[i][j]=c;
}
})
drg.setValues(dvA);
}
In google apps script, with onEdit trigger, how do I get the old values of all the cells if the edited range has multiple cells? In the Event object documentation https://developers.google.com/apps-script/guides/triggers/events it is specified that the oldValue attribute is "Only available if the edited range is a single cell".
In my case, I use onEdit from the Event object to run a function (that needs oldValue and newValue) only when a specific column is edited. It works fine when the user selects only one cell in my specific column, but if the user selects a few cells or the entire row for example, only data from the first selected cell is retrieved but I need to access the oldValue of my specific column.
You want to retrieve old values when the multiple cells are edited.
If my understanding is correct, how about this answer?
Issue:
Unfortunately, in the current stage, when the multiple cells are edited, there are no methods for retrieving all old values from the event object.
Workaround:
So as the current workaround, how about this flow?
Copy the active Spreadsheet.
This is run only one time.
When the cells are edited, the old values are retrieved by comparing the active Spreadsheet and copied Spreadsheet.
Update the copied Spreadsheet.
By above flow, the cycle for retrieving old values when the cells are edited can be created. When this flow is reflected to the script, it becomes as follows. Please think of this as just one of several answers.
Sample script:
When you use this script, please install the OnEdit event trigger to the function of onEditByTrigger() after copy and paste this script to the script editor of the container-bound script. By this, when the cells are edited, you can see the current and old values at the log.
var backupfilename = "backupfile";
function copyToo(srcrange, dstrange) {
var dstSS = dstrange.getSheet().getParent();
var copiedsheet = srcrange.getSheet().copyTo(dstSS);
copiedsheet.getRange(srcrange.getA1Notation()).copyTo(dstrange);
dstSS.deleteSheet(copiedsheet);
}
// This is run only one time.
function init() {
// Source
var srcss = SpreadsheetApp.getActiveSheet();
var range = srcss.getDataRange().getA1Notation();
var srcrange = srcss.getRange(range);
var srcsheetname = srcss.getName();
// Destination
var backupfile = DriveApp.getFilesByName(backupfilename);
var dstid = backupfile.hasNext()
? backupfile.next().getId()
: SpreadsheetApp.create(backupfilename).getId();
var dstss = SpreadsheetApp.openById(dstid).getSheets()[0]
var dstrange = dstss.getRange(range);
dstss.setName(srcsheetname);
copyToo(srcrange, dstrange);
PropertiesService.getScriptProperties().setProperty('backupfileid', dstid);
return dstid;
}
function onEditByTrigger(e) {
var columnNumber = 1; // If you want to retrieve the old values when the column "A" is edited, it's 1.
var source = e.source;
var range = e.range;
var dstid = PropertiesService.getScriptProperties().getProperty('backupfileid');
if (!dstid) {
dstid = init();
}
if (e.range.columnStart == columnNumber) {
var range = source.getSheetName() + "!" + range.getA1Notation();
var fields = "sheets(data(rowData(values(formattedValue,userEnteredFormat,userEnteredValue))))";
var currentValue = source.getRange(range).getValues();
var oldValue = SpreadsheetApp.openById(dstid).getRange(range).getValues();
Logger.log("currentValue %s", currentValue)
Logger.log("oldValue %s", oldValue)
}
// Update backup file
var range = e.source.getDataRange().getA1Notation();
var srcrange = e.source.getRange(range);
var dstrange = SpreadsheetApp.openById(dstid).getSheets()[0].getRange(range);
copyToo(srcrange, dstrange);
}
Note:
This is a sample script for retrieving the old values when the multiple cells were edited. So if you use this script, please modify this to your situation.
References:
Event Objects
Installable Triggers
If this was not the direction you want, I apologize.
I have this script running nicely on Google Sheets:
function recordMax() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("K16:L16");
var values = range.getValues()[0];
range.setValues([[values[0], Math.max(values[0], values[1])]]);
}
But, I have this effect here http://screencast.com/t/BOXzC0UZxFZ (short 1 min video show you the issue). Summary of the issue is that when the script runs in forces K16 to just show the current value of the formula and strips out the =sum formula I have in K16.
What do you think I need to do so that when the script runs, it will not automatically strip the K16 formula so K16 will continue updating to new values?
:)
How about the following modification?
Modification point :
In order to retrieve formulas in the cells, it uses getFormulas().
Insert the retrieved formulas.
Modified script :
In the most cases, the following modified script can be used. I think that in your case, the following modified script can be used.
function recordMax() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("K16:L16");
var formula = range.getFormulas()[0]; // Added
var values = range.getValues()[0];
range.setValues([[formula[0], Math.max(values[0], values[1])]]); // Modified
}
There are sometimes the case that it requires to insert the formula using setFormula() as follows.
function recordMax() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("K16:L16");
var formula = range.getFormulas()[0]; // Added
var values = range.getValues()[0];
sheet.getRange("K16").setFormula(formula[0]); // Added
sheet.getRange("L16").setValue(Math.max(values[0], values[1])); // Added
}
Reference :
getFormula()
getFormulas()
setFormula(formula)
setFormulas()
If I misunderstand your question, please tell me. I would like to modify.