How to add two variables together in sheets script? - google-apps-script

I'm trying to make a script that adds the value of one cell to another one before I clear the first cell. Unfortunately, all my attempts to add the second one have given errors. This is my latest one: I get a NUM error here. what do I do?1

You can use onEdit simple trigger, which will give you access to oldValue of cell which was edited and you can use that value to add it with column B.
Based on your this problem statement, try this sample script:-
function onEdit(e)
{
const range = e.range;
const sheet = range.getSheet();
const row = range.getRow();
const column = range.getColumn();
var oldValue = e.oldValue;
if(column === 1)
{
const colB = sheet.getRange(row,column+1); // Getting Column B value
var colB_Value = colB.getValue();
oldValue = isNaN(Number(oldValue)) ? 0 : Number(oldValue)
colB.setValue(oldValue + colB_Value) // adding old value of column A with B and setting it on Column B
}
}
Reference:
OnEdit()
Event Objects
isNaN

Related

Creating unique ID only for new rows when they are added

I have a Google Sheet (with header row) and I need to create a uniqueID for each new row as it's added.
I can create the ID like this (an AppsScript)
function generate() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const row = sheet.getLastRow();
const randomUnique = `${Math.random().toString(36).slice(2)}-${Date.now()}`
}
and I call the function like this
=ArrayFormula(IF(ISBLANK(A2:A),,generate()))
Simply if there is a value in Column A create the ID
BUT when I add the final line to the generate() function I always get an error
This is the final line
sheet.getRange(row,2 ).setValue(randomUnique);
This is the error
You do not have permission to call setValue()
To summarise, when row X column A has a value I need to have the ID created and inserted into row X Column B
Once set that ID must not change
How do I correct the function / formulas - thanks in advance
You need to return a value.
function generate() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const activeRange = sheet.getActiveRange();
//stop recalc, if needed:
//if(activeRange.getValue() !== '') return activeRange.getValue();
const activeRow = activeRange().getRow();
const lrow = sheet.getLastRow();
const randomUnique = () => `${Math.random().toString(36).slice(2)}-${Date.now()}`
return randomUnique();
//or return Array(lrow-activeRow).fill("").map(_ => [randomUnique()])
}
Unfortunately, in the current stage, setValue cannot be used with the custom function. And also, when the values are put with the custom function, the values are changed by the recalculation. So, in this case, in order to achieve your goal of To summarise, when row X column A has a value I need to have the ID created and inserted into row X Column B and Once set that ID must not change, how about using a Google Apps Script as not the custom function? The sample script is as follows.
Sample script:
function mYFunction() {
const sheetName = "Sheet1"; // Please set your sheet name.
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
const lastRow = sheet.getLastRow();
const values = sheet.getRange("A2:B" + lastRow).getDisplayValues().map(([a, b]) => [a && b ? b : a && !b ? `${Math.random().toString(36).slice(2)}-${Date.now()}` : ""]);
sheet.getRange("B2:B" + lastRow).setValues(values);
}
When this script is run, the columns "A" and "B" are checked. When there are the value of column "A" and no value of column "B", ${Math.random().toString(36).slice(2)}-${Date.now()} is used. When there are the value of columne "A" and "B", the value of column "B" is not changed.
References:
Custom Functions in Google Sheets
map()

Google Sheets script: Using a term in one cell to delete a row on another page

