Button to "Archive" rows based on variable - google-apps-script

I'm pretty new to Google Sheets and I'm looking for a method/function that will allow a button I create to archive all entries in the spreadsheet to another spreadsheet.
I currently have a column that calculates the current week of the year, and another manually entered column that is for the week of the year that the entry was input. This will eventually be calculated automatically on entry of a new row, but what I'm looking to do is pull all entries from weeks prior to the current week and place those rows into another spreadsheet I dictate.
I know this is possible in Excel, but I'm not the greatest with the programming in Google Sheets, so I'm looking for some advice/help.
EDIT:
Quickly I've discovered I'm either REALLY rusty or just not great at Java. I tried the following code:
function myArchive() {
var aYear = getYear()
var sourceSheet = SpreadsheetApp.getActive()
.getSheetByName('Payroll'),
destSheet = SpreadsheetApp.openById('PayrollArchive')
.getSheetByName(aYear),
sourceRanges = ['A:A', 'B:B', 'C:C'],
targetRanges = [7, 9, 12]
.map(function (r, i) {
var sr = sourceSheet.getRange(sourceRanges[i]),
val = sr.getValues();
destSheet.getRange(1, r, val.length, val[0].length)
.setValues(val);
sr.clear()
});
}
Retrieved from here: Is there an easy format to move columns of data by script?
However, I'm trying to do a little different.
I want to copy all entries where column 1 has the week # of the previous week or before. For example, it is currently the 21st week of the year. I want it to pull all entries in the spreadsheet where column 1 is 20 or previous. Not sure how to program the current week in Java.
I want to put ALL information from the rows pulled above into a sheet named the current year in the spreadsheet named PayrollArchive. So, all of the previous weeks' worth of rows would be put in the 2015 sheet in PayrollArchive spreadsheet. I think var aYear = getYear() is the proper coding to grab the current year but is it possible to grab the value of a particular cell in the sheet to get that? I already have the current week # and date information saved in cells within the spreadsheet. The week is saved in J1, and the date is saved in D1:E1 as the last day of the current work week. For example:
=TODAY()-WEEKDAY(TODAY(),3)+6
What happens when we want to archive the last week of 2015 during the first week of 2016? How do we prevent that 2015 information going into a 2016 sheet.
Will this CREATE the sheet if it does not exist? I currently have a 2015 sheet created, but will I need to manually create a 2016 sheet or will the function create the sheet on its own?

To add a custom menu to your spreadsheet, see the documentation:
Google Documentation - Custom Menus
To insert an image, open the help menu:
Do a search on "Insert Image"
You can add a custom menu, or insert an image that is linked to a script. There probably is a function or combination of functions that you could put into the spreadsheet to archive that would get data from the first spreadsheet, then you could copy all the formulas to values. That method would use formulas, then copy the formulas to values. It can all be done in code also, but you'd need to write a script to do that. So it's possible.
See posts like these:
Google Script to copy specific columns from one sheet to another sheet
Move columns of data by script
Copy from one sheet to another sheet

Related

How to stop formulas from updating at a certain time each day in Google Sheets?

I want Google Sheets to stop updating a formula in a cell corresponding to the current date at a certain time each day, but I am not well versed in scripting so I need some help. I have some examples of my data below.
I have a sheet "Time Spent in Statuses" that automatically updates every hour (with a google sheets extension). New 'Keys' are added to the sheet when they are added in the extension, i.e Key '5' doesn't exist now, but when someone creates it in the data source linked with the extension, Key '5' and its corresponding values will be automatically added, so it updates frequently with more data.
In a separate sheet, I track the daily averages of numbers from the auto update in a sheet "Daily Averages" .
Currently in the "Daily Averages" sheet, I use a formula to calculate the average of each column in the "Time Spent in Statuses" sheet. This formula is pre-filled for days upcoming. At the end of each day, I have to go to this sheet and Copy and Paste > Values Only to record the averages for that day and stop the formula from continuing to update the next day. I use the 'Date' column and the Avg columns to show change in the daily averages over time in a dashboard.
What I'm looking for is some kind of logic that will look at the 'Date' column in the "Daily Averages" sheet and if it equals the current date and the time is 11:59 pm (or some other set time), then automatically Copy and Paste > Values Only. Or something similar so that I don't have to go in and manually paste values only every day. Does anyone have any experience doing something like this?
What you're looking for is a time-driven trigger in Apps Script. You can write a script and set it to run daily at a specific time.
There are multiple approaches that you can take when writing the script, but based on the sample that you provided, you can try the following code:
function setDailyAverage() {
let ss = SpreadsheetApp.getActiveSpreadsheet()
let avgsheet = ss.getSheetByName("Daily Averages")
//this is a string with today's date in format mm/dd/yyyy, like in your sample
let today = new Date().toLocaleDateString("en-US")
//this will do a search of today's date and return the row number
let row = avgsheet.createTextFinder(today).findNext().getRow()
let avgcell = avgsheet.getRange(row,2) //gets column 2 in the row corresponding to today
let giavgcell = avgsheet.getRange(row,3) //gets column 3 in the row corresponding to today
//This reads the values in each cell and overwrites the formula with the actual value
avgcell.setValue(avgcell.getValue())
giavgcell.setValue(giavgcell.getValue())
}
To add the script go to Extensions > Apps Script and paste it there, then on the left side go to Triggers > Add Trigger, then the trigger settings should look like this:
This would run the script every day between 11pm and midnight, and pretty much just automate the same "Copy and Paste > Values Only" process that you're following. You still would need to have the pre-filled rows for each date so keep that in mind. With the trigger you could also automate the creation of each row daily but I don't know if this would interfere with your workflow.

