Auto select an option from a dropdown after a certain date - date

I'm creating a lost&found log for work, I have a dropdown list with options like "Collected", "Sent to guest", "Donated" etc.
I'd like to have the sheet automatically select 'Donated' after a certain date (maybe after 1 month) IF an option hasn't already been selected.
E.G. If somebody inputs a found pair of gloves on Nov 2nd, The empty dropdown will automatically change to 'Donated' on Dec 2nd unless somebody already selected another option (E.G. 'Collected').

You can accomplish this by either making use of Apps Script to check the conditions and make the corresponding changes or by directly implementing Sheets functions.
Sheets Functions
You can achieve the desired outcome by putting this formula on each status cell:
=IF(TODAY()-D4>30,"Donated","")
It will work as intended, the cell will not display anything until there are 30 days between the TODAY() date and the date provided in the D4 cell. If there are, the cell will display Donated. If another option from the drop-down is selected, that will erase the formula and only the new value will be displayed.
However, this method is more of a quick hack than an actual robust solution, as several things can go wrong. For instance, if an option from the drop-down is chosen by accident and then it is left blank again, the method will not work anymore for that line as the formula will have been permanently erased.
You can read about how TODAY() works here.
Apps Script (recommended)
The following script will check that, for every row in the sheet, both the status cell is blank and that subtracting the DATE FOUND is more than 30 days (unfortunately that has to be done in milliseconds).
function myFunction() {
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadSheet.getSheetByName("Sheet1");
sheet.getLastRow()
var range = sheet.getRange(4,1,sheet.getLastRow(), 7);
//SELECT A RANGE WITH THE 7TH FIRST COLUMNS AND AS MANY ROWS AS NECESSARY
//(WE ARE INTERESTED IN DATA STARTING FROM ROW 4TH)
var values = range.getValues();
var millisecondsIn30Days = 30 * 24 * 60 * 60 * 1000;
for(var row = 0; row<values.length; row++){
var status = values[row][6]; //STATUS IS THE 6TH ELEMENT IN THE ROW ARRAY (COLUMN G)
if(status == "" && (new Date() - values[row][3]) > millisecondsIn30Days){
//MORE THAN 30 DAYS AFTER FOUND
sheet.getRange(row+4,7).setValue("DONATED");
}
}
}
Of course, that script can be run manually or the job can be automated with an installable trigger that runs, for example, every month. You can read more about how to set up such triggers here.

Related

Google Sheets: Show values on a tab depending on date

We have a restaurant and want to show the Menu on a screen with google sheets.
I am using 2 tabs in Google sheets, The main (number 1) with the menu showing to the visitors, the second tab (number 2) has all the dates from today until coming 6 weeks like:
Column A
Column B
Column C
Column D
21 June
Appetizer this day
Main dish this day
Desert today
22 June
Appetizer this day
Main dish this day
Desert today
23 June
Appetizer this day
Main dish this day
Desert today
etc. etc.
Now what we want is that the 3 menu items are copied to the main tab on the day of today, so if it is 22 June, the corresponding appetizer, main dish and desert are copied to the main tab.
Is that possible?
This can be achieved with Google Apps Script. You can have a JavaScript code snippet that does this for you.
Open the required spreadsheet. Go to the Tools menu and click Script Editor. This will open up the script editor window with an empty function, code will have to be written inside this function, give it a name, I'm using updateFood():
function updateFood() {
// Fetch all the sheets/tabs of the current spreadhsheet
let sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
// Select the second sheet/tab using [1], first tab will be [0]
// Fetching the second sheet because that is where the data about the upcoming dates are present
let listSheet = sheets[1];
// Get all the data in the sheet
let data = listSheet.getDataRange().getValues();
// Iterate over all data in the sheet
for(i = 0; i < data.length; i++) {
// Get the date of the current row and create a date object
rowDate = new Date(data[i][0]);
// Get today's date
today = new Date();
// Check if the row date is equal to today's date
if(rowDate.setHours(0,0,0,0) == today.setHours(0,0,0,0)) {
// If the code reaches here, this row has the date same as today
// Get the first tab/sheet and then I'm selecting the cells A1, B1 and C1
// Modify the range as per which cells you want the dish names to be in
let range = sheets[0].getRange("A1:C1");
// Set the values of the selected three cells as the value of the second, third and fourth column in the current row of the 2nd tab which are Appetizer, Main dish and Dessert for that date respectively
range.setValues([[data[i][1], data[i][2], data[i][3]]])
}
}
}
And that's all the code you need! Save it and then you can try clicking on run code and then checking the first tab to see the values updated. However, when you click run for the first time, Google will ask you to grant permissions to the script to access your sheet. Click Review Permissions and then click on your account. Then click Advanced and then click:
.
But you will have to run this code every day. This can be achieved using a time-driven trigger.
In the same script editor window, look at the triggers button on the left:
Click on the + Add Trigger on the bottom right of the screen.
And select the values as follows (change the time as required):
That's all you need. Make sure that in the second tab, create dates in the date column with the Excel DATE(YEAR, MONTH, DAY) function rather than manually typing in the dates.

