Apps Script: Setfont italics for active row based on trigger cell - google-apps-script

thanks in advance for any help.
I want to trigger italicizing the entire row if column 13 of the row contains "y" (ideally if there is a way to set font as normal if not containing "y" that would be grand too)
Here's what I tried (it's part of an onEdit nest). Currently it is only making the trigger column italics rather than the whole row as I am wanting.
function onEdit(e)
{
//Formula to run
{
spreadsheetWizard(e);
spreadsheetWizardII(e);
spreadsheetWizardIII(e);
moveRow(e);
}
}
function spreadsheetWizardIII()
{
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getActiveSheet()
var range = sheet.getActiveRange()
var editrow = range.getRow()
var trigger = sheet.getRange(editrow,13)
// Header Rows to ignore
if(range.getRow() <= 1) return;
// Sheet(s) to include / exclude
if(sheet.getName() !== 'Masterlist') return;
// Trigger Column
if(range.getColumn() != 13) return;
if(trigger.getValue() == "y")
{
editrow.setFontStyle('italic');
}
}

Related

Installable Triggers to use multiple onEdit

I have created 2 functions that run onEdit (tested and working when named onEdit)
The first one sets the value (new Date) of a row >7 in Column D onEdit of Column C.
function CompleteTime() { //Function to add a time stamp to Complete Time Column D
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = sheet.getActiveCell();
var row = range.getRow();
var col = range.getColumn()
if(row>7 && col==3){
sheet.getRange(row, 4).setValue(new Date());
}
}
The second one sets a formula in Row 8 Column E onEdit of Row 8 Column D
function Duration() { //Function to set formula in column E to calculate duration from start time to first complte time
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = sheet.getActiveCell();
var row = range.getRow();
var col = range.getColumn()
if(row==8 && col==4){
sheet.getRange(row, 5).setFormula("=SUM(D8-B3)");
}
}
I have created 2 installable triggers to run these functions onEdit, and the first one runs fine, but the second one doesn't trigger the first one. The value that is entered by the first function doesn't trigger the second function.
Everything I've read suggests this is the way to get multiple onEdits to run in a single sheet, but I am stuck here.
One of the restrictions of triggers is that "Script executions and API requests do not cause triggers to run", meaning that you need to manually include the Duration() call after inserting the completion time.
The example below isn't the only way to accomplish this, but it should give you an idea of what I'm trying to describe.
function onEdit(e) {
var row = e.range.rowStart;
var col = e.range.columnStart;
if (row == 8 && col == 4) {
insertDurationFormula(e.range.offset(0, 1));
} else if (row > 7 && col == 3) {
insertCurrentTime(e.range.offset(0, 1));
insertDurationFormula(e.range.offset(0, 2));
}
}
function insertCurrentTime(cell) {
cell.setValue(new Date());
}
function insertDurationFormula(cell) {
cell.setFormula("=SUM(D8-B3)");
}
Also note that I'm using the event object included with edit triggers. Using the event object can help simplify your code a bit and reduce unnecessary calls.
It is not good practice to have multiple onEdit triggers in one spreadsheet
In case of simple onEdit triggers, it is not possible to have more than one per Apps Script project, in case of installable ones - it can cause to conflicts.
Instead, have only one function bound on a trigger and call from there on other function depending on the condition.
Sample:
function bindmeOnTrigger() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = sheet.getActiveCell();
var row = range.getRow();
var col = range.getColumn()
if(row==8 && col==4){
function1();
} else if(row>7 && col==3){
function2();
}
}
function function1(){
...
}
function function2(){
...
}
Or simply:
function bindmeOnTrigger() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = sheet.getActiveCell();
var row = range.getRow();
var col = range.getColumn()
if(row==8 && col==4){
sheet.getRange(row, 5).setFormula("=SUM(D8-B3)");
} else if(row>7 && col==3){
sheet.getRange(row, 4).setValue(new Date());
}
}

Clear the contents of each row in a column on one sheet, depending on the change in a column on the same row on another sheet