How do you track automated data inputs in Google Sheets over time?

I have a google sheet that runs a report on data that is automatically updated. What I would like to do is compare the new inputs with the old inputs to determine if the changes were positive or negative. How would you go about automating a sheet to track these changes?
Changes happen monthly
there would be a score 1-100; 100 being the best
would like to store this data over time for a historical view
Any advice would surely be appreciated
The numbers in each criteria change every month producing a score at the end of the table called Current Score
This score is then pulled into the historical tab as the "Current Score"
What I would like to see happen is that the Current score be saved every month and processed with a percentage change month over month
So I would need a function that stores a copy of the results before they change, processes a new score, and then calculates the difference between the two. Example here is the Dec score (stored values) compared to the most recent score.
Here is a link to the working example
https://docs.google.com/spreadsheets/d/1ImbRhWqGjvIx2CFRKapZ2wmxC9qpSKxxCbHr5tPOBOs/edit#gid=0
Solution
You can automate this process by using Google Apps Script. Open the script editor by clicking on Tools > Script Editor. It is based on JavaScript and allows you to create, access and modify Google Sheets files with a service called Spreadsheet Service.
In addition, you can use Time-driven triggers to run the script automatically once a month. To set it up, click Triggers in the left bar, then Add Trigger and select Time-driven in Select event source. You can now specify the month timer and the exact day and hour you want the script to run. However, I recommend that you do some testing before setting up the trigger to check that you get the desired results. You can test the code by clicking Run in the Editor.
Explanation of the code
There are three functions in the code. The main function is called updateScores and it does what you described in the question. It takes the current score, stores it in a new column and calculates the difference from the last month. Try this function and if you like the result, you can put the trigger in the main function. This way, the trigger calls main which its only responsibility is to call the other two functions. The first is updateScores, which I have already explained, and the second is clearScores, which clears all the values of Reports so you don't have to do it manually and you can start writing the new values for the new month.
I have added some comments so you can understand what each line does.
var lr = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('report').getLastRow()
function updateScores() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Historical')
var currentValues = ss.getRange('B2:B'+lr).getDisplayValues() // get current score
ss.insertColumnsAfter(2,2) // insert two new columns (current score and percent difference)
ss.getRange('D2:D'+lr).setValues(currentValues) // paste stored score
ss.getRange('C2:C'+lr).setFormula('=if(D2=0,"N/A",B2/D2-1)') // apply formula for last stored scores
ss.getRange('E2:E'+lr).setFormula('=if(F2=0,"N/A",D2/F2-1)') // correct formula reference
ss.getRange('E2:E'+lr).copyFormatToRange(ss,3,3,2,lr) // copy format percent
ss.getRange('F2:F'+lr).copyFormatToRange(ss,4,4,2,lr) // copy format scores
var month = new Date().toString().split(' ')[1] // get current month
ss.getRange('D1').setValue(month + ' score') // write current month on last stored scores
var diff = ss.getRange('E1').getDisplayValue() // get diff symbol
ss.getRange('C1').setValue(diff) // write diff
}
function clearScores(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('report')
ss.getRange('B2:G'+lr).clear()
}
function main(){
updateScores()
clearScores()
}

Get the previous date from employee record with reference for the current date using 2 sheets [Google Sheets]

I have an excel file and need to update them to Google sheets. The problem is I cannot convert the functions in my excel to Google sheets.
Can anyone help me get the correct function for previous date from employee record with reference for the current date using 2 sheets [Google Sheets]
Excel function:
=AGGREGATE(14,6,Sheet2!K:K/(Sheet2!K:K<X2)/(Sheet2!A:A=A2),1)
I have tried QUERY function but I haven't found any examples online that could get the correct result.
From the 1st sheet 'Main Data to LOAD' I need to adjust column 'G' and 'I' it to get result.
Sheet 2 Employee record history used for checking the correct date for the first sheet.
Here is a mock sheet so anyone can try: (Kindly make a copy first for testing, I have an extra copy but just to be safe. Thanks)
https://docs.google.com/spreadsheets/d/16pZgf7igkt27Ep8a94-5t1M8KEW5wxP5uzSdHCNx_k4/edit?usp=sharing
Let me know if more information is needed.
Kind regards,

