Script for Google Sheets to copy a column daily - google-apps-script

Every day we put all of the times our product is sent in column B of Sheet 1. Would it be possible at close of play every day (say 23:55) to copy the contents of column B to a column in Sheet 2?
The big problem here is every day it would move along a column in sheet 2. So Monday would be pasted into B, Tuesday C, and so on.
Basically want to use sheet 2 to keep a record of all our send times.

Here is a script that copies column B of Sheet1 to a new column in Sheet2. I think the variable names and method names are self-explanatory. To have it run daily, in the script editor go to "Edit > this project's triggers" and set a time-driven trigger to run daily between 23:00 and midnight. (You don't get to choose the exact minute; it will be about the same every day but Google chooses it itself at the time of trigger creation).
function copyData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceRange = ss.getSheetByName("Sheet1").getRange("B:B");
var targetSheet = ss.getSheetByName("Sheet2");
targetSheet.insertColumnAfter(targetSheet.getLastColumn());
var targetRange = targetSheet.getRange(1, targetSheet.getLastColumn()+1);
sourceRange.copyTo(targetRange);
}

Related

Macro Google Sheet Copy and Paste on Every day

needs help regarding the macro
I currently have such a code
function getDynamicRows(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('B.Wioski');
var sourceRange = sheet.getRange('A1:F26500');
var data = sourceRange.getValues(); // Array of arrays [[Row1],[Row1],[Row3]]
// add data to next empty row in the static sheet.
var targetSheet = ss.getSheetByName('TW');
data.forEach(function(row){
targetSheet.appendRow(row)
}) ;
}
but the google sheet has a problem because the macro works max 6 min and it reads a maximum of 400 lines
and I would need a Macro that would copy A1 cells to F26500 where it would perform this activity 4 times a day every 6h for a maximum of 7 days and then on the 8th day it would delete the first day or overwrite the cells again
Instead of appendRow() use setValues().
If you keep exceeding the 6 mins, you can create multiple triggers (Row 1-5000, 5001-1000...) or copy the entire sheet and set formulas in your 'TW' sheet making reference to the copied sheets.

Is there a Google Sheets method to have coded formulas fill values in the next empty row each day?

