How to Hide Array of Columns Based on Column Value(Todays Date) - google-apps-script

I'd like to achieve the following:
Hide Columns starting from Column C up to the column that matches today's date(11/16/2022)
Script should stop hiding columns if it reaches Column Z
Apply this to 3 different sheets with same cell ranges (Sheet1, Sheet2, and Sheet3)
I want to achieve this using Google Apps Script
Appreciate your help in advance.

In your situation, how about the following sample script?
Sample script:
function myFunction() {
const sheetNames = ["Sheet1", "Sheet2",,,]; // Please set your sheet names.
sheetNames.forEach(sheetName => {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
sheet.showColumns(3, sheet.getMaxColumns() - 2);
const today = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "M/d"); // or "MM/d" or "MM/dd"
const num = sheet.getRange(3, 3, 1, sheet.getLastColumn()).getDisplayValues()[0].findIndex(e => e == today);
if (num > 0) {
sheet.hideColumns(3, num);
}
});
}
When this script is run, from your showing sample image, the cells "C3:3" are searched by the date like M/d. When today's date is found, the columns until today are hidden.
Note:
This sample script is from your showing sample Spreadsheet. So, when you change the structure of the Spreadsheet, this script might not be able to be used. Please be careful about this.
References:
forEach()
hideColumns(columnIndex, numColumns)

Related

Moving one row to bottom of a sheet after date has passed

I am looking for a macro that can help move a row of a sheet to the bottom of it once it passes a certain date. Basically this will be used for a meeting tracker and I'm trying to find a way to automatically move meetings to a "Completed" section once the date (located on Column F) passes.
I've created macros before to move things between sheets, but I'm unfamiliar with how to move things on the same sheet. Would anyone be able to help?
Here's the sheet: https://docs.google.com/spreadsheets/d/1EPueop9bdky_J8VgpFdSUzzsMRieRUreeCRIy18ScTY/edit#gid=0
I would like to move rows based on the date in Column F. Once it passes I would like it to move to the "Completed" section of the sheet. This is an active spreadsheet so the row "Completed" it's on could change as meetings are being added.
function moveActiveRowToBottom() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
const r = sh.getActiveRange().getRow();
const vs = sh.getRange(r,1,1,sh.getLastColumn()).getValues();
sh.getRange(sh.getLastRow() + 1, 1, vs.length, vs[0].length).setValues(vs);
sh.deleteRow(r);
}
I believe your goal is as follows.
You want to check the date of column "F" of the sheet. When the date of column "F" is smaller than today, you want to move the row to the last row.
You want to achieve this in the same sheet in a Google Spreadsheet. And, the sheet has a row of "Completed" in column "A", you want to check the date of the above rows of the "Completed" row.
In this case, how about the following sample script?
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet, and save the script. When you use this script, please run the function of myFunction().
function myFunction() {
const sheet = SpreadsheetApp.getActiveSheet(); // or const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet 1");
const row = sheet.getRange("A4:A" + sheet.getLastRow()).createTextFinder("Completed").findNext().getRow();
const now = new Date().getTime();
const moves = sheet.getRange("F4:F" + (row - 1)).getValues().reduce((ar, [f], i) => {
if (f && f.getTime() < now) {
const r = i + 4;
ar.push(sheet.getRange(`A${r}:F${r}`));
}
return ar;
}, []).reverse();
const len = moves.length;
if (len == 0) return;
const lastRow = sheet.getLastRow();
moves.forEach((r, i) => sheet.moveRows(r, lastRow - i + len - 1));
}
When this script is run, the column "F" of the rows from 4 to the "Completed" row is checked. And, when there are moving rows, the rows are moved to the last row of the sheet.
Note:
This sample script was tested using your provided Spreadsheet. When you change the Spreadsheet and/or your actual Spreadsheet is different from your provided Spreadsheet, this script might not be able to be used. Please be careful about this.
When I saw your sample Spreadsheet, it seems that the sheet name is Sheet 1. If you want to use the sheet using the sheet name, please be careful about this.
References:
reduce()
forEach()
moveRows(rowSpec, destinationIndex)

