How can I highlight (mark) the active row in google sheets? - google-sheets

The conditional formatting does not help with that. I tried many scripts that are published online but non of them works.
Same issue is here: https://support.google.com/docs/thread/4469470?hl=en

Answer:
Unfortunately, this is not possible to do.
More Information:
The main reaason that thids can't be done is that the Sheets API nor Google Apps Script have listeners for when the active cell on a sheet changes. There are also no clicker or button press listeners, if the clicks or button presses do not make an edit or change to the Sheet.
Testing & Reasoning:
I had a mess around with Apps Script to see if I could create some sort of workaround, though this ended up with encountering other obstacles.
There is a way of making the background of the active row change colour, which can be easily done in Apps Script with something like:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var currRow = ss.getActiveCell().getRow();
sheet.getRange(currRow + ":" + currRow).setBackground("#F4C2C2");
Knowing this, and knowing that I couldn't call a trigger from just a click, I created a Sheets add-on instead with with a JavaScript function embedded in the of the HTML document which calls the Apps Script method at a specific time-interval:
<script>
function poll() {
setInterval(update, 500);
}
function update() {
google.script.run.rowHighlighter();
}
</script>
with the following rowHighlighter() function inside the code.gs file:
function rowHighlighter() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var currRow = ss.getActiveCell().getRow();
var l = PropertiesService.getUserProperties().getProperty("currRow");
if (l) {
sheet.getRange(l + ":" + l).setBackground("#FFFFFF");
}
sheet.getRange(currRow + ":" + currRow).setBackground("#F4C2C2");
PropertiesService.getUserProperties().setProperties({"currRow": currRow});
}
I thought it might be possible to call this function from within the sidebar of the Sheets add-on and use the PropertiesService class of Apps Script to store the currently selected row so that when clicked elsewhere the colour could be reset.
While this appeared to have positive results, this only lasted a few seconds - unfortunately after this the Apps Script quotas get hit and the errors in the console as seen from the Apps Script editor end show that some throttling is needed so not so many Apps Script requests are made. Of course, while this is something that you could do, increasing the interval at which the update() function is called in the add-on <body> reduced the real-timeness of the application and the whole functionality breaks.
In short; this can't be done. Both Apps Script and the Sheets API lack the functionality, and trying to build something that emulates it yourself will end in you using all your quota as the account limitations are hit.
References:
Google Apps Script - Extending Google Sheets
G Suite Developer - Extending Google Sheets with Add-ons
Google Apps Script - Properties Service
Docs editors herlp - Highlight (or mark) the row the current cell is on

function onSelectionChange(e){
const range = e.range;
const sheet = range.getSheet();
const currRow = range.getRow()
const maxRows = sheet.getMaxRows();
const maxColumns = sheet.getMaxColumns();
sheet.getRange(1, 1, maxRows, maxColumns).setFontWeight("normal");
sheet.getRange(currRow, 1, 1, maxColumns).setFontWeight("bold");
}

Regarding Devendra Pathak's solution, how do we tell the script to not act on selections where it is the selected range is lower than row 5? For example, click on A6, the script executes. Click on A1, no changes, A6 remains highlighted. Click on D7, the script executes. Row 6 formatting becomes normal, and row 7 gets the special formatting. As well, how does the script know to only format up to column 7?
Variation below.
https://docs.google.com/spreadsheets/d/1R4GPipk9FyucRcKeXcosbKmXxUTGmuaoQDaUoVDVorU/edit#gid=0
//Seeking: Act only when range is row 6 or higher

Highlight row and column of cell where the mouse is clicked:
function onSelectionChange(e) {
const range = e.range;
const sheet = range.getSheet();
const maxRows = sheet.getMaxRows();
const maxColumns = sheet.getMaxColumns();
sheet.clearConditionalFormatRules();
var formula = '=A1<>"1239"';
//---------------------------------------------------------------
//RULE1
var range1 = sheet.getRange(range.getRow(), 1, 1, maxColumns);
var rule1 = SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied(formula)
.setBackground('lightgray')
.setBold(true)
.setRanges([range1])
.build();
var rules1 = sheet.getConditionalFormatRules();
rules1.push(rule1);
sheet.setConditionalFormatRules(rules1);
//---------------------------------------------------------------
//RULE2
var range2 = sheet.getRange(1, range.getColumn(), maxRows, 1);
var rule2 = SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied(formula)
.setBackground('lightgray')
//.setBold(true)
.setRanges([range2])
.build();
var rules2 = sheet.getConditionalFormatRules();
rules2.push(rule2);
sheet.setConditionalFormatRules(rules2);
}