Google Apps Script- Copy & paste data from column one row at a time

(Please note: JavaScript, Stack Overflow posting, & Google Script novice)
THE BACKGROUND: I'm attempting to use a Google Sheet Email Notification Add On to trigger notifications when a specific value is seen in a Google Sheet. The config requirements of the add on look for a TextValue, however it has trouble finding the value in a pivot table (where my data is sorted). I've tried moving the data to another sheet with a QUERY formula, however the resultant value is not seen by the add on as a TextValue but rather a cell formula.
My workaround to this is to use a script to copy & paste the data from my pivot to a separate sheet. I used this post as my guide to create my script. It works, however because it pastes all column values at once, the add on is having trouble identifying the trigger TextValue.
THE QUESTION: instead of having the entire column copied and pasted at once, how can I tweak this script to copy and paste a row at a time with a slight delay (1-2 seconds)? This delay will allow the add on to see the the target TextValue and execute the notification (I've tested this manually and it works as expected). Any help in modifying this script (or completely changing the logic if necessary) would be greatly appreciated!!
//Copy contents of inventory column daily to run notification add on
function readInventoryNum() {
var sheetFrom = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Inventory Totals");
var sheetTo = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Testing123");
// Copy from 2nd row, 7th column, all rows for one column
var valuesToCopy = sheetFrom.getRange(2, 7, sheetFrom.getLastRow(), 1).getValues();
//Paste to another sheet from first cell onwards
sheetTo.getRange(1,sheetTo.getLastColumn()+1,valuesToCopy.length,1).setValues(valuesToCopy);
}

Beginner in desperate need: pastevalue() to create historical tab for investments

Thank you very much in advance for your help, I'm new to coding but proficient with standard Excel functions. I would greatly appreciate any input on this project.
I want to create a Google spreadsheet that has 3 sheets. The first is a DATA sheet which lists stock tickers and provides live prices via Google finance {=googlefinance(VTI,price)}.
The second sheet is the MASTER sheet that aggregates all of the positions, including number of shares in stocks, quantity in fixed income instruments, quantity in bullion, etc. The prices used to calculate current market value of positions are drawn from the DATA sheet. All values are added together to create a total value cell, E57, that updates itself automatically from the google finance data throughout the trading day. This all works fine.
The final sheet is the HISTORY sheet. Here's what I want to do. I want cell E57 to copy to this sheet once a day at market close so I have a daily history of the aggregate portfolio. Each time the script copies and pastes the value to the HISTORY sheet, it needs to paste on the next available row in the same column. So far, I've written a script that successfully copies and pastes the value at a defined time interval (using Project Triggers), but it just keeps pasting over the previous value. How can I make it paste to each successive open cell and generate a list?
Also, I need all of this to work without me signing in or opening/activating the sheet. I want it to run completely autonomously, that's why I'm activating the sheet via openById instead of using the ActiveSheet code (I think that reasoning is correct, but not sure).
Here's the script I have:
function PasteValue() {
var ss = SpreadsheetApp.openById("0Ao2pCtssx6TcdGpDWFpSXy1pUXA3MlAtSjZFVHlaZVE");
ss.getRange("MASTER!E57").copyTo(ss.getRange("HIST!C5"),{contentsOnly:true});
}
What do I do to improve?? Thank you!​
Your code suggests the name of the history sheet is HIST.
I think there are a few ways to do this:
Option 1:
Uses the getLastRow() method
function PasteValue() {
var ss = SpreadsheetApp.openById("0Ao2pCtssx6TcdGpDWFpSXy1pUXA3MlAtSjZFVHlaZVE");
var nextRow = ss.getSheetByName('HIST').getLastRow()+1;
ss.getRange("MASTER!E57").copyTo(ss.getRange("HIST!C" + nextRow),{contentsOnly:true});
}
Note that option 1 will not work if you have a column of cells that contain formulas that have been copied down to the bottom of the sheet.
Option 2:
Loops through the cells in column C to find the first blank cell.
function PasteValue() {
var ss = SpreadsheetApp.openById("0Ao2pCtssx6TcdGpDWFpSXy1pUXA3MlAtSjZFVHlaZVE");
var values = ss.getRange("HIST!C:C").getValues();
for (vari=0; i<values.length; ++i) {
if (values[i][0] == "") {
var nextRow = i+1;
break;
}
}
ss.getRange("MASTER!E57").copyTo(ss.getRange("HIST!C" + nextRow),{contentsOnly:true});
}
Option 2 should work as long as you have no blank cells in column C.
Option 3:
Use the appendRow() method
Good luck!