Automatically populate cell in Google Sheets when another cell in same row is manually filled

In Google Sheets, I want to create a macro that will automatically populate a column in each row when another column in that row is manually filled. The autofilled cell will use a formula that takes a chunk of the information (date) that's been entered manually and use a formula to concatenate it with a random number in order to create a unique ID. After inserting and executing the formula, the macro needs to copy and then paste "values only" the result of that formula. The point is to automatically create a stable ID in response to a triggering event (entry of date in row).
In pseudocode, here's the process I'd like the macro to execute:
when (date in yyyy-mm-dd format entered into A[i]) {
fill B[i] with =CONCATENATE(SUBSTITUTE(LEFT(A[i], 7), "-", ""),RANDBETWEEN(0,1000000000));
copy B[i];
PASTE_VALUES B[i] in B[i];
}
Apologies if I've overlooked a previous answer that solves this problem. I'm not new to coding, but I am new to coding in Google Sheets and am not sure what terms or phrases to use to describe what I'm after.
I believe your goal is as follows.
For example, when a value with the format of yyyy-mm-dd is put to the cell "A1", you want to put the formula of =CONCATENATE(SUBSTITUTE(LEFT(A1, 7), "-", ""),RANDBETWEEN(0,1000000000)) to the cell "B1".
You want to fix the value of the formula as the value.
You want to achieve this using OnEdit trigger.
Added: You want to put the value to the column "B", when the column "B" is empty.
In this case, how about the following sample script?
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet, and save the script. And, please set the sheet name you want to use. When you use this script, please put the value with the format of yyyy-mm-dd to the column "A", by this, the script is run.
function onEdit(e) {
const sheetName = "Sheet1"; // Please set the sheet name.
const range = e.range;
const sheet = range.getSheet();
const [a, b] = range.offset(0, 0, 1, 2).getDisplayValues()[0];
if (sheet.getSheetName() != sheetName || range.columnStart != 1 || !/\d{4}-\d{2}-\d{2}/.test(a) || b) return;
const dstRange = range.offset(0, 1);
dstRange.setFormula(`=CONCATENATE(SUBSTITUTE(LEFT(${range.getA1Notation()}, 7), "-", ""),RANDBETWEEN(0,1000000000))`);
SpreadsheetApp.flush();
dstRange.copyTo(dstRange, { contentsOnly: true });
}
Reference:
Simple Triggers
This is the script I came up with:
/** #OnlyCurrentDoc */
function onEdit(e) { //Runs every time the sheet is edited
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1'); //Change this to whatever your sheet is named
var inputCol = sheet.getRange('A1'); //Change this to whatever column the date is going to be entered
//This is the range that will be checked. Slightly redundant, but makes it easier to reuse this script without needing to retype every variable
var myRange = inputCol;
//Get the row & column indexes of the active cell
var row = e.range.getRow();
var col = e.range.getColumn();
//Check that your edited cell is within the correct column
if (col == myRange.getColumn()) { //This runs only if a value is entered into the column defined in 'inputCol'
if(sheet.getRange(e.range.getA1Notation()).getValue() == '') {return}; //If the edited cell is empty (ie the date is deleted, nothing happens)
if(row == 1) {return} //If the header is changed, nothing happens
let codeCell = sheet.getRange('B'+row); //Change to the column that will store the generated code value
codeCell.setValue('=CONCATENATE(SUBSTITUTE(LEFT(A'+row+', 7), "-", ""),RANDBETWEEN(0,1000000000))');
let hardValue = codeCell.getValue(); //Gets the value from the formula you just entered
codeCell.setValue(hardValue); //Replaces the formula with just the resulting value
};
}
Comments are included to explain everything that is happening. Linked below is the spreadsheet I used to test this. It is set to allow editing, so feel free to use it to test the script yourself.
https://docs.google.com/spreadsheets/d/1UONgRPBEbxn8CQeiRSPS4eFKHjh4ae8hXGYn6ImHxeI/edit?usp=sharing
Hope this helps!