I'm struggling with this code, which works perfectly inside the same sheet, to get it work between two sheets. For an example if I change a content in cell E5 or in multiple cells in E column on "Sheet1", this clears a content in Cell A5 or in multiple cells in A column, depending on the row they are in.
function onEdit(e){
var range = e.range;
var row = range.getRow();
// Check if column E and sheet "Sheet1"
if(range.getColumn() == 5 && range.getSheet().getName() == "Sheet1")
{
if(range.getHeight()>1)
{
// Multiple cells selection case
var nbRow = range.getNumRows();
var i;
for(i =0; i < nbRow; i++)
{
var temp = row + i;
e.source.getRange("A"+temp).clear();
}
}
else
{
// One cell selection case
e.source.getRange("A"+row).clear();
}
}
}
Could any of you guys please help me with the code to get it work between two sheets, because it's already driving me crazy :/
Any help would be greatly appreciated!
Change in one sheet clears range in another sheet
function onEdit(e){
var sh=e.range.getSheet();
if(sh.getName()=='Sheet1' && e.range.columnStart==5) {
var sh2=e.source.getSheetByName('Sheet2');
sh2.getRange(e.range.rowStart,1,e.range.rowEnd-e.range.rowStart+1,1).clearContent()
}
}
Question: What should I do to the code so it starts on the fifth row? First four rows are frozen. (Probably header info)
function onEdit(e){
var sh=e.range.getSheet();
if(sh.getName()=='Sheet1' && e.range.columnStart==5 && e.range.rowStart>4) {
var sh2=e.source.getSheetByName('Sheet2');
sh2.getRange(e.range.rowStart,1,e.range.rowEnd-e.range.rowStart+1,1).clearContent()
}
}
Animation:

How to repeat a google script function on every row in a column?

I have a google app script, that clears cells L2 and M2 if there is a change in cell B2.
I would like to apply this to the whole range of B2:B in case of change, it should clear the cell that matches their row. So for example if there is a change in B5, it should clear L5 and M5.
Can anyone help me or point me in the right direction? I just searched through here for 1h and couldn't make it happen.
Many thanks!
function onEdit(e){
if(e.range.getA1Notation() == "B2" &&
e.range.getSheet().getName() == "Sheet3"
)
e.source.getRange("L2").clear() &&
e.source.getRange("M2").clear()
}
You just need to get the row from range (See getRow() method from the documentation), and you could use it directly, like:
function onEdit(e){
var row = e.range.getRow();
if(e.range.getA1Notation() == "B"+row && e.range.getSheet().getName() == "Sheet3")
{
e.source.getRange("L"+row).clear();
e.source.getRange("M"+row).clear();
}
}
But your code only handle single cell selection. Here is a evolution, handling multiple cell selection:
function onEdit(e){
var range = e.range;
var row = range.getRow();
// Check if column B and sheet "Sheet3"
if(range.getColumn() == 2 && range.getSheet().getName() == "Sheet3")
{
if(range.getHeight()>1)
{
// Multiple cells selection case
var nbRow = range.getNumRows();
var i;
for(i =0; i < nbRow; i++)
{
var temp = row + i;
e.source.getRange("L"+temp).clear();
e.source.getRange("M"+temp).clear();
}
}
else
{
// One cell selection case
e.source.getRange("L"+row).clear();
e.source.getRange("M"+row).clear();
}
}
}

How To transform OnEdit script to Run-by-button script (copy cells from 1 sheet to another with rule)

I've made a well-working script to copy cells *OnEdit (col16 on sheet 2) if any row in Col16 = "Yes") to last row of custom column on sheet 1(now Col4). But I have a Query based data on sheet 2, so my script copies data only when I type "Yes" by hands. That's why now I need to run this script by button, or maybe as a time-driven trigger. Can't get it to work by button. How to change the following script to make it possible to work by clicking on button?
function onEdit(e) {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
if (sheet.getName() !== '2' || e.range.getColumn() !== 16 || e.value !== 'Yes') return;
var value = e.range.offset(0,-12,1,1).getValue();
sheet = e.source.getSheetByName('1');
var grd = sheet.getRange("D:D").getValues();
var maxIndex = grd.reduce(function(maxIndex, row, index) {
return row[0] === "" ? maxIndex : index;
}, 0);
sheet.getRange(maxIndex+2,e.range.getColumn()-12,1,1).setValue(value);
}
UPDATE: I've tried to change my script like this, assigned it to button, and after clicking on button- it say "Running..... then Finished..." but it don't copy anything (but it works when it's OnEdit(e), and I m not getting any error.
But it seems it's not enough just change "OnEdit(e)" to "copymissings()", I need to change something in code, but I don't know what exactly. Please help:
function copymissings() {
var s = SpreadsheetApp.getActive();
if (s.getName() !== '2' || range.getColumn() !== 16 || value !== 'Yes') return;
var value = range.offset(0,-12,1,1).getValues();
sht = s.getSheetByName('1');
var grd = sheet.getRange("D:D").getValues();
var maxIndex = grd.reduce(function(maxIndex, row, index) {
return row[0] === "" ? maxIndex : index;
}, 0);
sht.getRange(maxIndex+2,range.getColumn()-12,1,1).setValues(value);
}
Visualisation:
CLICK TO SEE GIF
I think you're mixing two concepts here. onEdit() is a trigger that runs AUTOMATICALLY when a user changes the value of a cell. However what you're trying to do is MANUAL, as the user is in charge when the event will trigger.
Refer to HTML Service: Create and Serve HTML on how create UI buttons. You can check actual samples here.
Okay big thanks to Edward Ulle from "Plus" google apps script forum.
We've made working version of same script as I offered in post which is automatically working OnEdit.
The following script copies cells from Sheet-2 Col4 if that row contains "Yes" in col16 to Sheet-1 col4. Everything optional.
function copymissings() {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Source sheet
var shs = ss.getSheetByName("2");
// Values from Sheet2
var vs = shs.getRange(1,1,shs.getLastRow(),shs.getLastColumn()).getValues();
// Destination sheet
var shd = ss.getSheetByName("1");
// Get the destination range
var rd = shd.getRange("D:D");
// Gets a 2D array
var vd = rd.getValues();
var j = 1;
// Get offset j to first empty row
for( j=0; j<vd.length; j++ ) {
if( vd[j][0] == 0 ) break;
}
// Assuming you want to do for every row in Sheet2
for( var i=0; i<vs.length; i++ ) {
if( vs[i][15] == "Yes" ) { // Column 16 is index 15
// Use offset from last row of destination sheet
rd.offset(j,0,1,1).setValue(vs[i][3]); // Copy to column 4 (0)
j++; // Increment to next row
}
}
}
catch(err) {
Logger.log(err);
}
}

