I used CRYPTOFINANCE.ai with Google Spreadsheets for some months now and I want to move on, to be able to get cryptocurrency data by "myself".
I discover the CoinMarketCap API and that should do it. I succeed in import one or many quotes. Now I would like to import the full listings data so I can have all the prices updated, in order to get a realistic value of my portfolio.
Here is what I have now, but it isn't importing the full listings :
function price() {
var sh1=SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Feuille 4');
var requestOptions = {
method: 'GET',
uri: 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest',
qs: {
'start': '1',
'limit': '5000',
'convert': 'USD'},
'headers' : {'X-CMC_PRO_API_KEY': '**********'},
'json': true,
'gzip': true};
var url='https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?symbol=ETH';
var result = UrlFetchApp.fetch(url, requestOptions);
var txt= result.getContentText();
var d=JSON.parse(txt);
sh1.getRange(1, 2).setValue(d.data.ETH.quote.USD.price)
}
I know it has something to deal with: https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest but I couldn't figure it out by myself.
I am not familiar with this site but when I try the URL on its own it returns an error stating the API key is missing
{
"status": {
"timestamp": "2021-03-31T12:29:45.203Z",
"error_code": 1002,
"error_message": "API key missing.",
"elapsed": 0,
"credit_count": 0
}
}
Also, it looks like Yahoo Finance has crypto historical data for free, no API required, just make an appropriate web request. This one grabs BTC from March 31, 2020 thru March 31, 2021.
https://query1.finance.yahoo.com/v7/finance/download/BTC-USD?period1=1585662494&period2=1617198494&interval=1d&events=history&includeAdjustedClose=true
One would need to decipher the format for period1 and period2, I believe they are UNIX timestamps, I was able to confirm at this site:
https://www.unixtimestamp.com/
Then this code would download the data into the current sheet:
function importCSVFromWeb() {
// Provide the full URL of the CSV file.
var csvUrl = "function importCSVFromWeb() {
// Provide the full URL of the CSV file.
var csvUrl = "https://query1.finance.yahoo.com/v7/finance/download/BTC-USD?period1=1585662494&period2=1617198494&interval=1d&events=history&includeAdjustedClose=true";
var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
var csvData = Utilities.parseCsv(csvContent);
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
BTW, it looks like Yahoo Finance gets their crypto data from CoinMarketCap
I was mistaken two requests : /listings and /quotes
Listing gives you a list of multiple currencies.
Quotes gives you data from one coin only
Related
I want to use google script to make a request and save some data on google sheet.
The problem is when I try to pass some non integer values as parameters in the request.
I think it's something to do with the fact that sheets uses comma for separating decimal from integer while my program sends the numbers separated by a dot.
This is where I am now:
const doPost = (event) => {
console.log(`doPost`, JSON.stringify(event));
const { parameter } = event;
const { temp, peso } = parameter;
var date = new Date();
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow([date, parseFloat(temp), peso]);
}
When I make a post request with parameters: { temp:1.234, peso:1.234 } the result on google sheet is a big mess.
Does someone have any idea how to fix this?
edit:
function Test(){
var sheet = SpreadsheetApp.getActiveSheet();
var d = 1.23456;
var date = new Date();
sheet.appendRow([date, d]);
}
This works fine... don't know if it can help you debug.
Post Data to Sheet
I don't actually do this all that much so I am by no means an expert at it
function doPost(e) {
Logger.log(e.postData.contents);
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet1");
let data = JSON.parse(e.postData.contents);
sh.appendRow([data.first,data.second])
}
function sendData(obj) {
const url = ScriptApp.getService().getUrl();
const params={"payload":JSON.stringify(obj),"muteHttpExceptions":true,"method":"post","headers": {"Authorization": "Bearer " + ScriptApp.getOAuthToken()}};
UrlFetchApp.fetch(url,params);
}
function saveMyData() {
sendData({first:"1.234",second:"1.432"});
}
This worked for me.
Finally figured it out!
The problem was in the setting of the google sheet file.
I'm from Italy so it enters as defult the Italian format. For some reasons this mess up all the new entries. The solution is very simple: change the format to the english one and the problem should solve itself!
I'm using Companies House API with a small google apps script. I want to retrieve the company numbers for a list of companies on a sheet.
I can't seem to be able to access the key/values of the response, can anyone help?
function findPayeeCHInfo() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1")
var optionsheet = ss.getSheetByName('Options');
var payee = sheet.getRange("F6").getValue();
var my_api_key = optionsheet.getRange('C2').getValue();
//Logger.log(my_api_key);
var headers = {
"Authorization": "Basic " + Utilities.base64Encode(my_api_key+":"),
}
var params = {
"method":"GET",
"headers":headers,
muteHttpExceptions: true,
};
var url = "https://api.companieshouse.gov.uk/search/companies?q=" + payee;
var response = UrlFetchApp.fetch(url,params);
Logger.log(response);
}
my logger says:
[20-08-02 16:14:00:624 BST] Logging output too large. Truncating output. {"kind":"search#companies","total_results":4163,"items_per_page":20,"start_index":0,"page_number":1,"items":[{"description":"01026167 - Incorporated on 4 October 1971","snippet":"BARCLAYS BANK INTERNATIONAL ","address_snippet":"1 Churchill Place, London, E14 5HP","matches":{"title":[1,8,10,13],"snippet":[1,8,10,13]},"address":{"postal_code":"E14 5HP","address_line_1":"Churchill Place","premises":"1","address_line_2":"London"},"kind":"searchresults#company","description_identifier":["incorporated-on"],"title":"BARCLAYS BANK PLC","company_type":"plc","links":{"self":"/company/01026167"},"company_number":"01026167","company_status":"active","date_of_creation":"1971-10-04"},{"description_identifier":["incorporated-on"],"address":{"country":"England","locality":"London","premises":"1","postal_code":"E14 5HP","address_line_1":"Churchill Place"},"kind":"searchresults#company","snippet":"BARCLAYS UK AND EUROPE ","address_snippet":"1 Churchill Place, London, England, E14 5HP","matches":{"snippet":[1,8],"title":[1,8,10,13]},"description":"09740322 - Incorporated on 19 August 2015","company_number":"09740322","date_of_creation":"2015-08-19","company_status":"active","company_type":"plc","links":{"self":"/company/09740322"},"title":"BARCLAYS BANK UK PLC"},{"title":"ZEDRA TRUST
i've used different methods of addressing object values and they're either not recognised, return a null value or return everything that you see above.
I wasn't even sure it's an object, so tried addressing it as an array, with zero success. According to the documentation, this is a subset of "items", but when i try to log response.items.company_number i get
TypeError: Cannot read property 'company_number' of undefined –
The resource representation is here:
https://developer.companieshouse.gov.uk/api/docs/search-overview/CompanySearch-resource.html
any pointers will be gratefully received.
UrlFetchApp.fetch() returns HTTPResponse
Get the string from HTTPResponse and parse the string to a object
items in the response is a array of objects. Access the object inside using index of the array and then use company_name key
var httpResponse = UrlFetchApp.fetch(url,params);
var text = httpResponse.getContentText();
var object = JSON.parse(text);
var compName = object.items[0]['company_name'];
Logger.log(compName);
I have basically non-existent experience in Javascript, but know a little bit of Python so I figured I was up to the task of Frankensteining a couple of pre-made scripts together which I found online. The idea is to look through a list of data, then send PDFs of the appropriate spreadsheet to the desired e-mail address. I have copied my attempt below.
// This constant is written in for rows for which an email has been sent successfully.
var EMAIL_SENT = 'EMAIL_SENT';
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 16; // First row of data to process
var numRows = 1; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 6); // Fetch the range of cells
var data = dataRange.getValues(); // Fetch values for each row in the Range.
const token = ScriptApp.getOAuthToken();
const ss = SpreadsheetApp.getActiveSpreadsheet(); // Get the currently active spreadsheet URL (link)
const subject = 'Monthly Invoice'; // Subject of email message
const url = 'https://docs.google.com/spreadsheets/d/SS_ID/export?'.replace('SS_ID', ss.getId()); // Base URL
const exportOptions = // Specify PDF export parameters From: https://code.google.com/p/google-apps-script-issues/issues/detail?id=3579
'exportFormat=pdf&format=pdf' + // export as pdf / csv / xls / xlsx
'&size=A4' + // paper size legal / letter / A4
'&portrait=true' + // orientation, false for landscape
'&fitw=true&source=labnol' + // fit to page width, false for actual size
'&sheetnames=false&printtitle=false' + // hide optional headers and footers
'&pagenumbers=false&gridlines=false' + // hide page numbers and gridlines
'&fzr=false' + // do not repeat row headers (frozen rows) on each page
'&gid='; // the sheet's Id
const sheets = ss.getSheets();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[4];
var message = row[3];
var emailSent = row[5];
var client_id = row[0];
var client_sheet = ss.getSheetByName(client_id);
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates
const blobs = []; // make an empty array to hold your fetched blobs
// Convert individual worksheets to PDF
const response = UrlFetchApp.fetch(url + exportOptions + client_sheet, {
headers: {
Authorization: 'Bearer ${token}'
}
});
// convert the response to a blob and store in our array
blobs[i] = response.getBlob().setName('${client_sheet}.pdf');
// If allowed to send emails, send the email with the PDF attachment - 500 emails per day standard
if (MailApp.getRemainingDailyQuota() > 0)
GmailApp.sendEmail(emailAddress, subject, message, {
attachments: [blobs[i]]
});
sheet.getRange(startRow + i, 6).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
// create new blob that is a zip file containing our blob array
// const zipBlob = Utilities.zip(blobs).setName(`${ss.getName()}.zip`);
// optional: save the file to the root folder of Google Drive
// DriveApp.createFile(zipBlob);
}
I'm currently running into this error, however - and honestly I'm lost.
Request failed for https://docs.google.com returned code 401
Request failed for https://docs.google.com returned code 401. Truncated server response: <HTML> <HEAD> <TITLE>Unauthorized</TITLE> </HEAD> <BODY BGCOLOR="#FFFFFF" TEXT="#000000"> <H1>Unauthorized</H1> <H2>Error 401</H2> </BODY> </HTML> (use muteHttpExceptions option to examine full response) (line 39, file "send_emails")
If it helps, line 39 is:
const response = UrlFetchApp.fetch(url + exportOptions + client_sheet, {
Could somebody please assist? Thank you.
If you are using the script in your question, how about this answer? Please think of this as just one of several answers.
Modification point:
Unfortunately, in the current stage, the template literal, which was added at ES2015, cannot be used with Google Apps Script. I thought that the reason of your issue might be this.
Modified script:
Please modify your script as follows.
From:
Authorization: 'Bearer ${token}'
To:
Authorization: 'Bearer ' + token
And
From:
blobs[i] = response.getBlob().setName('${client_sheet}.pdf');
To:
blobs[i] = response.getBlob().setName(client_sheet + '.pdf');
References:
Basic JavaScript features
Template literals
If I misunderstood your question and this was not the result you want, I apologize.
Added:
I noticed one more modification point. Please modify your script as follows.
From:
var client_sheet = ss.getSheetByName(client_id);
To:
var client_sheet = ss.getSheetByName(client_id).getSheetId();
In order to retrieve gid, please use getSheetId().
Updated: December 19, 2020:
Now, Google Apps Script can use V8 runtime. Ref So the template literals can be used. But there is an important point. In this case, please use the backtick (grave accent) as follows.
Authorization: `Bearer ${token}`
and
blobs[i] = response.getBlob().setName(`${client_sheet}.pdf`);
I am beginner to google apps script. I am trying to import CSV file from Zipped attachement from gmail. I am getting error Could not Parse tex at Line of code
var csvData = Utilities.parseCsv(unZipBlob.getDataAsString(), "\t");"
I have tried all combinations Like UTF -8 and other unicode to solve the issue but unable resolve it. even i tried the answer mentioned at Link
Utilities.parseCsv() 'Could not parse text' (Google Apps Script)
Below I have attached my code . can some one please help me to resolve?
Please let me know if you need further details to help
function importCSVFromGmailMC1() {
var threads = GmailApp.search('GOC "CM pacing Report" - 1*');
var message = threads[0].getMessages()[0];
var attachment = message.getAttachments()[0].copyBlob();
attachment.setContentType('application/zip');
var unZipBlob = Utilities.unzip(attachment)[0];
unZipBlob.setContentType('text/csv');
var sheet = SpreadsheetApp.openById('mysheetid').getShee tByName('CM pacing_daily');
if (unZipBlob.getContentType() === "text/csv") {
var csvData = Utilities.parseCsv(unZipBlob.getDataAsString(),"\t");
sheet.clearContents().clearFormats();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
}
I am adding\inserting a Line chart to Excel via the following JS call:
var newSheet = ctx.workbook.worksheets.add();
newSheet.activate();
// populate grid
// category (axis)
var cell = newSheet.getCell(0, 0)
...
// values (axis)
cell = newSheet.getCell(0, 1)
...
var range = newSheet.getUsedRange();
newSheet.charts.add("Line", range);
My "range" data looks like this:
2012 10
2013 20
2014 30
2015 40
2016 50
The issue I'm having is each column is treated as an individual series, and 2 lines are rendered in the chart. I only want one line and the Category Axis to contain the years. Does anyone know if this is possible?
Screenshot:
Chris,
The current JavaScript API for Excel that you use to create the chart doesn't give you much control of how Excel should construct the series and axis for the chart. When using the ChartCollection.add() method, you are depending on the "smarts" of the Excel Recommended Charts algorithm, and in this particular case the, answer it comes up with as the first answer is not what you expect.
We have an item in our API backlog to provide more fine-grained control for charts similar to what is available in other Excel APIs. At this time I can't say when this will be available in the API. I encourage you to follow our open specification process to get a heads up, and an opportunity to give feedback on our designs.
As a workaround for your particular case, I would suggest that you try using date values for the first column instead of numbers. You can format the column to show only the year part of the dates:
async function run() {
try {
await Excel.run(async (context) => {
var sheet = context.workbook.worksheets.getActiveWorksheet();
let data = [
["Year", "Measure"],
["2010-12-31", 10],
["2011-12-31", 20],
["2012-12-31", 30],
["2013-12-31", 40],
["2014-12-31", 50],
];
let format = [
["#"],
["yyyy"],
["yyyy"],
["yyyy"],
["yyyy"],
["yyyy"]
];
let categories = sheet.getRange("A1:A6");
categories.numberFormat = format;
var range = sheet.getRange("A1:B6");
range.values = data;
sheet.charts.add(Excel.ChartType.line, range, Excel.ChartSeriesBy.columns);
await context.sync();
});
}
catch (error) {
OfficeHelpers.Utilities.log(error);
}
}
This snippet is written in TypeScript using async/await, but easily be translated to JavaScript.
Jakob