Copy & Delete Function on Sheets w/ Apps Script

After someone submits a Google Form response, their responses go to the DropRequests sheet (although the form is not currently linked for reasons).
What we want to do is after someone submits their form, and their responses go to the DropRequests sheet, that if the value in column C matches that of column F in the StudentMatches sheet, it is moved to the OldMatches sheet. We have started on the code below but it does not yet work. Any ideas on how to make this functional and fix the issue with the range in the last line?
function moveMatch(){
var oldmatches = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("OldMatches");
var droprequest = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DropRequests");
var currentmatches = SpreadsheetApp.openById('1dd9UhD2LpshCFVYizpf3OwI1XzPrq3AfqhMAO1iJ6Ns')
value1 = currentmatches.getRange("F:F").getDisplayValues();
value2 = droprequest.getRange("C:C").getDisplayValues();
for(var i in value1)
if(value2[0,i]=value1){
currentmatches.getDataRange.getRow(0,i).moveTo(oldmatches.getLastRow())
}
}
Thank you again.
I believe your goal is as follows.
There are 3 sheets DropRequests, StudentMatches, OldMatches in your Spreadsheet.
You want to retrieve the values of column "C" from DropRequests sheet, and want to compare these values with the values of column "F" of StudentMatches sheets.
When the values are matched, you want to move the row from the StudentMatches sheet to the 1st empty row of OldMatches sheet.
When moveTo is used, the moved row becomes the empty row. In your goal, you want this situation.
In this case, how about the following sample script?
Sample script:
function moveMatch() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet1 = ss.getSheetByName("DropRequests");
var srcSheet2 = ss.getSheetByName("StudentMatches");
var dstSheet = ss.getSheetByName("OldMatches");
var srcValues1 = srcSheet1.getRange("C2:C" + srcSheet1.getLastRow()).getValues().map(([c]) => c);
var [,...srcValues2] = srcSheet2.getDataRange().getValues();
var values = srcValues2.flatMap((r, i) => srcValues1.includes(r[5]) ? i + 2 : []);
if (values.length == 0) return;
var lastCol = srcSheet2.getLastColumn();
var lastRow = dstSheet.getLastRow();
values.forEach((r, i) => srcSheet2.getRange(r, 1, 1, lastCol).moveTo(dstSheet.getRange(lastRow + 1 + i, 1)));
}
In this modification, the values are retrieved from the column "C" of "DropRequests" and "StudentMatches". And, the values of the column "C" of "DropRequests" are compared with the column "F" of "StudentMatches" sheet. When the values are matched, the row is moved from "StudentMatches" to "OldMatches".
Note:
First, please check the sheet names, again.
This sample script is for your question. So, when the Spreadsheet is changed, this script might not be able to be used. Please be careful this.
References:
forEach()
moveTo(target)

AutoFill Formula (running across spreadsheet) - Google Sheets / Apps Script

