onOpen if column B is blank fill column A with todays date - google-apps-script

I have a spreadsheet where there is a value in column B and in column A is inserted a date, and i want to create a script that when the spreadsheet is open, inside the function onOpen (){}, checks if there is a cell in column B filled but left with column A (date) blank, then automatically inserts todays date, this needs to be done via app script, can anyone give some light?
Timesheet Example

If columnB and not Column A then insert Date into column A
function onOpen() {
ifBAndNotA();
}
function ifBAndNotA() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");//change sheet name as required
const sr = 2;//data startrow;
const vs = sh.getRange(sr, 1, sh.getLastRow() - sr + 1, 2).getValues();
vs.forEach((r, i) => {
if (!r[0] && r[1]) {
sh.getRange(i + sr, 1).setValue(new Date()).setNumberFormat("dd/MM/yyyy");
}
});
}

Related

How to get average of input category in google sheet

The thing is I want to find average of value from a column with a condition of category, so whenever I put a category value into the cell I should get average of that category in another cell
You could use a simple QUERY formula.
Average
function average() {
const ss = SpreadsheetApp.getActive()
const sh = ss.getSheetByName("Enter Sheet Name");
var avg = sh.getRange(2, 2, sh.getLastRow() - 1).getValues().flat().reduce((a,c) => { a.sum += c;++a.cnt;return a;},{sum:0,cnt:0,av:function(){return this.sum/this.cnt}}).av();
//Logger.log(avg);
return avg;
}

Google Apps Script - Adding/Subtracting Time - Hours/Minutes/Seconds to a particular column in googles sheet

I want to be able to add or subtract Time - Hour/Minutes/Seconds to a particular column with some conditions using google app scripts.
Example - The Image Below.
Column A is the Original Time.
If Column D2 is "Depart To" 30 minutes will be added to the original time (column A2) which will result to the time in Column C2
while If Column D4 is "Arrive from" 30 minutes will be subtracted from the original time (column D2) which will result to the time in Column C4.
which script can I use to achieve this?
Try this:
function myFunction() {
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getSheetByName("Sheet1");
var range = ss.getRange(2, 1, ss.getLastRow()-1, 4); //get A2:D4 range
var data = range.getDisplayValues(); //get values
data.forEach(row => { // loop each sub-array returned by getDisplayValues
var time = row[0].split(":"); //split the column a to get hour and minutes
var hour = time[0];
var minutes = time[1];
var fDate = new Date(row[1]) //create new Date object by using column b
fDate.setHours(hour) //set the hour of new Date Object
fDate.setMinutes(minutes) //set the minute of new Date Object
if(row[3].toLowerCase() == "depart to"){
fDate.setMinutes(fDate.getMinutes() + 30); // add 30 minutes to current date object
row[2] = Utilities.formatDate(fDate, Session.getScriptTimeZone(), "H:mm");
}else if(row[3].toLowerCase() == "arrive from"){
fDate.setMinutes(fDate.getMinutes() - 30); // minus 30 minutes to current date object
row[2] = Utilities.formatDate(fDate, Session.getScriptTimeZone(), "H:mm");
}
})
range.setValues(data) //write values to sheet
}
Test Data:
Output:
References:
Date Object
Spreadsheet Class
Range Class
Adding and subtracting dates
function addsubDates() {
const mA = [...Array.from(new Array(12).keys(), x => Utilities.formatDate(new Date(2021, x, 15), Session.getScriptTimeZone(), "MMM"))];//month array
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const vs = sh.getRange(2, 1, sh.getLastRow() - 1, 4).getDisplayValues();//get as string
let vo = vs.map((r, i) => {
let t = r[0].toString().split(':');
let d = r[1].toString().split('-');
let dt = new Date(parseInt(d[2]), mA.indexOf(d[1]), parseInt(d[0]), parseInt(t[0]), parseInt(t[1]));//base date
let a = 0;
if (r[3].toString().toLocaleLowerCase().includes('arrive')) { a = 30; }//adjustments
if (r[3].toString().toLocaleLowerCase().includes('depart')) { a = -30 }
return [Utilities.formatDate(new Date(dt.valueOf() + a * 60000), ss.getSpreadsheetTimeZone(), "HH:mm")];
})
sh.getRange(2, 3, vo.length, vo[0].length).setValues(vo);
}
Data:
21:46
17-Oct-2020
21:16
Depart To
21:47
17-Oct-2020
21:17
Depart To
21:48
17-Oct-2020
22:18
Arrive From
21:49
17-Oct-2020
22:19
Arrive From
21:50
17-Oct-2020
21:20
Depart To
21:51
17-Oct-2020
21:21
Depart To
21:52
17-Oct-2020
22:22
Arrive From
21:53
17-Oct-2020
22:23
Arrive From
Try this formula. Time is hours where 24 hours = 1 so 0.5/24 is a half hour.
=IF(D1="Depart To",A1+(0.5/24),A1-(0.5/24))

Is there a way to prevent spreadsheet from updating the date to today's date in formula?