I have a Google Sheets document that has 36 formulas across a row in the "Historical Data" tab. When I run the script each morning it populates the next empty row with the formulas in the previous row and then makes the previous row a value (so as to remove the formulas). I have an issue sometimes that the row with formulas loses the values and display "#N/A". I believe this is because the data is pulled from GoogleFinance.
Error in the image below.
I am curious if there is a method to do the following:
Define the formulas for each column in the code.
Run the script each morning and populate the next empty row with the values of the formulas.
The biggest item I need help with is adding the following formulas to the code so they will not be present in the worksheet. Additionally, some of the formulas rely on the value in a cell. For example the first formula is to create the date based on the date in the last row cell (A). The remaining formulas use the date from the new row columnm (a) and inputs from other columns in the new row. So when you see A2736 that is in last row and A2737 is the new row that was create when I last ran the script.
//DATE(A)=workday(A2736,1,'NYSE Holidays'!$A$2:$A$27)
//VIX9D(B)=INDEX(GOOGLEFINANCE("INDEXCBOE:VIX9D","close",$A2737),2,2)
//VIX1D(C)=INDEX(GOOGLEFINANCE("INDEXCBOE:VIX","close",$A2737),2,2)
//VIX3M(D)=index(GOOGLEFINANCE("INDEXCBOE:VIX3M","close",$A2737),2,2)
//VIX6M(E)=index(GOOGLEFINANCE("INDEXCBOE:VIX6M","close",$A2737),2,2)
//VIX1Y(F)=index(GOOGLEFINANCE("INDEXCBOE:VIX1Y","close",$A2737),2,2)
//VVIX(G)=index(GOOGLEFINANCE("INDEXCBOE:VVIX","close",$A2737),2,2)
//SPX(H)=index(GOOGLEFINANCE("INDEXSP:.INX","close",$A2737),2,2)
//VIX9D:VIX(I)=B2737/C2737
//VIX:VIX3M(J)=C2737/D2737
//VIX:VIX6M(K)=C2737/E2737
//VIX:VIX1Y(L)=C2737/F2737
//CORR, SPX , VVIX, 5(M)=correl(H2733:H2737,G2733:G2737)
//CORR, SPX , VIX, 10(N)=correl(H2728:H2737,C2728:C2737)
//Contango VIX2:VIX1(O) No formula yet
//Vix4:Vix7 Contango(P) No formula yet
//Log Ret(Q)=ln(H2737/H2736)
//V10(R)=stdev(Q2728:Q2737)
//V20(S)=stdev(Q2719:Q2737)
//HV10(T)=sqrt(252)*R2737
//HV20(U)=sqrt(252)*S2737
//VIX - HV10(V)=C2737-(T2737*100)
//VIX - hv20(W)=C2737-(U2737*100)
//VIX9D % Rank(X)=PERCENTRANK(B$2:B,B2737)
//VIX1D % Rank(Y)=PERCENTRANK(C$2:C,C2737)
//VIX3M % Rank(Z)=PERCENTRANK(D$2:D,D2737)
//VIX6M % Rank(AA)=PERCENTRANK(E$2:E,E2737)
//VIX1Y % Rank(AB)=PERCENTRANK(F$2:F,F2737)
//VVIX % Rank(AC)=PERCENTRANK(G$2:G,G2737)
//VIX9D Median(AD)=MEDIAN(B$2:B)
//VIX1D Median(AE)=MEDIAN(C$2:C)
//VIX3M Median(AF)=MEDIAN(D$2:D)
//VIX6M Median(AG)=MEDIAN(E$2:E)
//VIX1Y Median(AH)=MEDIAN(F$2:F)
//VVIX Median(AI)=MEDIAN(G$2:G)
//VDelta (VIX-VIX9D)(AJ)=C2737-B2737
Current code is below.
// Add Run button to menu
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu("Auto Trigger")
.addItem("Run","runAuto")
.addToUi();
}
// Define function to run with menu button
function runAuto() {
recordValue()
}
function createTimeDrivenTrigger() {
// Trigger every Weekday at 09:00.
ScriptApp.newTrigger('recordValue')
.timeBased()
.onWeekDay(ScriptApp.WeekDay)
.atHour(9)
.create();
}
// Record history from a cell and append to next available row
function recordValue() {
if (isNotHoliday()){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Historical_Data");
var lastRow = sheet.getLastRow();
var oldDate = sheet.getRange(lastRow,1).getValue();
var rng = sheet.getRange(lastRow,1,1,36);
rng.copyTo(sheet.getRange(lastRow+1,1,1,36));
rng.setValues(rng.getValues());
}
}
function isNotHoliday(){
var yesterday = new Date(new Date().getFullYear(),new Date().getMonth(),new Date().getDate()-1);
var formattedDate = Utilities.formatDate(yesterday, Session.getScriptTimeZone(), "M/d/yy")
var holidays = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('NYSE Holidays').getRange('A2:A').getDisplayValues().join().split(",");
return (! ~holidays.indexOf(formattedDate))
}
If you wish to run the script once every morning you could use programmatically triggers. This way you can easily set up a script run inside your desired time frame. Then you only would need to get the range of the last row and paste the formula there. I see that the script already gets the range, so you only need Range.setFormula() to drop the formula.
There is a much simpler way to do this - which is to flip time the other way.
You leave the google finance formulas in row 2 along with a =TODAY() in cell B2, with headers in row 1.
every night at 11pm, your sheet inserts a row above row 3, copies the values from row 2 into the new row 3 as values only.
That's it. super simple. you never need to copy formulas at all.
The newest prices are always at the top. This is how most people track portfolios.

Nightly Script that Inserts values into different sheet based on date - Google Sheets

