Google Sheets, For Loop to auto update stocks from google api - javascript

As the title describes I'm trying to update a stock price with a script. I understand that this is likely trivial for most of you, but it's my first time scripting with google sheets.
From what I can see this code should be okay and the code within the loop does work on it's own.
It makes a list for for every time the list has a value it will process the command. Currently the command will only repeat on the same row as I've not figured how to increment the row properly yet.
I want to read from column A and as long as there is a value to increment which A row is read to get the stock symbol, pull the value, and paste it in an incremented E row.
function getData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var symbol = ss.getRange("A2:A").getValues();
for (var row = 2, var count = symbol.length; row < count; row++) {
if (symbol[row] !=''){
ss.getRange('E2').setValue('=GOOGLEFINANCE(A2)');
}
}
}

I think this will get you what you want. The issue with your script was that the E2 was hardcoded in, as was the A2 so it didn't iterate through as needed.
function getData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var symbol = sheet.getRange("A2:A").getValues();
for(i=0; i<symbol.length; i++)
{
if (symbol[i]!=""){
ss.getRange('E'+(i+2)).setValue('=GOOGLEFINANCE(A'+(i+2)+')');
}
}
}

Related

How do I input an specific cell for every i in a loop on google script?

One of my projects is making a sales spreadsheet.
The sales spreadsheet contains the names of the products and their prices are in the documentation, the challenge is getting the prices to automatically show up on the cell right next to the product name in the spreadsheet.
Here's what I did:
function Autoprice() {
var sales = SpreadsheetApp.getActive().getSheetByName('Sales')
var salesrow = sales.getRange('D2:D'+sales.getLastRow())
var productnames = salesrow.getValues()
size = productnames.length+1
for (var i = 0; i< size; i++){
if (productnames[i+1]=='Diary')
{
sales.getRange('F'+i).setValue(31.90)
}
And I just input all the prices manually.
The thing is, google script does not read the sales.getRange('F'+1) as I thought it would, and I can't find the correct way to read that for every item in 'DI' cell, i want to put a price on 'FI' cell.
Try using this script, I modified a couple of lines in the sample you shared and added comments next to it to explain.
function Autoprice() {
var sales = SpreadsheetApp.getActive().getSheetByName('Sales')
var salesrow = sales.getRange('D2:D'+sales.getLastRow())
var productnames = salesrow.getValues()
size = productnames.length+1
for (var i = 0; i< size; i++){
if (productnames[i]=='Diary') //If you do productnames[i+1], you're not starting from the beginning of the range, basically you're starting from D3 instead of D2
{
sales.getRange(i+2,6).setValue(31.90) //You can try getRange(row, column) instead
}
}
}
Reference:
getRange(row, column)
You are trying to loop through a 2-dimensionall array (not technically... but each element is a single array).
So to see D2's value you would need productnames[0][0]
However, you can easily fix this using the flat() function. Modify one line of code below:
var productnames = salesrow.getValues().flat();
Also consider learning to use the debugger. If you step through your code, this is easy to see.

Google Script return value from one sheet to another sheet

This is my first Google Script and I'm struggling a little bit while trying to bring back the values from a specific cell & sheet to another sheet.
I have a total of 18 columns, being the first one the ID which is going to be the input that the user would need to add in order to retrieve the data from one sheet to another. As the first one is the ID, and will be already be inputted by the user, I would need to retrieve the data from columns 2 to 18
Here is my code:
function SearchID() {
var columnIndex = 0;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("Manual Costs App"); // App sheet
var str = formS.getRange("D6").getValue(); // The ID to search will be inputted here
var dataS = ss.getSheetByName("Inputs").getDataRange().getValues(); // Retrieving the data based on the user input
for (var i = 0; i<=dataS.length; i++) {
var row = dataS[i];
if (row[columnIndex] == str) {
formS.getRange("D9").setValue(row[1]);
formS.getRange("D13").setValue(row[2]);
formS.getRange("D14").setValue(row[3]);
formS.getRange("D15").setValue(row[4]);
formS.getRange("D16").setValue(row[5]);
formS.getRange("D18").setValue(row[6]);
formS.getRange("D19").setValue(row[7]);
formS.getRange("D20").setValue(row[8]);
formS.getRange("D21").setValue(row[9]);
formS.getRange("D22").setValue(row[10]);
formS.getRange("D23").setValue(row[11]);
formS.getRange("D25").setValue(row[12]);
formS.getRange("D26").setValue(row[13]);
formS.getRange("D27").setValue(row[14]);
formS.getRange("D28").setValue(row[15]);
formS.getRange("D29").setValue(row[16]);
formS.getRange("D30").setValue(row[17]);
break;
}
}
}
The link to a sample spreadsheet of what I'm building is here
Update: Everything is fixed now! What I did was removing the space in the for loop. After that, it retrieved the data but a TypeError: Cannot read property '0'. Also solved it adding a break after the loop to avoid it.
It's a type in your for loop, notice how spelled length:
for (var i = 1; i <= values.lenght; i++)
You also don't want to set values line by line like you do, get a longer range and set the values with setValues() rather than setValue(). There's quite a bit of refactoring to do there actually.
The user did found the answer and updated it on the question.
Posting here as community wiki so it can be seen more clearly.
User's answer:
Update: Everything is fixed now! What I did was removing the space in the for loop. After that, it retrieved the data but a TypeError: Cannot read property '0'. Also solved it adding a break after the loop to avoid it.
function SearchID() {
var columnIndex = 0;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("Manual Costs App"); // App sheet
var str = formS.getRange("D6").getValue(); // The ID to search will be inputted here
var dataS = ss.getSheetByName("Inputs").getDataRange().getValues(); // Retrieving the data based on the user input
for (var i = 0; i<=dataS.length; i++) {
var row = dataS[i];
if (row[columnIndex] == str) {
formS.getRange("D9").setValue(row[1]);
formS.getRange("D13").setValue(row[2]);
formS.getRange("D14").setValue(row[3]);
formS.getRange("D15").setValue(row[4]);
formS.getRange("D16").setValue(row[5]);
formS.getRange("D18").setValue(row[6]);
formS.getRange("D19").setValue(row[7]);
formS.getRange("D20").setValue(row[8]);
formS.getRange("D21").setValue(row[9]);
formS.getRange("D22").setValue(row[10]);
formS.getRange("D23").setValue(row[11]);
formS.getRange("D25").setValue(row[12]);
formS.getRange("D26").setValue(row[13]);
formS.getRange("D27").setValue(row[14]);
formS.getRange("D28").setValue(row[15]);
formS.getRange("D29").setValue(row[16]);
formS.getRange("D30").setValue(row[17]);
break;
}
}
}

get x cell in range google sheets app script

Using a google sheets apps script, Is it possible to get the X cell in a range of cells as shown below:
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cells = sheet.getRange("D6:BF100"); // the range
for (var x = 0; x < 100; i++) {
var cell = cells[row][x]; // this is the line that doesn't work
if (someCondition(x)) {
cell.setBackground("red");
}
}
I don't want to change the colors for every single cell, just the ones that have the correct condition.
I know it is possible to do something like this:
var cell = sheet.getRange(row+i);
But this method takes a very long time to complete the for loop as there are hundreds of cells that need to be scanned. I would rather only use getRange once with the entire range (instead of just one cell at a time) and then from that range (it should make a 2d array right?) set the cell values. I think that would be a lot faster.
Is there a different way to do it faster, or do I just need to do this: var cell = cells[row][x]; a different way.
Thanks!
It looks like your for loop is constructed incorrectly. You increment the variable i that isn't defined or used anywhere. Also, you use the variable row without defining it.
It takes forever because it has to query your sheet each time you call cells.getRange() Instead, you can query once using cells.getValues() to get the whole range, and then change the cells color that meet the condition one at a time.
Try the following;
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cells_range = sheet.getRange("D6:BF100");
var cells_values = cells_range.getValues();
for (var col = 1; col <= cells_values[0].length; col++) {
for (var row = 1; row <= cells_values.length; row++) {
if (someCondition(cells_values[row][col])) {
cells_range.getCell(row, col).setBackground("red");
}
}
}
This is just my own answer to help users who might get to this question.
Once you have a range of cells, like this:
var range = sheet.getRange("your range");
You can do this to get a specific cell:
var cell = range.getCell(row, col);

Updating a sheet with a value if strings match on two sheets

Sheet 2 has all the items and their statuses, while Sheet 1 has only some of the items from Sheet 2. I want to be able to see every time an item mentioned on Sheet 1 is listed as having a status update, i.e. e date, on Sheet 2.
Here's what I have so far, but having trouble calling the right range to work with. Is there a simpler way to do what I want to do?
function statusupdate() {
var activesht = SpreadsheetApp.getActiveSpreadsheet();
var statussht = activesht.getSheetByName("Sheet 2"); //get sheet on which status update occurs
var statusrng1 = statussht.getRangeByName('B');
var statusrng2 = statussht.getRangeByName('C');
var mainsht = activesht.getSheetByName("Sheet 1"); //get sheet where you show a specific thing has been updated, if that thing mentioned here.
var mainrng = mainsht.getRangeByName('F');
if (statusrng1 == mainrng) {
var date = statusrng2.getValue();
var daterng = mainrng.getRangeByName('E');
daterng.setValues(date);
}
}
Spreadsheet formula
You can have the rows in one sheet follow those in another without using a script. For example, say we have a sheet named Items that contains one row for every item we carry, with the item number in the first column.
We can use VLOOKUP() to search for the row containing info about individual items, and select specific columns from it.
For example, this formula would be used in B2, and could be copied to other cells in our sheet:
=VLOOKUP($A2,Items!$A$2:$C$7,COLUMN(),false)
Script
There are a few issues with your script.
.getRangeByName('B') - This method gets a named range. Given the name, I suspect you mean to get column B, and NOT a named range. If that's the case, you could use this instead:
var statusrng1 = statussht.getRange('B:B');
In A1Notation, the range B:B is the entire column B.
You intend to copy values, so there is another step required beyond identifying ranges; you need to first read the values from a range, and then later write them to a different range. For that, you need to use methods like getValues() and setValues().
Here's an updated version of your script, adapted to the example spreadsheet described above.
function statusupdate() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
//get sheet on which status update occurs
var statusSheet = ss.getSheetByName("Items");
var statusRange = statusSheet.getDataRange();
var statusData = statusRange.getValues();
//get sheet where you show a specific thing has been updated, if that thing mentioned here.
var trackingSheet = ss.getSheetByName("Tracking");
var trackingRange = trackingSheet.getDataRange();
var trackingData = trackingRange.getValues();
// Loop over all rows in the Tracking sheet to update from the Items sheet
// Start with row=1, because row 0 contains headers
for (var row=1; row<trackingData.length; row++) {
var item = trackingData[row][0];
if (item == '') continue; // skip rows without item #
// Look for item in Items sheet
var statusRow = null;
for (var sRow=1; sRow<statusData.length; sRow++) {
if (statusData[sRow][0] == item) {
// Found our match, grab that row
statusRow = statusData[sRow];
break;
}
}
// If we found a matching row, copy the status
if (statusRow) {
// Customize this depending on how your sheets are organized
trackingData[row][1] = statusRow[1];
trackingData[row][2] = statusRow[2];
}
}
// All values have been copied to trackingData, now write to sheet
trackingRange.setValues(trackingData);
}

I want to hide Columns on each sheet according to a value in Cells in row 1

I get an error every time I try this here is what I am using. I get this error:
TypeError: Cannot find function hideColumns in object Sheet,Sheet,Sheet,Sheet,Sheet."
I am not very familiar with scripts and cant seem to get this to work.
function Hide() {
// get active spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// look at all sheets
var sheet = ss.getSheets();
// get data
var data = ss.getDataRange();
// get number of columns
var lastCol = data.getLastColumn()+1;
Logger.log(lastCol);
// itterate through columns
for(var i=1; i<lastCol; i++) {
if(data.getCell(1, i).getValue()[0] == '*') {
sheet.hideColumns(i);
}
}
}
Could some one help me?
I am assuming, you are using this reference. I guess, you want to do the following:
Iterate all the columns in the data range.
If the value of the first row of column equals * then hide that column.
I am not familiar with Google Apps Services, but I think your code should look like this:
function Hide() {
// get active spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// look at all sheets
//var sheet = ss.getSheets();
// get data
var data = ss.getDataRange();
//get the sheet this range belongs to.
var sheet = data.getSheet();
// get number of columns
var lastCol = data.getLastColumn()+1;
Logger.log(lastCol);
// itterate through columns
for(var i=1; i<lastCol; i++) {
if(data.getCell(1, i).getValue()[0] == '*') {
sheet.hideColumns(i);
}
}
}
Since .getSheets return an Array of Sheet objects you can not call that function.

Categories