Related

Convert text format to a value format

I am looking to create a script that will automatically convert a phone number that is cut & pasted into Google Sheets. The phone number is in a text format and I need to change it into a value. Currently, I have to have an additional column(s) for each pasted phone number that converts it. I would like to eliminate having these extra columns.
The formula I am using to do the converting are:
Column C:
=IF(ISBLANK(A3)," ",(VALUE(REGEXREPLACE(A3, "[-]", ""))))
Column D:
=IF(ISBLANK(B3)," ",(VALUE(REGEXREPLACE(B3, "[-]", ""))))
I'm very new to scripts and just starting to learn about it. Any help would be much appreciated. Thank you.
Shared Link
I think what you are looking for is the onEdit-trigger. There is quite a good video on youtube explaining the basics, as well as the general documentation for the onEdit trigger.
I'm no Google AppScript expert, so all I can give you is a sample script that work for Cell A3. I leave it up to you to complete the code and build something that will work with all your cells. ;) The code should be self explaining - especially after watching the linked video above. Most of the code is basic Javascript, so it should be simple to understand.
// source code example for cell A3
function onEdit(e) {
var range = e.range;
var spreadSheet = e.source;
var sheetName = spreadSheet.getActiveSheet().getName();
var column = range.getColumn();
var row = range.getRow();
var inputValue = e.value;
// column 1 is "A", so column 1, row 3 is Cell "A3"
if (sheetName == "Sheet1" && column == 1 && row == 3) {
var number = inputValue.replace(/[-]/, '');
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("A3").setValue([number]);
}
}

Unchanged Cell after filling a condition in google spreadsheet

I want to create a conditional cell formation.
Say Column B has a value that is a live score:
In Column C, I want to create an if condition, like this:
if B>10, then C is YES.
However, as I mentioned, B column as live score, even if B falls below 10 afterward, I want C to remain unchanged. So essentially, I want C to remain at yes, once my live score condition hits.
Please let me know how to do it.
You can use the Apps Script editor with the code below:
function liveScorePass(){
var spreadsheet = SpreadsheetApp.getActiveSheet();
var i = 0;
Logger.log(i);
while (i == 0){
Logger.log('B1');
if (spreadsheet.getRange('B1').getValue() > 10){
spreadsheet.getRange('C1').setValue("YES");
Logger.log('C1');
i = 1;
}
else{
spreadsheet.getRange('C1').setValue("NO");
}
}
}
/* OPTIONAL FUNCTION*/
function onOpen(){
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('Live Score Menu')
.addItem('Reset Script', 'liveScorePass') //creates a menu to start the script again
.addToUi();
var spreadsheet = SpreadsheetApp.getActiveSheet();
liveScorePass(); //starts the script whenever you open the spreadsheet.
}
It basically checks if your cell B1 is greater than 10. If it's not, the script keeps running indefinetly, but when it is, the value of C1 is set to YES and i is set to 1, breaking away from thw while loop, no longer changing the value of C1 independent of the value of B1.
Edit
To use it as a function rather than a tab on the toolbar menu, you can just call it as if it were a formula =LIVESCOREPASS(). However, this implicates three things:
You can't use any set*() methods, so you need to adapt you coding, leaving you with this:
function LIVESCOREPASS(){
var spreadsheet = SpreadsheetApp.getActiveSheet();
var i = 0;
Logger.log(i);
while (i == 0){
Logger.log('B1');
if (spreadsheet.getRange('B1').getValue() > 10){
var result1 = "YES";
Logger.log('C1');
i = 1;
return result1;
}
else{
var result2 = "NO";
return result2;
}
}
}
It won't allow changes in arbitrary cells other than the one you're using or its adjacents (not a problem here);
Every time you update your referenced cell (B1), the function is reset, so you'll lose the fix "YES" if it drops to 10 or below.
Here you can find the documentation on Custom Functions.

Google spreadsheet script for insert new row based on value of cell