LibreOffice BASIC function - Copy if over a value to a new sheet

I'm trying to create a simple function on a LibreOffice Calc sheet.
I have a table of information where cells A1:K2 has headings (the cells in Row 2 are merged)
all the information runs from A3:K176
The sheet has various functions running on it already, all I need is one more function.
At first I wanted it to automate when i open, but then i thought running the BASIC macro off of a button might be better, so i can edit and then just hit the button once I'm done.
I have the button linked up to run the macro already, but now im stuck... I have tried many ways of writing the code, but it seems that i am just too green to figure it out.
the last time i ran Excel advanced functions i was in high school.
ok, enough talking...
All I need the macro to do is once I hit the button, I need it to check column K and any value > 1 it needs to take that whole row and copy it then go to a target sheet, clear any data on the target sheet. then copy that set of rows to the next open row in the target sheet. possibly even exporting the result to a .txt file as a bonus.
this is a start...
in future I would like to add another button that will do the same function to a array lower down and put that into a different sheet.
Option Compatible
Sub SWD_AwakeningsTrade
Dim i, LastRow
LastRow = Sheets("Card_List").Range("A" & Rows.Count).End(xlUp).Row
Sheets("Awakenings For trade").range("A2:I500").clearContents
For i=2 to LastRow
If Sheets("Card_List").Cells(i,"K").Value = "(>1)" Then
Sheets("Card_List").Cells(i, "K").EntireRow.Copy
Destination:=Sheets("Awakenings For trade").Range("A" & Rows.Count.end(xlUp)
End if
next i
End Sub

Excel stops working when adding new row to the Table

I don't know why but when I try to do this Excel Quits without saving anything:
On Sheet1 I have 11 Rows x 6 cols formatted as Table. With 1st row as Table Header.
I assign col A as a STU_ID Named Range using Name Manager.
I have only a listbox on the Userform. And I give RowSource property as =STU_ID . I get the col A data on the list box.
Now when I go to Sheet1 and try to add more data on next row of the table. Excel quits saying it has stopped working. Windows is checking for error and it restarts on a blank Workbook.
Shouldn't Listbox be dynamic and get data from Name Manager as I add them on the sheet ?
I am using MS Excel Pro 13 on Win 10 64 bit.
This is a bug in Excel. As a workaround, use the .List property instead of the .RowSource.
Try something like this in the UserForm's code:
Private Sub UserForm_Initialize()
ListBox1.List = Range("table1[abc]").Value
End Sub
This way it will be dynamic, and it will work.
If you need it to change while the userform is displayed, put a small code to the Sheet change event, that updates the list every time the sheet changes. (This is only necessary if your form is modal, and you want it to reflect the changes made in real-time.)

Excel Form VBA Combobox reset

This should be easy but I can't seem to find anything to solve. I have a Form in Excel using VBA. The Excel sheet has four columns populated with data and the Form displays those fields.
The user then selects a value in a combobox, uses a command button to submit the responses and the values from the combobox are written to the Excel sheet.
The user then uses a command button to advance one row down in the spreadsheet and load the four values from a new row. This all works great.
The issue I am trying to solve is that the combobox remains selected to the value in the prior selection. I'd like to reset the combobox so nothing is selected and the user has to make a selection again for the next row.
Below is the code I am using to load the combobox and to set a variable for what the user selected. Can't seem to get the combobox back to it's default state after the user has submitted the form.
Private Sub cbDesAccWanted_Change()
Select Case cbDesAccWanted.Text
Case "Yes"
desacc = "Yes"
Case "No"
desacc = "No"
End Select
cbDesAccWanted.Text = desacc
End Sub
Private Sub cbDesAccWanted_DropButtonClick()
cbDesAccWanted.List = Array("Yes", "No")
End Sub
There are two ways to reset the combobox. Take your pick:
1
cbDesAccWanted.Value = Null
2
cbDesAccWanted.ListIndex = -1
the line
cbDesAccWanted.Text = desacc
is totally unnecessary.
Using cbDesAccWanted_DropButtonClick is not the right place to populate the list of values. This list should be set up when the form is first shown to the user.
(unelss the values it shows chnages in which case change it when the row changes or something, not when the user clicks on it)
So when theuser clicks the down arrow to move to thenext record include the following line
Me.cbDesAccWanted.text = Me.cbDesAccWanted.List(1)
Note (1) access teh 2nd item in the list which is No.
So this reset it to the default value of No.
Ok.

Programmatically repeat "Detail" section in Active Reports

I need to repeat a "detail" section, simply repeating the data found in XML, based on the value of one of the XML elements.
Example:
I have a shipped quantity on a line item of 18. There is only one set of data for this in the XML, it is not repeated 18 times. I would like it to display this data 18 times.
Is there a way to programmatically repeat a section? I'm a total novice and i figured for once I'd ask here instead of going to the software vendor, in which case i learn nothing! I tried pouring over the 800+ page manual and couldn't find an answer.
Any solution where I'm not just repeating the detail section is of course welcome!
The report is coded in VB.net, my dataset is XML.
Thanks in advance!
Shawn
I understand your requirement and as per my understanding you wish to repeat the data in the detail section depending on the value of the 'Shipped Quanity'.
If the value is 18, the details section should be repeated 18 times and if ofr the next record the value if 5, the entry for this record should be dispalyed in the report for 5 times.
A cleaner to implement this without repeating the Details Section of the report would be to make use of a subreport.
The flow of the implementation would like the following :
Add a subreport in the Detail section of Report1 (Main Report)
Set it's datasource and add the fields you wish to display
You may remove the ReportHeader/ReportFooter of the subreport and set the height of the PageHeader/Footer to zero
In the Format event of the Detail section fetch and save the value of the 'Shipped Quanity' in some variable (say count).
On the basis of this value,
a. either repeat the Detail Section (number of times=value of count) of the Subreport
b. or render the Subreport multiple times (number equivalent to the value of count)
Regards,
Mohita
I ended up using a counter system and LayoutAction (which i didn't know existed before making this question)
The code ends up looking like this:
int counter = 1;
int skip = 1;
public void Detail_Format() {
if (skip == 1)
{
string convert =((TextBox)rpt.Sections["Detail"].Controls["txtShipQuantity"]).Text.ToString();
counter = int.Parse(convert);
}
if (counter > 1)
{
rpt.LayoutAction = LayoutAction.PrintSection|LayoutAction.MoveLayout;
counter--;
skip = 0;
}
else
{
rpt.LayoutAction = LayoutAction.PrintSection|LayoutAction.MoveLayout|LayoutAction.NextRecord;
skip = 1;
}
}
Thanks!
Shawn