Default value in data validation dropdown - google-sheets

I have a table that changes dynamically based on the week we're on by using
=WEEKNUM(TODAY())
but I want to create a dropdown menu with all the week numbers, so a user can select any week and check the data related to that weeknum. However, I'd like that everytime the sheet opens, it shows as a default, the current weeknum.

You might be able to use a non-script approach if you can adapt the technique outlined in detail at https://www.benlcollins.com/spreadsheets/default-values/. You will need to be able to add a column to the immediate left of the 'Week' column, and probably also to hide the column afterwards for neatness.
For instance, if the example table above was in columns B&C, add the following formula to A2, copy down the column as far as needed then hide column A:
={"",weeknum(today())}
You can then set up the data validation dropdown in the week column, and anything you select in those cells will overwrite the default value. This generates #REF! errors in column A because you are preventing a literal array expanding, but you can't see the error because it's hidden, and you don't care about it anyway. If you delete the value in any cell in the Week column, the array in the corresponding cell in column A will be able to expand again and show the default value once more.

Suggestion
As what #player0 have mentioned, this is possible using a script. You may use this quick sample script below as reference on how to create a drop-down, set it with week numbers from the current week down to the first week of year, and set it up to show the default current week number.
Sample Script:
function test() {
var currentDate = new Date();
var startDate = new Date(currentDate.getFullYear(), 0, 1);
var days = Math.floor((currentDate - startDate) / (24 * 60 * 60 * 1000));
var weekNumber = Math.ceil((currentDate.getDay() + 1 + days) / 7);
var weeks = [];
while (weekNumber != 0) { //Get the week numbers from today to the first week of the year
weeks.push(weekNumber)
weekNumber--;
}
var cell = SpreadsheetApp.getActive().getRange('A1');
var rule = SpreadsheetApp.newDataValidation().requireValueInList(weeks, true).build();
cell.setDataValidation(rule).setValue(weeks[0]); //Sets the default value to the current week number
}
Test
Reference
https://developers.google.com/apps-script/reference/spreadsheet/range#setvaluevalue
https://developers.google.com/apps-script/reference/spreadsheet/data-validation-builder#requirevalueinlistvalues

Related

How to keep lock a cell value even if the condition changed?

please refer to the images below
Sheet1
sheet2
I have 2 sheets: sheet1 and sheet2, here's what I want to do: if sheet2!B37 = sheet1!B1, take the value of sheet1!B2, if not stay blank.
This part is easy, but what I want is that if I change the date in sheet1!B1 to 16 Mar 2021 and sheet1!B2 to 90, I want sheet2!C37 to stay 100 and sheet2!C38 returns 90.
One way is to copy the content of sheet2!C37 and paste it as value.
Reference: Convert formulas to values in Google Sheets
But I doubt that you would want to convert the formula into a value every time you need to change the condition. Hence, you might want to consider using Google Apps Script and run it using a button.
Sample Code:
function updatePrice() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
//Get Sheet1 object
var sheet1 = ss.getSheetByName("Sheet1");
//Get Sheet1 object
var sheet2 = ss.getSheetByName("Sheet2");
//Get Sheet1!B1 string value
var targetDate = sheet1.getRange("B1").getDisplayValue();
//Get Sheet1!B2 string value
var targetPrice = sheet1.getRange("B2").getDisplayValue();
//Get Sheet2 column B range
var dates = sheet2.getRange("B1:B");
//Create a textfinder and look for the target date (Sheet1!B1 value)
var textFinder = dates.createTextFinder(targetDate);
var firstOccurrence = textFinder.findNext();
if(firstOccurrence!=null){
//Date found
//Update price in column C
firstOccurrence.offset(0,1).setValue(targetPrice);
}
}
What it does?
Get the active spreadsheet using SpreadsheetApp.getActiveSpreadsheet()
Get the sheet object for Sheet1 and Sheet2 using Spreadsheet.getSheetByName(name)
Select the range for Sheet1!B1 and Sheet1!B2 using Sheet.getRange(a1Notation). Get the string value using Range.getDisplayValue()
Select the range for Sheet2!B1:B using [Sheet.getRange(a1Notation)]
Create a textFinder using Range.createTextFinder(findText)
Get the first occurrence of the date string that was being searched using TextFinder.findNext(). If date string has no match, return will be null. If date string has match it will return a Range of the matching cell
Matching cell will give you a range in column B, to set the price value move the range 1 column to the right by adding 1 column offset using Range.offset(rowOffset, columnOffset) and set the range value using Range.setValue(value)
Add A Google Sheets Button To Run Scripts
Add a Google Sheets button. You add a button via the Insert > Drawing menu.
Click Save and Close, this drawing gets added to your Google Sheet. You can right click on it to resize it or drag it around to reposition it.
To assign a script, Right Click the drawing and click the three little dots in the top right of the drawing and select Assign Script. Then type in the name of the function you want to run from your Apps Script code.
Output:
Note:
Please don't forget to click enter when editing your Sheet1 values before clicking the button. Apps Script cannot update Sheet2 when the cell to be read is still in edit.