GoogleScript: How to CopyRow before Delete the same

Situation:
I find this script, that delete the rows when the text in the column B change to "Closed". I want to copy the row before to delete into other sheet called historic.
Action:
The script should be copy the row when the the status is "Closed" in other sheet called "Historic" in the same spreadsheeet.
Then when the first point is completed should be delete the rows in the activesheet.
SCRIPT DELETE ROWS:
function DeleteRow(e) {
try {
var ss = e.source; // Just pull the spreadsheet object from the one already being passed to onEdit
var s = ss.getActiveSheet();
// Conditions are by sheet and a single cell in a certain column
if (s.getName() == 'ISP1' && // change to your own
e.range.columnStart == 2 && e.range.columnEnd == 2 && // only look at edits happening in col 2 which is 2
e.range.rowStart == e.range.rowEnd ) { // only look at single row edits which will equal a single cell
checkCellValue(e);
}
} catch (error) { Logger.log(error); }
};
function checkCellValue(e) {
if ( e.value == 'Closed') { // Delete if value is zero or empty
e.source.getActiveSheet().deleteRow(e.range.rowStart);
}
}
SCRIPT HISTORIC:
This script when somone update the column 5 will copy the row to other sheet called "historic".
When somone change the column 9 and select the status "Closed" the script copy the row to the historic and insert the closed date.
Now, does exist any why to do the same and improve the perfomance? I think this script is very complex and use many line.. I don't know if possible do the same better.
function Historic(e) { //CopyRows
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var r = SpreadsheetApp.getActiveRange();
var date = Utilities.formatDate(new Date(), "GMT-3", "dd/MM/yyyy HH:mm"); // Function Date + Format
// Get the row and column of the active cell.
var rowIndex = r.getRowIndex();
var colIndex = r.getColumnIndex();
// Get the number of columns in the active sheet.
var colNumber = s.getLastColumn();
// Move row based on criteria in column 5, and if row is not the header.
if (colIndex == 5 && rowIndex != 1) {
// Get value from column 5, in the active row.
var status = s.getRange(rowIndex, colIndex).getValue();
// Do nothing if criteria value is not actually changed to something else.
if (s.getName() != 'Historic') {
// The target sheet is the one with the same name as the criteria value.
var targetSheet = ss.getSheetByName('Historic');
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(rowIndex, 1, 1, colNumber).copyTo(target);
//s.deleteRow(rowIndex); // This line delete the source row
targetSheet.getRange(targetSheet.getLastRow(), 11).setValue(s.getSheetName()); //Insert in the Column 11 the SheetName where was modify that line
}
}
else if (colIndex == 9 && rowIndex != 1 && e.value == 'Closed' ) {
// Get value from column 5, in the active row.
var status = s.getRange(rowIndex, colIndex).getValue();
// Do nothing if criteria value is not actually changed to something else.
if (s.getName() != 'Historic') {
// The target sheet is the one with the same name as the criteria value.
var targetSheet = ss.getSheetByName('Historic');
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(rowIndex, 1, 1, colNumber).copyTo(target);
targetSheet.getRange(targetSheet.getLastRow(),10).setValue(date); //This Line Insert Close Date when the user select option Close
targetSheet.getRange(targetSheet.getLastRow(),11).setValue(s.getSheetName()); //Insert in the Column 11 the SheetName where was modify that line
e.source.getActiveSheet().deleteRow(e.range.rowStart); // This line delete the source row
}
}
}
I see somone vote this question -1. I'm using the Historic the second part, this part copy and then delete the row.
If anyone have a better idea, I will appreciate your help.
Thanks So much