I have a Google sheet trigger that splits the values in Column F when any value in that column gets edited. However I want the script to only split the 'last row', and not all the rows (even the ones above already split)
Which line of code should I add to have the script only split the last edited row in column F and not the entire range? This is my sample so far:
function Split() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('F2:F50').activate();
spreadsheet.getRange('F2:F50').splitTextToColumns();
spreadsheet.getRange('F2:F50').splitTextToColumns(SpreadsheetApp.TextToColumnsDelimiter.COMMA);
};
Kind regards,
Brendon
I believe your goal as follows.
You want to reflect splitTextToColumns(SpreadsheetApp.TextToColumnsDelimiter.COMMA) to the column "F" of the last row of the active sheet.
In this case, you can use getLastRow().
Modified script:
function Split() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('F2:F50').activate();
// spreadsheet.getRange('F2:F50').splitTextToColumns();
// spreadsheet.getRange('F2:F50').splitTextToColumns(SpreadsheetApp.TextToColumnsDelimiter.COMMA);
spreadsheet.getRange("F" + spreadsheet.getLastRow()).splitTextToColumns(SpreadsheetApp.TextToColumnsDelimiter.COMMA);
}
Reference:
getLastRow()
Related
I want to create a macro that finds the leftmost empty cell in a row, then adds today's date to that row (as in setFormulaR1C1('=TODAY()') )
I have been able to get the last empty row or column from a sheet but not, specifically, the last empty cell from the row I'm standing on.
From I want to create a macro that finds the leftmost empty cell in a row, then adds today's date to that row (as in setFormulaR1C1('=TODAY()') ), I believe your goal is as follows.
You want to find the most left empty cell in the active row and want to put a formula of =TODAY() to the cell.
In this case, how about the following sample script?
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet and save the script.
function myFunction() {
const sheet = SpreadsheetApp.getActiveSheet();
const range = sheet.getActiveRange();
const row = range.getRow();
const values = sheet.getRange(row, 1, 1, sheet.getLastColumn()).getDisplayValues()[0];
const column = values.findIndex(c => !c);
if (column == -1) return;
sheet.getRange(row, column + 1).setFormula("=TODAY()");
}
When this script is run, please select a cell in the sheet and run the script. By this, a formula of =TODAY() is put into the most left empty cell of the selected row.
When the empty cell is not found, the script is stopped.
If you want to fix the value of =TODAY() as the constant value, please modify it as follows.
From
sheet.getRange(row, column + 1).setFormula("=TODAY()");
To
const today = new Date();
today.setHours(0, 0, 0, 0);
sheet.getRange(row, column + 1).setValue(today);
References:
getActiveRange()
findIndex()
I have a scripts in my sheet which which I use to clear a cell & then add a formula to force it to update. In the script I reference the specific cell to clear and then add the formula to.
The problem I am having is that if I add a column or row to the sheet which impacts the position of the cells referenced in the script, the script then still uses the old cell range and so performs the action on the wrong cell
e.g. the cell referenced in the script that I want to clear & add the formula to is AD10. If I insert a column this cell would then need to beceome AE10 but the script still works on cell AD10.
The script I am using is
function UpdateDraft() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('AD10').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getCurrentCell().setFormula('=if($C$5<>"",IMPORTJSONAPI("https://api.sleeper.app/v1/draft/"&$C$5&"/picks" , "$..metadata.player_id", "#",1),)');
};
Thanks
Jon
One easy way to do that is to create two named ranges: formulaCell in AD10, and parameterCell in C5.
The function then becomes:
function UpdateDraft() {
const cell = SpreadsheetApp.getActive().getRange('formulaCell');
const formula = '=if( len(parameterCell), IMPORTJSONAPI("https://api.sleeper.app/v1/draft/" & parameterCell & "/picks" , "$..metadata.player_id", "#",1), iferror(1/0) )';
cell.clearContent().setFormula(formula);
}
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.
I have a Google Sheet where I collect responses and another tab where I see a report for each record.
I want to add manually a number in the cell Writing Points (as in the image below) and click Update to update the cell of that specific record in the responses tab.
I managed to get the row number depending on the student the formula is:
MATCH($D$3,Responses!D:D, 0)
And the column is always BG of the repsonses tab.
How can I achieve this through Google script? I have an idea but I don't know how to do it.
My try:
row = MATCH($D$3,Responses!D:D, 0)
SpreadsheetApp.getActiveSheet().getRange('BG'+row).setValue(newwritingpoints);
I don't know how to conver the match formula into Google script syntax and how to copy and paste the value from that cell to the responses tab.
Google Sheet link:
https://docs.google.com/spreadsheets/d/1dE6UVABhVp7WqEFdC0ptBK2ne6wEA6hCf0Wi6PxcMWE/edit#gid=2032966397
I believe your goal as follows.
When Update() of Google Apps Script is run by the button, you want to retrieve the cells "D3" and "H24" in the sheet Report.
You want to search the value of "D3" from the column "D" in the sheet Responses.
When the value of "D3" and the values of column "D" in the sheet Responses are the same, you want to put the value of "H24" to the same row of the column "BG" in the sheet Responses.
For this, how about this answer? The flow of this sample script is as follows.
Retrieve the values from the cells "D3" and "H24" in the sheet Report.
Retrieve the values from the cells "D2:D" in the sheet Responses.
Create the range list from the retrieved values.
Put the value using the range list.
Sample script:
function Update() {
var spreadsheet = SpreadsheetApp.getActive();
// 1. Retrieve the values from the cells "D3" and "H24" in the sheet `Report`.
var reportSheet = spreadsheet.getSheetByName("Report");
var searchText = reportSheet.getRange("D3").getValue();
var writingPoints = reportSheet.getRange("H24").getValue();
// 2. Retrieve the values from the cells "D2:D" in the sheet `Responses`.
var responsesSheet = spreadsheet.getSheetByName("Responses");
var values = responsesSheet.getRange("D2:D" + responsesSheet.getLastRow()).getValues();
// 3. Create the range list from the retrieved values.
var ranges = values.reduce((ar, [d], i) => {
if (d == searchText) ar.push("BG" + (i + 2));
return ar;
}, []);
// 4. Put the value using the range list.
responsesSheet.getRangeList(ranges).setValue(writingPoints);
}
In this script, it also supposes the case that the value of "D3" might find at several rows in the sheet Responses.
References:
reduce()
Class RangeList
Not sure how to go about incrementing the number values on my google spreadsheet by 1 with a button, the script I'm using only increments the first cell and copies that down. How can I make the script increment the whole column and it's individual cells by 1?
function increment(){
var cell = SpreadsheetApp.getActiveSheet().getRange("C2:C86");
var cellValue = cell.getValue();
cell.setValue(cellValue + 1);
}
You want to add 1 to the cells of "C2:C86".
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this modification? Please think of this as just one of several answers.
Modified script:
function increment(){
var cell = SpreadsheetApp.getActiveSheet().getRange("C2:C86");
var cellValues = cell.getValues().map(function(row) {return [row[0] + 1]}); // Modified
cell.setValues(cellValues); // Modified
}
Flow:
Retrieve the values from the cells of "C2:C86".
Add 1 for the value of each cell.
Put the values to the range of "C2:C86".
References:
getValues()
setValues()
map()
If I misunderstood your question and this was not the result you want, I apologize.