How to generate random data of birth dates using google spreadsheets for a specific years?

I want a formula to generate random data of birth dates for a specific years (Example: 1995 to 2002) and make it Array like this:
Sheet URL: https://docs.google.com/spreadsheets/d/1XHoxD-hNmpUOMVm_u-cz-4ESrabodsrS0fIfaN-n4js/edit
That might not be the best approach but it will get you closer to what you want:
=DATE(RANDBETWEEN(1995,2002),RANDBETWEEN(1,12),RANDBETWEEN(1,31))
There are two issues with this approach:
you might get a day that does not exist for the particular month. For example, 2/28/2021 exists, but 2/29/2021 does not exist.
I wasn't able to generate an array but only drag down formulas. When I generate an array, the same random numbers are used and as a result the dates are the same.
For the first issue, you can use isdate to check if the random date returned is correct. For example, 2/29/2021 is a wrong date (I hardcopied that date).
but I guess you can filter out the FALSE cases.
I really hope other people can come up with a better approach.
You could try (as I demonstrated in your sheet):
=ARRAY_CONSTRAIN(SORT(SEQUENCE(DATE(1992,12,31)-DATE(1900,1,1),1,DATE(1900,1,1)),RANDARRAY(DATE(1992,12,31)-DATE(1900,1,1)),1),COUNTA(A2:A),1)
SEQUENCE(DATE(1992,12,31)-DATE(1900,1,1),1,DATE(1900,1,1)) - Is used to create an array of valid numeric representations of true dates between 1-1-1900 and 31-12-1992.
SORT(<TheAbove>,RANDARRAY(DATE(1992,12,31)-DATE(1900,1,1)),1) - Is used to sort the array we just created randomly.
ARRAY_CONSTRAIN(<TheAbove>, COUNTA(A2:A),1) - Is used to only return as many random birth-dates we need according to other data.
Note that this is volatile and will recalculate upon sheet-changes and such. Also note that this is just "slicing" a given array and may fall short when you try to use it on a dataset larger than the given array.
As Google Sheets can deal with dates as integers (~ number of days since 1900), choosing a random date between two dates can be a single call to RANDBETWEEN (with the output formatted as Date).
With your initial date written in B1 and your end date in B2, the formula is simply:
=RANDBETWEEN($B$1,$B$2)
You can paste this formula in as many cells as you want, to generate N different random dates.
Of course, as other answers involving random generators in your sheet, the formula will be recomputed at each change. My suggestion to overcome this would simply be to copy/paste the output, using the "Paste special > Values only" option (right click or "Edit" menu).
Script Solution
Just for sake of completeness, here is a solution using a script
Initial Considerations
This cannot function like a in sheet function/formula.
https://developers.google.com/apps-script/guides/sheets/functions
Custom function arguments must be deterministic. That is, built-in spreadsheet functions that return a different result each time they calculate — such as NOW() or RAND() — are not allowed as arguments to a custom function. If a custom function tries to return a value based on one of these volatile built-in functions, it will display Loading... indefinitely.
A custom function cannot affect cells other than those it returns a value to. In other words, a custom function cannot edit arbitrary cells, only the cells it is called from and their adjacent cells. To edit arbitrary cells, use a custom menu to run a function instead.
So a normal script is needed.
The Script
/**
* Sets the values of a range to random dates.
*/
function generateRandomBdays(range, start, end) {
let height = range.getHeight();
let width = range.getWidth();
let output = [];
for (let i = 0; i != height; i++) {
let row = [];
for (let j = 0; j != width; j++) {
row.push(randomBday(start, end));
}
output.push(row)
}
range.setValues(output);
}
/**
* Generates a random date beween start and end
*/
function randomBday(start, end) {
if (start < 2000) start = start - 1900
start = new Date(`${start}`);
if (end < 2000) end = end - 1900
end = new Date(`${end}`);
let bday = new Date(
start.getTime() + (Math.random() * (end.getTime() - start.getTime()))
);
return bday;
}
/**
* Gets active selection and fills with random dates
*/
function main(){
let file = SpreadsheetApp.getActive();
let sheet = file.getActiveSheet()
let range = sheet.getActiveRange();
// ============
generateRandomBdays(range, 1995, 2002); // Change these years to your liking
// ============
}
/**
* Creates menu when sheet is opened.
*/
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Generate Birthdays')
.addItem('Generate!', 'main')
.addToUi();
}
Which works like this:
Installation
You will have to copy it into your script editor and then run one of the functions to authorize the script with the permissions it needs. Then next time you open the sheet you should have the menu available.
Alternatively you can delete the onOpen function and just use it from the script editor.
Within the main function, customize the range of years you need.
References
Apps Script
Overview of Spreadsheet Service in Apps Script