I'm trying to print the date when I change the value on a cell (status column). But spreadsheets update the date to today's date. I wish it could save the date from when the status was changed.
The code to print the date:
function TIMESTAMP() {
var today = new Date();
var date = Utilities.formatDate(today, 'GMT-3', 'dd/MM/yyyy');
return date;
}
In the spreadsheet, the column D is where I set the status and columns H to J print the date from when the status was changed.
The code for column H is the following:
=ARRAYFORMULA(IF(ROW(H:H)=1;"LogĂ­stica";IF(ISBLANK(D:D);;IF((D:D>=3)*(D:D<6);TIMESTAMP();IF(D:D<1;"Aguardando Pagamento";IF(D:D=2;"Aguardando Etiqueta";IF(D:D=6;"Cancelado";"Aguardando Faturamento")))))))
The codes for columns I and J are similar to H. So, how to print the date from when the status in column D was changed and keep spreadsheet from updating to today's date?
Not sure but how about this:
function onEdit(e) {
const sh=e.range.getSheet();
if(sh.getName() == 'Sheet Name' && e.range.columnStart == 4 ){
let dt = Utilities.formatDate(new Date(), 'GMT-3', 'dd/MM/yyyy');
e.range.offset(0,4).setValue(dt)
}
}
You have to change the sheet name
Since you manually change the state on column D, you may use an onEdit(e) trigger to override the formula with the value that you want:
function onEdit(e) {
const { range } = e
const sheet = range.getSheet()
if(sheet.getName() === 'Set your sheet name here' && range.getColumn() <= 4 && range.getLastColumn() >= 4){
const firstRow = range.getRow()
const values = sheet
.getRange(range.getRow(), 4, range.getHeight(), 1)
.getValues()
.flat()
for (let i = 0; i < values.length; i++) {
const value = values[i]
if (!Number.isInteger(value) || value < 3 || value > 5) continue
const row = firstRow + i
const col = value - 3 + 8
const targetRange = sheet.getRange(row, col)
const todayStr = Utilities.formatDate(new Date(), 'GMT', 'dd/MM/yyyy')
targetRange.setValue(todayStr)
}
}
}
This code works even when setting multiple rows at the same time. Remember to set the name of your sheet and the timezone you are in.
References
Utilities.formatDate(date, timeZone, format) (Google Apps Script reference)
Class Range (Google Apps Script reference)

Google Sheets Add row based on cell number value

I'm trying to make a google sheet script that adds a row based on cell value, basically if I have in the Quantity (Column D) 7x laptops, I want the script to add 6 additional rows below if Column H is marked as "Yes" through data validation.
What I was able to find and to do is only duplicate that row but is without data validation and I would prefer to add the data validation and possible make each quantity split to 1 (instead of 7) after the duplication.
`function autoDup() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
var newData = [];
for(var n in data){
newData.push(data[n]);
if(!Number(data[n][3])){continue};// if column 3 is not a number then do nothing
for(var c=1 ; c < Number(data[n][3]) ; c++){ // start from 1 instead of 0 because we have already 1 copy
newData.push(data[n]);//store values
}
}
sheet.getRange(1,1,newData.length,newData[0].length).setValues(newData).sort({column: 1, ascending: false});// write new data to sheet, overwriting old data
}`
Hope someone is able to help me.
Thank you,
Column D contains a qty and goods description. If Column H = "Yes", you want to insert a number of rows below Col D equal to the qty minus one. If Column H <> "Yes, then take no action.
Sample data - Before
Sample data - After
function so5925663201() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetname = "59256632";
var sheet = ss.getSheetByName(sheetname);
var row = 7;
// get value of Column H
var colHValue = sheet.getRange(row,8).getValue();
if (colHValue === "Yes"){
//Logger.log("DEBUG: Col H = yes. do something")
// get value of Column D
var Value = sheet.getRange(row,4).getValue();
var searchterm = "x";
var indexOfFirst = Value.indexOf(searchterm);
//Logger.log("DEBUG: the first instance of 'x' is "+indexOfFirst);
// get the quantity and convert from a string to a number
var qty = Value.substring(0, indexOfFirst);
var qtynum = +qty;
// var newtype = typeof qtynum; // DEBUG
//Logger.log("DEBUG: the quantity is "+qtynum+", new type = "+newtype)
// This inserts rows after
sheet.insertRowsAfter(row, qtynum-1);
}
else{
//Logger.log("DEBUG: col H <> Yes. do nothing");
}
}

insert formula in newly created rows

Hi everyone was wondering how do i insert a formula into the newly created row
this script inserts 10 new row and i would like to instert a formula in the 10 new created row in the column E
var ss = SpreadsheetApp.getActive();
var target = ss.getSheetByName('Data Entry');
target.insertRowsAfter(target.getMaxRows(), 10)
what would i need to insert this formula in those newly created rows
=If(len(D3:D),vlookup(D3:D,'Configuration List'!A2:B,2,0),"")
You want to add rows to the last row, and put the formulas to column E in the created rows. You want to modify "D3:D" of the formulas. If my understanding is correct, how about these 2 solutions? I think that there are several solutions for your situation. So please think of this as two of them.
Pattern 1 :
In this script, it creates 2 dimensional array including the formulas. And put them to column E of the created rows using setFormulas().
var ss = SpreadsheetApp.getActive();
var target = ss.getSheetByName('Data Entry');
var maxRow = target.getMaxRows();
var r = target.insertRowsAfter(maxRow, 10);
var formulas = [];
for (var i = 1; i < maxRow; i++) {
formulas.push(["=If(len(D" + (maxRow + i) + ":D),vlookup(D" + (maxRow + i) + ":D,'Configuration List'!A2:B,2,0),\"\")"]);
}
target.getRange(maxRow + 1, 5, 10, 1).setFormulas(formulas);
Pattern 2 :
In this script, it creates a formula. And put it to column E of the created rows using setFormula().
var ss = SpreadsheetApp.getActive();
var target = ss.getSheetByName('Data Entry');
var maxRow = target.getMaxRows();
var r = target.insertRowsAfter(maxRow, 10);
var formula = "=If(len(D" + (maxRow + 1) + ":D),vlookup(D" + (maxRow + 1) + ":D,'Configuration List'!$A$2:B,2,0),\"\")";
target.getRange(maxRow + 1, 5, 10, 1).setFormula(formula);
Note :
Please select one of them for your situation.
References :
setFormula(formula)
setFormulas(formulas)
If I misunderstand your question, please tell me. I would like to modify it.