I have a sheet "Sheet1" where a user inputs data in cells A3:E3. The goal is to then move that data into "Sheet2" where column A4:A34 is a numeric value for the day of the month. I want to move the data inputted on "Sheet1" into "Sheet2" on the row that corresponds with the current day of the month. Then "Sheet1" would clear itself for the next day ahead.
I'll be honest I'm not great with functions and I'm mainly looking for help on where to look to find a solution. I've tried different code that I do know how to use like Query but the issue is it doesn't lock the value in place and as soon as the values are wiped in Sheet1 they are then removed via the query.
You will need to run a function on a time-driven trigger. The function can use Range.getValues() to read the data, get the current date's day number with const dayNumber = new Date().getDate(), look up the day number in Sheet2 with Range.getValues().flat().indexOf(dayNumber), write the data with Range.setValues() and finally clear the source range with Range.clearContent().
It is unclear what the purpose the day numbers in Sheet2 serve, because the data would in any case be written once a day. It would seem simpler to always append the most recent data at the first available row and include a timestamp.
For an example of how to do this, see the appendRowsToArchiveSheet script.
Since the task is rather simple, here is the code that does the work:
// add menu Scripts
function onOpen() {
SpreadsheetApp.getUi().createMenu('🔨 Scripts')
.addItem('✅ Copy to archive', 'copy_range_to_archive')
.addItem('❌ Erase', 'erase_range')
.addToUi();
}
// erase the range A3:E3
function erase_range() {
SpreadsheetApp.getActiveSpreadsheet()
.getSheets()[0]
.getRange("A3:E3")
.clearContent();
}
// copy the range A3:E3 to Sheet 2
function copy_range_to_archive() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const src_range = ss.getSheets()[0].getRange("A3:E3");
const data = src_range.getValues();
const dest_sheet = ss.getSheets()[1];
const today = new Date().getDate();
const dest_range = dest_sheet.getRange(3 + today, 2, 1, data[0].length);
dest_range.clearContent();
dest_range.setValues(data);
}
It makes the menu 'Scripts' and two command 'Copy to archive' (the range A3:E3) and 'Erase' (the same range).

Pasting a value into a new cell each time another is updated?

I'm hoping to have 2 cells that update their value every week. Each time these cells get their values updated I would like them to also be printed onto another two cells on a different sheet. Each week these cells that they are printed onto moving down by one. For example Week 1, the two cells are printed in A1 and B1. Week 2 they are printed in A2 and B2, and so on.
I know how to do this in Excel but no idea how I can change that over to Google Sheets / Scripts.
Assumptions:
Your new inputs are in input!A1 and input!B1; and
Your outputs will by in output!A and output!B.
You can write a script by clicking on Tools on the menu and entering Script Editor.
Then write this function:
function writeData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var input = ss.getSheetByName("input")
.getRange(1, 1, 1, 2)
.getValues();
var outputSheet = ss.getSheetByName("output");
var numRows = outputSheet.getLastRow();
outputSheet.getRange(numRows + 1, 1)
.setValue(input[0][0]);
outputSheet.getRange(numRows + 1, 2)
.setValue(input[0][1]);
}
Next, set up a trigger. Within Script Editor, under Resources, select Current project's triggers and then set up your trigger. If you want it to run weekly, use a time-driven trigger. You can also set a spreadsheet-driven trigger to run on every edit. Save everything.
If you don't want to use automatic triggers, you can execute the writeData() function by adding an item on the menu bar of the spreadsheet:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({name: "Write data", functionName: "writeData"});
ss.addMenu("Custom functions", menuEntries);
}
Save, and if you refresh the spreadsheet you'll see a new item on the menu bar.

Google Apps Script copy from cell to new row

I have two sheets in My Google Spreadsheet.
Master Tracking
Daily Tracking
Master Tracking pulls in information from other tracking sheets and updates the number of miles driven by each driver in cell M7.
I want to set up Daily Tracking with Date (Column A) and Number of Miles Traveled (Column B).
I want to write a Google Apps script which will copy the data from Master Tracking!M7 to Daily Tracking (column B) but into a NEW ROW every time the script is run. I'm planning on using a trigger for it to run at the end of every work day.
I have this till now but it doesn't work.
function copyFunction() {
var inputRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master Tracking").getRange("M7:M7");
var inputValues = inputRange.getValues();
var outputRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Daily Tracking").getRange("B:B").getLastRow();
outputRange.setValue(inputValues);
}
I can't figure it out. I can get it to paste in one specific cell but I can't figure out how to paste it into a new row. Maybe getLastRow would work. I don't know.
Also, how to have a timestamp put in Column A of Daily Tracking?
Please help!
Didn't test it but should work : (see comments in code)
function copyFunction() {
var inputRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master Tracking").getRange("M7");
var inputValue = inputRange.getValue();// use simple getValue without S, get a simple value
var last = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Daily Tracking").getLastRow();// get the last row on this sheet
var outputRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Daily Tracking").getRange(last+1,1,1,2);// getRange col A & B +1 after last row
outputRange.setValues([[Utilities.formatDate(new Date(), Session.getTimeZone(), 'MM-dd-yyyy'),inputValue]]);// date string in col A and value in col B in a 2D array (note the S in setValues) -
}