I want to auto populate a cell with date when adjacent cell is populated or changed in Google Sheets

I'm specifically working with Google sheets app on either my tablet or cellphone (though I can access an actual computer and update it through that as well, I mainly work within the apps) and I need to be able to auto-populate the cell in column C with the current date whenever there is data entered or changed. I'm reading all the other answered questions and they're based on excel and I'm not sure it applies to Google Sheets. I'm not very familiar with code or formulas so if you can give me the exact code I need to use and tell me where out needs to be entered I can follow those instructions but just giving me a bunch of code jargon well only serve to confuse me now.
Here's what I'm working on. I have a sheet where all data in Column A is the name of a person, column B is their current weight, and column C is the date they entered their current weight whether it be a new entry or changing an existing entry. I hope this helps.
make a copy of this sheet: https://docs.google.com/spreadsheets/d/
what you are asking is done by a script which runs whenever you enter something in column B
go to Tools
select Script editor
copy paste this script:
function onEdit(event) {
var sheet = event.source.getActiveSheet();
// note: actRng = the cell being updated
var actRng = event.source.getActiveRange();
var index = actRng.getRowIndex();
var cindex = actRng.getColumnIndex();
if (cindex == 2) { // 1 == Column A, 2 == Column B, 3 == Column C, etc.
var dateCol = sheet.getLastColumn();
var lastCell = sheet.getRange(index,dateCol);
var date = Utilities.formatDate(new Date(), "EST", "MMM-dd-yyyy");
lastCell.setValue("'" + date);
}
}
save the project under some name
return to your sheet (you can close script window/tab)

How to record the date on column B every day, in a new line

I use a daily (01:00 am) script to record my daily portfolio value, calculated in sheet A, to a new sheet.
Every day the script runs, opens a new line and records the value in column A, but I have to add the date manually on column B.
The document looks like that:
A-----------B
$1000-----1.1.2019
$1004-----1.2.2019
... ------....
$1006-----1.5.2019
I couldn't find a way to automatize column B date recording. What should I add to my code?
function copy() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getRange ("calc!U12");
var data = source.getValues();
var ts = ss.getSheetByName("record");
ts.getRange(ts.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
This can be solved without using script. In cell B1 put your starting date. In all of the other cells in B, drag down this formula:
=IF(COUNTBLANK(A2)=0,B1+1)
This checks to see if the cell to the left (in A) has a value, and if it does, it will add one to the previous date. The first date will still have to put in by hand. You may want to make column B formatted so that the numbers appear as dates.

Cleaner formula for subtracting a set amount from a column of values each calendar day in google sheets?

Formula: In cell A1 I manually type the date that I'm adding a new value, in cell B1 I have the Today() formula, and finally in cell C1 I have the formula =YourStartingValue - (5*(B1-A1)).
Result: The end result is that the value I input into cell C1 gets 5 subtracted from it each new calendar day. I then repeat this step in a new row for each new value that I add.
My question: is there a formula I can use so that I don't have to add the stuff in A1 and B1 each time? It'd save time and make things cleaner. Thanks!
In order to have 5 subtracted from every value in some column every day, I would use a script such as this one:
function subtractDaily() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var range = sheet.getRange('C:C');
var values = range.getValues();
range.setValues(values.map(function(row) {
return [row[0] == parseFloat(row[0]) ? row[0] - 5 : row[0]];
}));
}
Change the sheet name and column as needed, and set it to run daily using "Resources > Current project's triggers" dialog of the script editor.
The script checks that the cells contain numbers and does not attempt to subtract 5 from text or blank cells.

Resources