I would like to change my code below to autofill the formula across the page - not autofill down
you can see in the 2 images below I can add the formula to N527 but cannot autofill across the page with code - which is what i am looking for.
So images are before and after of what i am looking to accomplish
function LastColumn(){
var spreadsheet = SpreadsheetApp.getActive();
var LastColumn = spreadsheet.getLastColumn();
//spreadsheet.setActiveSheet(spreadsheet.getSheetByName('MASTER'), true);
spreadsheet.getRange('N527').activate();
spreadsheet.getCurrentCell().setFormula('=sum(N497*N498*N499)/100/250');
var destinationRange = spreadsheet.getActiveRange().offset(0, 0, LastColumn -526);
spreadsheet.getRange("N527:BK527").copyTo(destinationRange);
}
I couldnt get the attached code to work
I am trying to Autofill N527 across to AK527 - IF THE CELL ABOVE HAS DATA.
Thanks in Advance
I believe your goal as follows.
You want to put the formula of =sum(N497*N498*N499)/100/250 from the cell "N527" to the column direction.
In this case, when the row 526 of the same column has the value of carton, you want to put the formula.
You want to achieve this using Google Apps Script.
In this case, how about the following sample script?
Sample script:
function LastColumn() {
var sheetName = "Sheet1"; // Please set the sheet name.
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
var range = sheet.getRange('N526:526');
var ranges = range.getValues()[0].reduce((ar, r, i) => {
if (r.toLowerCase() == "carton") ar.push(range.offset(1, i, 1, 1).getA1Notation());
return ar;
}, []);
sheet.getRangeList(ranges).setFormulaR1C1('=sum(R[-30]C[0]*R[-29]C[0]*R[-28]C[0])/100/250'); // This formula is like `=sum(N497*N498*N499)/100/250`.
}
In this case, at first, the cells "N526:526" are checked whether the cell has the value of carton. And, when the cell has the value, the formula is put to the row 527.
I used RangeList for this.
References:
getRangeList(a1Notations)
setFormulaR1C1(formula) of Class RangeList
You need to copy the formula from cell already containing the formula to the range to which you want to expand it
This means that your destination range should be "O527:BK527".
Sample:
function autoFill(){
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('MASTER');
var firstCell = sheet.getRange('N527');
firstCell.setFormula('=sum(N497*N498*N499)/100/250');
var destinationRange = sheet.getRange("O527:BK527");
firstCell.copyTo(destinationRange);
}

Looking for better way to pass range for my function sumBlack()

I would love to be able use my script in Google sheet with just =sumBlack(C4:14)
currently my script ** see below ** works in Google sheet with =sumBlack(3,4,14)
3 for column, 4 and 14 are the row start and end
here's my code... pleased that it works though
it sums only cells that have the fontColor of black
function sumBlack(column, rowst, rowend) {
result = 0;
for(row = rowst;row <= rowend;row++){
var txtColor = SpreadsheetApp.getActive().getDataRange().getCell(row, column).getFontColor();
if(txtColor == "#000000"){
result = result + SpreadsheetApp.getActive().getDataRange().getCell(row, column).getValue();
}
}
return result;
}
I believe your goal as follows.
You want to sum the values of cells, when the font color is #000000 as hex.
You want to achieve this using the custom function.
Modification points:
In this case, in order to give the a1Notation to the custom function, how about using =sumBlack("C4:14") instead of =sumBlack(C4:14)? Because when =sumBlack(C4:14) is used, the values of cells "C4:14" is given as 2 dimensional array. By this, the range cannot be known.
In this modification, getFontColors() and getValues() are used instead of getFontColor()andgetValue(), respectively. By this, I think that the process cost will be able to be reduced.
When you can permit this suggestion, how about the following modified script?
Modified script:
When you use this script, please put =sumBlack("C4:14") to a cell. In this case, please don't forget to enclose the a1Notation with ".
function sumBlack(a1Notation) {
const range = SpreadsheetApp.getActiveSheet().getRange(a1Notation);
const fontColors = range.getFontColors();
const values = range.getValues();
const result = fontColors.reduce((n, r, i) => {
r.forEach((c, j) => {
if (c == "#000000") n += Number(values[i][j]);
});
return n;
}, 0);
return result;
}
If you want to give the sheet name like =sumBlack("Sheet1!C4:14"), please modify above script as follows.
From
const range = SpreadsheetApp.getActiveSheet().getRange(a1Notation);
To
const range = SpreadsheetApp.getActiveSpreadsheet().getRange(a1Notation);
In above modified script, when =sumBlack("C4:14") is put and the cell value of "C4:14" is changed, no recalculation occurs. If you want to recalculate for this situation, please add the following script. The following script is automatically run when the cells in the active sheet are edited, and the formula of =sumBlack() is recalculated.
function onEdit(e) {
const sheet = e.source.getActiveSheet();
sheet.createTextFinder("=sumBlack").matchFormulaText(true).replaceAllWith("###sumBlack");
sheet.createTextFinder("###sumBlack").matchFormulaText(true).replaceAllWith("=sumBlack");
}
References:
getFontColors()
getValues()
reduce()
Class TextFinder