Spreadsheet data looks like this
function myFunction()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('Active Listeners');
sh.insertRowBefore(15551)
}
As i have large range of rows that could be work on. If the value of the range matches with "Apr 9" then insert row before to that. Could anyone help me to get that.
A 'for loop' to cycle through your rows from the bottom would almost do the trick. The loop inserts a row after each row specified by i. Keep in mind you'll need a different solution if your Apr 9 column is formatted as a date. This works for plain text only. You can select the column and change to plain text with "Format > Number > Plain Text" on the menu.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('Active Listeners');
//var shlen = sh.getDataRange().getLastRow(); //returns integer last row
var shlen = Browser.inputBox("Enter Last Row of Preferred Range", Browser.Buttons.OK_CANCEL);
var ecell = sh.getActiveCell().getA1Notation();
You may need a different dataRange (below), I've just grabbed the parameters of data in your whole sheet (above), then grabbed a range specified in A1 notation of "A1:B[number reference of bottom row]" The modification may be that you need "B1:C" + [shlen] or whichever other range.
if (shlen >= 1) {
var dataRange = sh.getRange("A1:A" + shlen).getValues();
for (var i = shlen; i > 0; i--) {
var row = dataRange[i-1];
if (row[0] == "Apr 9") {
sh.insertRowAfter(i-1)
}
}}
}
Someone more knowledgeable than me can pitch in if they have a better answer, but my only solution (which should be ok if it's a one-of) would be to just repeat the script a few times, starting at the row of your choice each time. Select cell A1 and then press "control (or command) + down arrow". It will take you to the first gap, which should be where the previous script ended. Remember the row number you're up to and plug that in the input box when you run the script again. Might take a few iterations but you'll get there.
If this process is going to be done repeatedly then best of luck in finding a solution :)

Increment a Google Sheet cell by 1 via App Scripts

I'm trying to increment a number in a Google sheet cell by one, when I custom menu item is clicked. But the result in the spreadsheet is either #NUM! or 1range. I've tried a number of different methods, as shown in the comments in my code.
Note that the number is stored as a custom number format so that it has 4 leading zeros, eg: 00001
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('OrderNumber')
.addItem('Generate next order number', 'menuItem1')
.addToUi();
}
function menuItem1() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange("N11");
range = 1 + +range;
// For the previous line, I've also tried: range = 1 + parseInt(range)
// For the previous line, I've also tried: range = 1 + Number(range)
SpreadsheetApp.getActiveSheet().getRange('N11').setValue(range);
}
As a test if it just set it to a number it shows in the spreadsheet correctly, e.g:
range = 5
SpreadsheetApp.getActiveSheet().getRange('N11').setValue(range);
Any help on this would be greatly appreciated. Thanks.
A Range is an object containing a lot of information: values but also formatting, data validation, font size etc.
You need to call getValue() on range first to extract the number:
var range = sheet.getRange("N11").getValue();

How to add and remove a character from a cell to force a value change

I'm using a function to count the number of colored cells, but when they change color (not value), the spreadsheet doesn't recognize a value change and my formula doesn't update with the new number of colored cells.
To manually force an update, I have to add a character to that cell, then remove it, so that the sheet will recognize a value change and recount the number of colored cells. Is there a way to automate this and force the sheet to add and remove a character in order to force an update?
Hopefully, this is clear enough to be answerable.
You can simply use onEdit function if there is any data update on the cells. But for your case, I have tested below scripts works good, but I am still confused it is the best practice of coding, because I could not find any other options to solve your question.
//Below function will count the number of cells with the specified background color
function countWhereBackgroundColorIs(color, rangeSpecification) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange(rangeSpecification);
var bgColors = range.getBackgrounds();
var k = 0;
for (var i in bgColors) {
for (var j in bgColors[i]) {
if(bgColors[i][j] == color)
k = k +1;
}
}
return k;
}
//Below function will append a space" " on the cell A1 data and then remove the appended char. This is for updating the range. Make sure that at least a cell mentioned in above function countWhereBackgroundColorIs() is getting updated. Here Used 'A1'
function updateSheet()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var cell = sheet.getRange("A1");
var d = cell.getValue();
cell.setValue(d+" ");
SpreadsheetApp.flush();
cell.setValue(d);
SpreadsheetApp.flush();
}
//creating a time based trigger to execute the updateSheet() function for every one min. Minimum time is 1min. This trigger creation is a one time activity and this can be done in GUI also Resources>All your triggers.
function createTimeDrivenTriggers() {
ScriptApp.newTrigger('updateSheet')
.timeBased()
.everyMinutes(1)
.create();
}

Resources