I’m trying to find a way to delete a row on one sheet based on a row selected by a checkbox on another sheet, using an onEdit function.
The checkbox is in Column A on Sheet1; the row is variable, since Sheet1 is a search page. The unique search result / search string is in Column B. The records that I want to delete from this search page are on a second sheet, Sheet2. In Sheet2, some of the same data is duplicated from Sheet1, but there’s no checkbox. So, the unique identifier in Column B on Sheet1 is Column A on Sheet2, and that’s where I want the deletions to happen. In Sheet2, the Column A values are always unique, so I wouldn't think this calls for an array.
So, to summarize, this script would say: if a row on Sheet1 is checked, look at the value of Column B in that row. Then, search Column A in Sheet2. If matched, deleteRow. So, my question is: How would this script be written?
However, there’s one slight complication, which I hesitate to mention for fear that the question will face closure due to “lack of focus.” (so, if you just want to answer the above and ignore this bit, that's still wonderful!). I'm only asking because I feel like it affects how the script would be coded in the first place. I only want this deletion to happen if Column E on Sheet1 says Indirect. If Column E is blank, or contains other text, then the script runs as follows:
function onEdit(e) {
if (e.range.columnStart != 1) return;
if (e.value != 'TRUE') return;
var sheet = SpreadsheetApp.getActive();
var ignored_sheets = ['Sheet2','Sheet3'];
if (ignored_sheets.includes(sheet.getName())) return;
if(e.range.getSheet().getRange(e.range.getRow(),5).getValue().length > 0){
sheet.toast("Can't overwrite data.");
sheet.getActiveCell().setValue(false);
return;};
var row_index = e.range.rowStart;
var row = sheet.getRange('B' + row_index + ':D' + row_index).getDisplayValues().flat();
if (row[1] == '') return;
var result = SpreadsheetApp.getUi()
.alert("Append record?", SpreadsheetApp.getUi().ButtonSet.OK_CANCEL);
if (result != SpreadsheetApp.getUi().Button.OK) {
sheet.toast("Operation canceled.");
sheet.getActiveCell().setValue(false);
return;}
sheet.toast("Operation complete.");
sheet.getActiveCell().setValue(false);
sheet.getRange('B3').clearContent();
sheet.getSheetByName('Sheet2').appendRow(row);
sheet.getSheetByName('Sheet1').setActiveCell('B3');
}
As per problem statement you mentioned in comments:-
The third function I want to add is the ability to delete records, if
their column E value is "Indirect"
Sample script will look like this :-
function onEdit(e)
{
const value = e.value
const range = e.range
const sheet = range.getSheet();
const row = range.getRow();
const column = range.getColumn();
const ss = SpreadsheetApp.getActiveSpreadsheet();
const checkValue = sheet.getRange(row, 5).getValue(); // Column E value
if(column === 1 && value == 'TRUE' && checkValue === 'Indirect')
{
const ref_IDtoSearch = sheet.getRange(row, 2).getValue(); // ref id in sheet 1
const targetSheet = ss.getSheetByName('Sheet2')
const refRange = targetSheet.getRange('A1:A').getValues().flat(); // Range ref column in sheet 2
const posRow = refRange.indexOf(ref_IDtoSearch)
if(posRow > -1)
{
targetSheet.deleteRow(posRow+1)
}
}
}
Incorporate it in your existing onEdit code.
Reference:
deleteRow()

onEdit function where action in specific column sets value for corresponding row in the next column over

I'm trying to work out a google scripts onEdit function that is only triggered by one specific column, and will set the value in the same row on the next column.
The script should set the value (new Date()) in column D when a cell in column C is edited, and should be limited to rows after row 7.
Currently I have one that kinda works, but it works when you edit any cell in the sheet, so it's not ideal. I've been googling and reading for a while to no avail. Any help would be greatly appreciated.
Here's the code I currently have:
function onEdit() { //Function to add a time stamp to Complete Time Column D
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range= sheet.getActiveCell();
var row = range.getRow();
if(row>7){
sheet.getRange(row, 4).setValue(new Date());
}
}
Explanation:
You should take advantage of the event object and use it to find
the active sheet and active range.
The following script will set a new date in column D when a cell in column C is edited, but after row 7.
You are very close. In the same way you use var row = range.getRow(); you can also use var row = range.getColumn(); and put that as a constraint to be 3 (column C).
The script will work for the active sheet. You might want to restrict this functionality to a particular sheet (e.g. Sheet1). If yes, then change the if condition to something like this:
if(as.getName() == 'Sheet1' && row>7 && col==3)
Solution:
function onEdit(e) {
const row = e.range.getRow();
const col = e.range.getColumn();
const as = e.source.getActiveSheet();
if(row>7 && col==3){
as.getRange(row, 4).setValue(new Date());
}
}

Automatically Add a Note Based on Dynamic Cell in Google Sheets

I am trying to modify a Script in Google Sheets that creates a Note that contains the content of the Cell it lives in. I think I'm almost there- however, the script I have below only references a static cell. I need it to create a note within each cell in Column C, with each note referencing the text in the specific cell it is assigned.
For example:
C1 contains "TEST", C1 Note shows "TEST"
C2 contains "HELLO", C2 Note shows "HELLO"
C3 contains "WORLD", C3 Note shows "WORLD"
Here is the script that I have currently:
function addNote() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var targetCell = sheet.getRange("C3");
var sourceCell = sheet.getRange("C3");
var noteText = sourceCell.getValue();
targetCell.setNote(noteText);
}***
Appreciate any help that can be provided- also, would be great if this could update the content of the note when the spreadsheet is updated, if anyone knows how to append that.
You want to set the values of column "C" to the notes of the same column.
The values for the notes are the same with the values of cells of column "C".
For example, when the cell "C1" has "TEST", you want to set "TEST" to the note.
When the values of column "C" in 1st tab of active Spreadsheet is edited, you want to update the notes.
You want to achieve this using Google Apps Script.
From your question and your replying comments, I could understanding like above. If my understanding is correct, how about this sample script? Please think of this as just one of several answers.
In this sample script, I used a simple trigger. By this, when the column "C" of the 1st tab is edited, the script is run and the notes of column "C" are updated using the values of column "C".
Sample script:
Please copy and paste the following script and save the script. When you edit the cell of the column "C" in the 1st tab of active Spreadsheet, the script is run and the notes are set with the values of column "C".
function onEdit(e) {
var sheet = e.source.getSheets()[0];
if (e.range.getSheet().getSheetName() === sheet.getSheetName()) {
var range = sheet.getRange("C1:C" + sheet.getLastRow());
var values = range.getValues();
range.setNotes(values);
}
}
References:
Simple Triggers
Event Objects
getValues()
setNotes(notes)
The following script will create a note using the text from the cell that is being edited. The cell must be in the third column ("C"). To change the column that can be edited, change the 3 to the correct column number (A=1,B=2,C=3,etc...)
function onEdit(e){
var range = e.range;
if (range !== 3) return;
range.setNote(e.value);
}
You may want to go a step further and clear the cell after creating the note. Here is an example of that:
function onEdit(e){
var range = e.range;
if (range.getColumn() !== 3) return;
range.setNote(e.value);
range.clearContent();
}
I have done something like this before and found it useful to be able to keep adding notes by entering values into the cell. Here's how you can do that:
function onEdit(e){
var range = e.range;
var newNote = '';
var cellValue = e.value;
if (range.getColumn() !== 3) return;
var previousNote = range.getNote() ? range.getNote() : '';
if (previousNote) {
newNote = cellValue + '\n\n' + previousNote;
} else {
newNote = cellValue;
}
range.setNote(newNote);
range.clearContent();
}

Set an installable edit trigger to fire for a selected cell or range only

What I mean is something like this except this one works for simple triggers:
function onEdit(e)
{
var range = e.range;
var columnOfCellEdited = range.getColumn();
var rowOfCellEdited = range.getRow();
if ( columnOfCellEdited === 2 && rowOfCellEdited === 1 )
{
doSomething();
}
};
What I could think of is
saving the recent value of the given cell into another cell by every occasion the sheet
is edited and check if the value has changed since the last call.
However this solution is pretty far from classy.
Also do you know any more appropriate ways to restrict the range of the function which is called by an installable trigger?