So I can get the xpath working for "mainstream" stocks like CVNA with this line:
=REGEXEXTRACT(INDEX(IMPORTXML("https://finance.yahoo.com/quote/CVNA?p=CVNA";"//*[#id='quote-header-info']");;3); "\d+.\d+|\d+")+0
But when trying to point to a specific exchange like Oslo exchange I get an error.
Would like to scrape stock prices from NEL.OL
Any suggestions?
As the page is built in javascript on the client side and not on the server side, you will not be able to retrieve the data by the importxml / importhtml functions. However, the page contains a json which you can retrieve and analyze to retrieve the information you need.
var source = UrlFetchApp.fetch(url).getContentText()
var jsonString = source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}'
var data = JSON.parse(jsonString)
for instance, for marketprice, you can retrieve the informations by
function marketPrice(code) {
var url='https://finance.yahoo.com/quote/'+code
var source = UrlFetchApp.fetch(url).getContentText()
var jsonString = source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}'
var data = JSON.parse(jsonString)
var regularMarketPrice = data.context.dispatcher.stores.StreamDataStore.quoteData[code].regularMarketPrice.raw
return regularMarketPrice
}
https://docs.google.com/spreadsheets/d/1sTA71PhpxI_QdGKXVAtb0Rc3cmvPLgzvXKXXTmiec7k/copy - column G
Related
I have read everything I could find on this site and others about methods of getting text out of a google sheet and into a google doc. I don't want the "data" in a table. It's not a huge amount of data to work with, so I'm able to tinker with the source sheet a bit and found a solution using a ListItem append approach.
Here's what I've come up with:
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('Agenda')
.addItem('CreateAgenda', 'createagenda')
.addToUi();
}
function createagenda() {
// take info from agenda topic google spreadsheet and put in a google doc
var documentId=DriveApp.getFileById('_______________').makeCopy().getId();
//add today's date to new filename
var d = new Date();
var curr_date = d.getDate();
var curr_month = d.getMonth() + 1;
var curr_year = d.getFullYear();
var theDate = curr_month + "_" + curr_date + "_" + curr_year;
DriveApp.getFileById(documentId).setName(theDate + '_CommitteeAgenda');
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("AgendaPlanning");
//Determine how many items are in the list to set count in For Loop
sheet.getRange('B2').activate(); // Starting cell in column with agenda items
sheet.getCurrentCell().getNextDataCell(SpreadsheetApp.Direction.DOWN).activate();
var last_row_submissions = sheet.getCurrentCell().getRowIndex();
const body = DocumentApp.openById(documentId).getBody();
for (var i=2; i<= last_row_submissions; i++){
var currentline = sheet.getRange(i,14).getValue();
var agenda_item = body.appendListItem(currentline);
}
var documentsInPacket = sheet.getRange("B28").getValue();
var doclist = body.appendListItem(documentsInPacket);
}
For the most part this works because items on the agenda document are numbered, but because I've used the ListItem approach, the final item (Documents) has a number to it (18) which I don't want. Since someone has to go in and put in meeting info (zoom link, etc.) then having one more thing to do isn't horrible, but....
Minutes (6:30)
Commentary (6:35)
Adjourn (6:40)
Documents: Superintendent report; .....etc.
? Is there an easier way to do this? Can I get rid of the number preceding the last item? How can you get the value of a cell from sheets and have google doc accept it as text?
Thank you!
You can use body.appendParagraph(documentsInPacket) instead of body.appendListItem(documentsInPacket) to achieve the results you are looking for.
Basically what I'm trying to do is have google sheets take the user input and plug it into a website template that will then be used to scrape information from that website.
Example would be:
User selects "candy" from cell A2
I would then like to have another cell develop the website: www.something.com/candy/secondpart
This should work. You'll need to create some sort of trigger to make this happen, but this will return the HTML content.
function pullDateFromWebsiteBasedOnCell() {
const theSS = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); //or specify
const theFirstPart = "https://www.something.com/";
const theLastpart = "/secondPart/";
var theMiddlepart = theSS.getRange("A2").getValue();
var theURL = theFirstPart+theMiddlepart+theLastpart;
var response = UrlFetchApp.fetch(theURL);
var theHTMLtext = response.getContentText(); //gets content as HTML blob.
Logger.log(theHTMLtext);
return theHTMLtext;
}
Like the title says, is there a way to get the highs and lows of a stock price during the day after a certain time? There's a way to get the days high and low over a period of time:
=GOOGLEFINANCE("AMZN","high","05/01/2020","05/10/2020","DAILY")
=GOOGLEFINANCE("AMZN","low","05/01/2020","05/10/2020","DAILY")
But what about during the day during a specific time period? For example from 9:12AM PST to 11:23AM PST?
Solution#3 : you can use Alpha Vantage by 2 ways, add-on GSheets or a custom function i.e. :
// mike steelson
var apikey = 'xxxxxxxxxxxxxx'
function getAllDataJSONv2(code) {
var url = 'https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol='+code+'&interval=5min&apikey='+apikey
var data = JSON.parse(UrlFetchApp.fetch(url).getContentText())['Time Series (5min)']
var resultat = []
for (var elem in eval(data)){
resultat.push([elem,eval(data[elem]['1. open']),eval(data[elem]['2. high']),eval(data[elem]['3. low']),eval(data[elem]['4. close']),eval(data[elem]['5. volume'])])
}
return resultat
}
the apikey is free for up to 500 requests a day. https://rapidapi.com/alphavantage/api/alpha-vantage
no, not possible with GOOGLEFINANCE. you can get only the daily value which is usually from 16:00:00
your only other option is to find some website (which doesn't use JavaScript) that holds values you wish for and scrape it into google sheets
Solution1 : You can use Yahoo Finance to retrieve the information you want
function getHistoric(url){
var source = UrlFetchApp.fetch(url).getContentText()
var jsonString = source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}'
var data = JSON.parse(jsonString).context.dispatcher.stores.HistoricalPriceStore.prices
var result = []
data.forEach(function(elem){
result.push([elem.date,elem.open,elem.high,elem.low,elem.close])
})
return result
}
https://docs.google.com/spreadsheets/d/1Kly5-Vu5jBfrl6xFljdICFJW369X-OCjB22z3Ouzt4Y/copy
Solution#2 : you can build your own data based on yahoo finance https://docs.google.com/spreadsheets/d/1QlqpPkIMjE8_jT6kNME1cLrMmQZ9cSzG-SR2Jjivvqo/edit?usp=sharing
//Mike Steelson
var histo = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('historic')
var code = histo.getRange('B1').getValue()
//put a trigger on historic
function historic(){
if (testDateHour()==true) {histo.appendRow([new Date(),marketPrice(code)])}
}
function marketPrice(code) {
var source = UrlFetchApp.fetch('https://finance.yahoo.com/quote/'+code).getContentText()
var data = JSON.parse(source.match(/(?<=root.App.main = ).*(?=}}}})/g) + '}}}}')
return data.context.dispatcher.stores.StreamDataStore.quoteData[code].regularMarketPrice.raw
}
function testDateHour(){
var d = new Date();
// not on sunday and saturday and between 10am and 4pm
if (d.getDay()!=0 && d.getDay()!=6 && d.getHours()>=10 && d.getHours()<=16) {return true}else{return false}
}
Configure your local settings (PST) + update if necessary the period when you want to retrieve the information. Then put the trigger (1min)
Been collecting historical bitcoin data from CoinGecko API using Google Sheets. Manual method where I have to open the sheet and copy and "Paste values only" to paste data in the history list. History on the left side and data collection on the right.
I want to automate this process if possible. Current code pulls 10 rows of data that's not in the history yet. The history row ends in a "BOTTOM" field to indicate bottom of page. Script Editor already set to run at midnight for data collection.
Here is my example:
https://docs.google.com/spreadsheets/d/1kAcVtF2x9ox7gNCt5liQdhApQpGaBw1kl4I8PjKMfx8/edit?usp=sharing
Answer
You have to make use of the Sheet and Range classes.
Code
In order to automate that process add the following code to your existing Apps script:
function Pull_History_bitcoin() {
//PREVIOUS CODE
var days = parseInt(targetSheet.getRange("J4").getValue().toString());
if (days > 0) {
var range = targetSheet.getRange("G6:J" + (5+days)).getValues();
var lastRowHistory = targetSheet.getRange("G1").getValue();
var nextLastRowHistory = parseInt(lastRowHistory[1]) + days;
var bottomCell = targetSheet.getRange("A" + nextLastRowHistory);
bottomCell.setValue("BOTTOM");
var nextRange = targetSheet.getRange(`${lastRowHistory}:D` + (nextLastRowHistory - 1));
nextRange.setValues(range);
}
}
Where days define the number of entries after calling the external API.
Don't worry about the values rounded because they are just showing rounded, the current values are like the original ones.
Reference
Sheet class
Range Class
Here below find my full google-apps-script as reference to anyone wishing to acquire crypto historical information from the free CoinGecko Api service.
function Pull_History_bitcoin() {
var targetSS = SpreadsheetApp.getActive();
var targetSheet = targetSS.getSheetByName("bitcoin");
// To force an update
targetSheet.insertRowBefore(3);
targetSheet.deleteRow(3);
// Copy newly acquired history into the history columns
var days = parseInt(targetSheet.getRange("J4").getValue().toString());
if (days > 0) {
var range = targetSheet.getRange("G6:J" + (5+days)).getValues();
var lastRowHistory = targetSheet.getRange("G1").getValue();
//var nextLastRowHistory = parseInt(lastRowHistory[1],4) + days;
var nextLastRowHistoryStr = lastRowHistory.slice(1);
var nextLastRowHistory = Number(nextLastRowHistoryStr) + days;
var nextRange = targetSheet.getRange(`${lastRowHistory}:D` + (nextLastRowHistory - 1));
nextRange.setValues(range);
var bottomCell = targetSheet.getRange("A" + nextLastRowHistory);
bottomCell.setValue("BOTTOM");
}
}
I am making a spreadsheet for people to submit information and when they submit the information on the entry sheet, the data is copied to a new sheet and then cleared from the entry sheet so that it is ready for another entry. When the new sheet is created, it is renamed and then shared with me so that I can view each sheet that people send in. Right now my script isn't working and I am not receiving the new sheets when they are made.
function Copy() {
var sss = SpreadsheetApp.getActiveSpreadsheet();
var ss = sss.getSheetByName('Sheet1');
var range = ss.getRange('A1:J30');
var strange = ss.getRange('A2:J30');
var data = range.getValues();
sss.appendRow(data[0]);
strange.clear();
var tss = SpreadsheetApp.create('New Entry');
var ts = tss.getSheetByName('Sheet1');
ts.getRange(1, 1, data.length, data[0].length).setValues(data);
var r = ts.getRange('A2:A3');
r.getA1Notation() == 'A2';
tss.setName(r.getValue());
tss.addEditor("john.doe#gmail.com");
}