I have named ranges with all the same number of rows (21), all named ranges begin with a cell containing a date. I would like to hide all rows below their date cell when that date is older than today's date. Or, hide the associated 21 rows immediately following the date. I am ignorant as to how to write scripts, but I will learn. I also found I cannot ask a question well, very sorry.
I found a script in stackoverflow to hide a row with a date earlier than today:
function hideRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("MON");
var v = s.getRange("A:A").getValues();
var today = new Date();
today.setHours(0, 0, 0, 0);
for (var i = s.getLastRow(); i > 2; i--) {
var t = v[i - 1];
if (t != "") {
var u = new Date(t);
if (u < today) {
s.hideRows(i);
}
}
}
}
When the sheet is opened I expect the row with the date earlier than today to cause the next 21 rows to be hidden.
Try this:
This gets all of the ranges on the active sheet
function hideNamedRange() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rgA=sh.getNamedRanges();
var dv=new Date(new Date().getFullYear(),new Date().getMonth(),new Date().getDate()).valueOf();
for(var i=0;i<rgA.length;i++) {
var vA=rgA[i].getRange().getValues();
if(vA[0][0] && new Date(vA[0][0]).valueOf()<dv) {
sh.hideRows(rgA[i].getRange().getRow(), rgA[i].getRange().getHeight());
}
}
}
This does the same thing for the spreadsheet
function hideNamedRange() {
var ss=SpreadsheetApp.getActive();
var rgA=ss.getNamedRanges();
var dv=new Date(new Date().getFullYear(),new Date().getMonth(),new Date().getDate()).valueOf();
for(var i=0;i<rgA.length;i++) {
var rg=rgA[i].getRange();
var sh=rg.getSheet();
var vA=rg.getValues();
if(vA[0][0] && new Date(vA[0][0]).valueOf()<dv) {
sh.hideRows(rgA[i].getRange().getRow(), rgA[i].getRange().getHeight());
}
}
}
Related
I have a workbook with 6 similar sheets. And I have one script which helps me to protect the rows according to date in column A. Each row has a date. The rows are sorted according to the date, and we add information with a new date and data almost every day. When the date is before today, the row becomes protected, so we can enter new info in the row with current date and the future.
So, for today the yellow rows are protected. Here is the link for the worksheet.
The script I use:
function onOpen(e) {
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ISKUR");
var dateRange = sh.getRange(6, 1, sh.getLastRow()-2, 1);
var val = dateRange.getDisplayValues();
var curDate = Utilities.formatDate(new Date(), "GMT+3", "MM/dd/YYYY");
var protectRow;
//check if date is less than the current date
for(var i = 0; i < val.length; i++){
if(val[i][0]>=curDate){
protectRow = i;
break;
}
}
var protection = sh.getProtections(SpreadsheetApp.ProtectionType.RANGE);
//If protection exists, update else add new one.
if(protection.length > 0){
var range = sh.getRange(6, 1, protectRow, 13);
protection[0].setRange(range);
}else{
sh.getRange(6, 1, protectRow, 13).protect();
}
}
function onOpen(e) {
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var dateRange = sh.getRange(6, 1, sh.getLastRow()-2, 1);
var val = dateRange.getDisplayValues();
var curDate = Utilities.formatDate(new Date(), "GMT+3", "MM/dd/YYYY");
var protectRow;
//check if date is less than the current date
for(var i = 0; i < val.length; i++){
if(val[i][0]>=curDate){
protectRow = i;
break;
}
}
var protection = sh.getProtections(SpreadsheetApp.ProtectionType.RANGE);
//If protection exists, update else add new one.
if(protection.length > 0){
var range = sh.getRange(6, 1, protectRow, 13);
protection[0].setRange(range);
}else{
sh.getRange(6, 1, protectRow, 13).protect();
}
}
It seems that it doesn't work correctly for several pages. How can I protect rows using this script in several sheets, if all of them have a similar structure (date in column A)?
Issue:
You can't have multiple onOpen triggers.
Solutions:
Solution 1 (recommended): execute your code for multiple sheets like that:
This code assumes you can run the same code for every sheet you specify in the sheetNames array:
function onOpen(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetNames = ['ISKUR','Sheet1']; // put the names of the sheets you want to run the script
sheetNames.forEach(name=>{
var sh = ss.getSheetByName(name);
var dateRange = sh.getRange(6, 1, sh.getLastRow()-2, 1);
var val = dateRange.getDisplayValues();
var curDate = Utilities.formatDate(new Date(), "GMT+3", "MM/dd/YYYY");
var protectRow;
//check if date is less than the current date
for(var i = 0; i < val.length; i++){
if(val[i][0]>=curDate){
protectRow = i;
break;
}
}
var protection = sh.getProtections(SpreadsheetApp.ProtectionType.RANGE);
//If protection exists, update else add new one.
if(protection.length > 0){
var range = sh.getRange(6, 1, protectRow, 13);
protection[0].setRange(range);
}else{
sh.getRange(6, 1, protectRow, 13).protect();
}
});
}
Solution 2: create multiple functions for every sheet:
This solution is recommended in case you want to run different code for different sheets:
function onOpen(e){
onOpen1(e);
onOpen2(e);
}
function onOpen1(e) {
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
// rest of the code
}
function onOpen2(e) {
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ISKUR");
// rest of the code
}
That solution becomes handy in case different sheets have different structure or you want to apply a unique logic for individual sheets.
I have used a code found in another post (thank you very much, see below), to make a sheet open on Today's date.
Please, could you advise where I would need to add "+7" (or something else) to make it open on the date a week from now (Today + 7 days)?
How do I get my google spreadsheet to open to today's date?
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("1:1");
var values = range.getValues();
values = values[0];
var day = 24*3600*1000;
var today = parseInt((new Date().setHours(0,0,0,0))/day);
Logger.log(today);
var ssdate;
for (var i=0; i<values.length; i++) {
try {
ssdate = values[i].getTime()/day;
}
catch(e) {
}
if (ssdate && Math.floor(ssdate) == today) {
sheet.setActiveRange(range.offset(0,i,1,1));
break;
}
}
}
Try this:
function onOpen() {
var ss=SpreadsheetApp.getActive();
var sheet=ss.getActiveSheet();
var range=sheet.getRange("1:1");
var values=range.getValues()[0];
var today=new Date();
var nextweek=new Date(today.getFullYear(),today.getMonth(),today.getDate()+7);
for (var i=0;i<values.length;i++) {
var ssdate = values[i].getTime()/86400000;
if (ssdate && Math.floor(ssdate) == nextweek) {
sheet.setActiveRange(range.offset(0,i,1,1));
break;
}
}
}
Here is a link to my document:
https://docs.google.com/spreadsheets/d/1wBpeCUTmePD3N5CDz57LeBBWZHnSwrX-5b6XscdbB4s/edit?usp=sharing
I want the document to open to today's date or to the Monday of each week.
Please help.
Thanks in advance.
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("A:A");
var values = range.getValues();
var day = 24*3600*1000;
var today = parseInt((new Date().setHours(0,0,0,0))/day);
var ssdate;
for (var i=0; i<values.length; i++) {
try {
ssdate = values[i][0].getTime()/day;
} catch(e) { }
if (ssdate && Math.floor(ssdate) == today) {
sheet.setActiveRange(range.offset(i,0,1,1));
break;
}
}
}
The main issue in your attempt is that you grabbed column A, but your dates exist in row 2. Try this:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("2018"); // Specifiy the sheet
var range = sheet.getRange("2:2"); // Row 2
var values = range.getValues()[0]; // This is a 2-dimensional array in the form [[row1-col1, row1-col2],[row2-col1,row2-col2]].
// Because we only pulled one row (Row 2), we can immediately select just that row by appending the [0]
var today = new Date();
var todayDate = today.getDate();
var todayMonth = today.getMonth();
var todayYear = today.getFullYear();
for (var i=0; i<values.length; i++) {
var columnDate = new Date(values[i]);
if (columnDate.getDate() === todayDate && columnDate.getMonth() === todayMonth && columnDate.getFullYear() === todayYear) {
sheet.getRange(1, i+1).activate();
break;
}
}
}
I found this solution but am struggling to get it to work on my sheet.
The user who submitted that question had 3 header rows and wanted the script to only work on row 4 and down. I have 1 header, and as such need the script to work on row 2 and down.
I've got it leaving row 1 alone - but it ONLY hides rows 2 and 3. I can't figure out where I'm going wrong.
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuItems=[{name: 'HideRows', functionName: 'hideRows'}];
ss.addMenu('Hide Rows', menuItems);
};
function hideRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Responses");
var v = s.getRange("B:B").getValues();
var today = new Date();
var m = today.getMonth();
for(var i=3;i<v.length;i++)
if(v[i][0]=="" || v[i][0].getMonth()>=m) break;
if(i>1) s.hideRows(2,i-1)
};
ETA: Here's a link to my sheet/script: https://docs.google.com/spreadsheets/d/1PkB1_hlJoI-iFYTAN8to_ES9R8QyUxEgPsWtSTUmj8U/edit?usp=sharing
function hideRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Responses');
// start range from B2 skipping header
// join() + split(',') converts 2D array into plain array
// filter(Boolean) skips all the blank cells in column
var v = s.getRange('B2:B').getValues().join().split(',').filter(Boolean);
// today in milliseconds for date comparison
var today = new Date().getTime();
// one month in milliseconds
var oneMonth = 2629746000;
Logger.log(v.length);
for (var i=0;i<v.length;i++) {
// Date Object from cell in B2:B in milliseconds
var vDate = new Date(v[i]).getTime();
// exit for loop when first date less than one month is found
if (today - vDate <= oneMonth) {
break;
}
}
Logger.log(i+1);
s.hideRows(2, i);
}
You have a syntax error on your for loop as well as the if statements. There should be {} the code to be worked on when in these portions. Then there is an error in your logic. The month of October in row 2 is greater than the current month, February. So you may want to first compare Years for the highest year and then compare months:
function hideRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Responses");
var v = s.getRange("B:B").getValues();
var today = new Date();
var m = today.getMonth();
var y = today.getYear();
for(var i=3;i<v.length;i++){
if(v[i][0] === "" || v[i][0].getYear() >= y){
if(v[i][0].getMonth() >= m) {
var stophere = 0;
break;
}
}
}
if(i>1) {
s.hideRows(2,i-1);
}
};
function onOpen(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Responses');
var today= new Date();
var today=today.setDate(today.getDate()-30); //minus 30 days
for ( var i = sheet.getLastRow(); i >= 2 ; i-- ) {
var filter = sheet.getRange(i, 2).getValue();//Evaluates Column B
if ( filter.valueOf() < today.valueOf()) {
sheet.hideRows(i); }
}
}
Sample Sheet- So, I am new to this part. Our work schedule is in by-weekly format, each two-week pay-period is on a separate sheet.
I need a script to cause it to open to the current date whenever a user accesses the sheet from their Google Drive.
Similar to this, but something isn't right:
function onOpen() {
var today = new Date();
var ss = SpreadsheetApp.getActive();
ss.setActiveSheet(ss.getSheets()[today.getMonth()]);
}
This script should bring you to the sheet with the current date..
function onOpen() {
var today = format(new Date());
var ss = SpreadsheetApp.getActive();
var sheets = ss.getSheets()
.forEach(function (s) {
var val = s.getRange("C2:P2")
.getValues()[0];
for (var i = 0, len = val.length; i < len; i++) {
if (format(val[i]) === today) {
ss.setActiveSheet(s)
break;
}
}
});
}
function format(date) {
return formattedDate = date.getMonth() + 1 + "/" + date.getDate()
}
See if this works ?