importing JSON to google sheets gives getRrange-error - javascript

I'm having troubles importing json data to google spreadsheets using google script. I have no java knowledge so sorry if the question is a bit stupid!
I do code a bit of VBA so I'm not completely unaccustomed to code.
I'm trying to pull the live exchange-rate from a cryptocurrency-exchange's API. I managed to get it to work with a different exchange's API, but here the json looks slightly different.
The JSON I can't get into google spreadsheets looks like this;
{"success":true,"message":"","result":{"Bid":0.00011437,"Ask":0.00011447,"Last":0.00011447}}
I have checked json on https://jsonlint.com/ and it checks out ok.
The code I use is this;
1 function pullJSON_XRP() {
2 var ss = SpreadsheetApp.getActiveSpreadsheet();
3 var sheets = ss.getSheets();
4 var sheet = ss.getActiveSheet();
5 Logger.log(sheets)
6 var url="https://bittrex.com/api/v1.1/public/getticker?market=BTC-XRP"; // JSON call URL
7
8 var response = UrlFetchApp.fetch(url);
9 var dataAll = JSON.parse(response.getContentText());
10 var dataSet = dataAll;
11 Logger.log(dataSet)
12 var rows = [],
13 data;
14 Logger.log(rows)
15
16 for (i = 0; i < dataSet.rows; i++) {
17 data = dataSet[i];
18 rows.push(data.result.Bid, data.result.Ask, data.result.Last); //JSON entities
19 }
20
21 dataRange = sheet.getRange(3, 1, rows.length, 3); // 4th Denotes total number of entites
22 dataRange.setValues(rows);
23 }
I get an error on row 21. The error message is in Swedish and remains in Swedish even though I changed my language on google but it reads something like: "Range coordinates or size invalid. At first at thought this was because dataRange = sheet.getRange(3, 1, rows.length, 3); mismatched the array for some reason. I have spent hours searching and testing but to no avail. I now suspect that my parsed json isn't being addressed correctly in rows.push(data.result.Bid, data.result.Ask, data.result.Last);
I have tried just using the ids data.Bid, data.Ask, data.Last but I still get the same error.
Any help would be so appreciated! =)
Thank you for taking the time!
Humbly,
Brian

This is a simple way:
function pullJSON_XRP() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sheet = ss.getActiveSheet();
var url="https://bittrex.com/api/v1.1/public/getticker?market=BTC-XRP"; // JSON call URL
var response = UrlFetchApp.fetch(url);
var dataAll = JSON.parse(response.getContentText());
var values=[[ dataAll.result.Bid,dataAll.result.Ask,dataAll.result.Last]]
sheet.getRange("A3:C3").setValues(values)
}

Related

Google Sheets - Sending Row to Another Spreadsheet

Written a Google Sheet where when a button is pressed a collated row of data is sent to a different Google Sheet. It was launched six months ago among colleagues that have full permissions to both sheets. The reason for this post was that 1 in 10 submissions goes missing and never arrives to be added to the secondary Google Sheet. Thus wondering if anyone had any ideas as to if there was an issue with my code.
sh.getRange("j7").setValue('=now()');
var range = sh.getRange('J7:R7'); //Fixed range of where the row/data is collated
var data = range.getValues();
var tss = SpreadsheetApp.openById('SHEET ID');
var ts = tss.getSheetByName('Main');
ts.getRange(ts.getLastRow()+1,1,1,9).setValues(data);
Many thanks for any ideas...
Try this:
function lfunko() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Enter Your Sheet Name");
sh.getRange("J7").setFormula('=now()');
var range = sh.getRange('J7:R7');
var data = range.getValues();
var tss = SpreadsheetApp.openById('SHEET ID');
var ts = tss.getSheetByName('Main');
ts.getRange(ts.getLastRow() + 1, 1, data.length, data[0].length).setValues(data);
}

Google Script for sending mass emails from Sheets stopped working. I didn't change the code

I have found a script that worked for sending batch emails straight from Google Sheets. I used it occasionally and it worked great. And then it just stopped working. When I run the code below, I see the message "Execution completed", but the emails don't arrive.
I can read basic code and that's about the extent of my knowledge. That is to say, that the only things I change in what you see below are the subject of the email, the number of rows to process and the parameters in getRange.
I've tried to use the script on diffrent sheets, from different Google Accounts. No luck.
I would be greatful for your help.
Edit 1: I copied the code, made a new file and ran it there. It only sent an email to the address in row 4, even though the range was set to be from row 1 to 5. I am very confused now.
//Прежде чем запускать, убедись, что ты сидишь с того аккаунта, с которого должны улететь письма!!!
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 1; // First row of data to process
var numRows = 5; // Number of rows to process
// Fetch the range of cells A1:B5
var dataRange = sheet.getRange(startRow, 1, numRows, 5);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = "Script Test 18/02";
MailApp.sendEmail( emailAddress, subject, message);
}
}

Google Apps Script - Run Same Code on Dynamically Changing Tab Numbers

I would like the below code to run on how ever many tabs get created - after Sheet 7 (First 7 tabs always remain unchanged). Currently I use an array and must number them which works if you know exactly how many tabs get created - which I dont always know. So I currently create script for [7] then [8] etc etc. this does return an error when I say have [20] but Tab 20 doesnt exist.
function Company_ONE() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[7]; //SHEET 8
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheets()[7];
var lr = sheet.getLastRow();
var cell = SpreadsheetApp.getActive().getRange('AK3');
var criteria = SpreadsheetApp.DataValidationCriteria.CHECKBOX;
var rule = SpreadsheetApp.newDataValidation()
.requireCheckbox()
.build();
cell.setDataValidation(rule);
sheet.getRange('AK3').activate();
var destinationRange = sheet.getActiveRange().offset(0, 0, lr-3);
sheet.getRange('AK3').copyTo(destinationRange);
}
Explanation:
Use getSheet().slice(7) to get from 8th sheet onwards. See here how slice works.
Then you can use forEach() to iterate through every sheet (after sheet 7th).
I also removed some unnecessary lines of codes. For example, you use SpreadsheetApp.getActive() multiple times in the sheet or you define the same variables twice like ss or sheet.
Since you are interacting with the sheets iteratively you might need to use SpreadsheetApp.flush() to make sure all the pending changes are completed.
Solution:
function Company_ONE() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets().slice(7); // get 8th sheet onwards
sheets.forEach(sheet=>{
var lr = sheet.getLastRow();
var cell = ss.getRange('AK3');
var criteria = SpreadsheetApp.DataValidationCriteria.CHECKBOX;
var rule = SpreadsheetApp.newDataValidation()
.requireCheckbox()
.build();
cell.setDataValidation(rule);
sheet.getRange('AK3').activate();
var destinationRange = sheet.getActiveRange().offset(0, 0, lr-3);
sheet.getRange('AK3').copyTo(destinationRange);
SpreadsheetApp.flush();
});
}

How to get formatted array on Google AppScript?

I have a code that takes each cell from a gsheet and changes the format using appscript but this does not correct it back on the google sheet. I used this because even though the format was correct on the gsheet, when getvalue() is used, the number loses its format.
var Qty1 = ss.getRange(i, 15).getValue();
var Qty1Format = Qty1.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
//Output has a thousands separator and two decimal places.
This takes a lot of time to run and as a result I am looking for alternative ways to correct the format.
I was thinking of getting all the values of the column as an array and I am looking to convert the array in the format needed and paste this back into the sheet.
I've had attempts at coding this but would be grateful for any help on how to change format for the array or alternative ways of achieving the outcome.
Sample code attempt:
function copypastetest() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").activate();
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var rng = ss.getRange("C2:"+"c"+lr).getValues();
var frng = rng.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
var copy = ss.getRange("C2:"+"c"+lr).setValues(frng)
}
Further Edit:
#Cooper's answer is spot on. However I'm might not have asked the right question to solve my problem. I am ultimately looking to take values from the google sheet and replace placeholders into a google doc.
See below (although the number is formatted it still appears to be unformatted in the formula bar - and I should have noticed this before but i did not)
So how I can format the array (or get an array that is formatted in the first place to come on my Logger.log on the appscript?
Here is the rest of the script for you to understand what I am looking to achieve,
function generatetest() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").activate();
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr = ss.getLastRow();
var rng = ss.getRange("A1:"+"F"+lr).getValues();
for (var i =2;i<=lr;i++){
if(ss.getRange(i, 1).getValue()){
var client = rng[i-1][1];
var email = rng[i-1][2];
var documentId = DriveApp.getFileById('1j36HPQkTPc0R4GCtA0XKcmeHUVPsgBKoyNIl93HFhp0').makeCopy().getId();
DriveApp.getFileById(documentId).setName(client);
var body = DocumentApp.openById(documentId).getBody();
body.replaceText('{Name}', client).replaceText('{Email}', email)
}
else {}
}
}
If I understood your issue correctly, I believe it can be solved by using the getDisplayValues() method of class Range. This method copies the format of the cell and returns the formatted string.
var rng = ss.getRange("C2:"+"c"+lr).getDisplayValues()
References:
Range.getDisplayValues()
I tried this and it seems to work, if I understand your issue.
function runOne() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet22');
const rg=sh.getRange(1,1,sh.getLastRow());
const vA=rg.getValues();
vA.forEach(function(r,i){
sh.getRange(i+1,2).setValue(r[0]).setNumberFormat('#,##0.00');
})
}
Here's my start data:
1000000.33
2000000.34
3000000.35
4000000.36
5000000.37
6000000.38
7000000.39
8000000.4
9000000.41
10000000.42
11000000.43
12000000.44
13000000.45
14000000.46
15000000.47
16000000.48
17000000.49
18000000.5
And here's my ending data:
1000000.33,1000000.33
2000000.34,2000000.34
3000000.35,3000000.35
4000000.36,4000000.36
5000000.37,5000000.37
6000000.38,6000000.38
7000000.39,7000000.39
8000000.4,8000000.4
9000000.41,9000000.41
10000000.42,10000000.42
11000000.43,11000000.43
12000000.44,12000000.44
13000000.45,13000000.45
14000000.46,14000000.46
15000000.47,15000000.47
16000000.48,16000000.48
17000000.49,17000000.49
18000000.5,18000000.5
Here's what the sheet looks like:
I use this script a lot for viewing and editing number formats on a spreadsheet and I find it helpful to solve formatting issues. There's probably an easier way but I haven't found it yet.
function getandSetActiveRangeFormats() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getActiveRange();
var fA=rg.getNumberFormats();
var html='<style>th,td{border:1px solid black;}</style><table><tr><th>Item</th><th>A1 Notation</th><th>Number Format</th><th>Enter Format</th><th>Set Format</th></tr>';
var item=1;
var row=rg.getRow();
var col=rg.getColumn();
fA.forEach(function(r,i){
r.forEach(function(c,j){
var txt=Utilities.formatString('<input type="text" id="RC-%s-%s" />',row+i,col+j);
var btn=Utilities.formatString('<input type="button" value="Set Form" onClick="setFormat(%s,%s);" />',row+i,col+j);
html+=Utilities.formatString('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>',item++,sh.getRange(row + i,col + j).getA1Notation(),fA[i][j],txt,btn);
});
});
html+='</table><input type="button" value="Exit" onClick="google.script.host.close();" />';
html+='<script>function setFormat(row,col){var f=document.getElementById("RC-"+row+"-"+col).value;google.script.run.setFormat(row,col,f);}</script>';
var ui=HtmlService.createHtmlOutput(Utilities.formatString(html));
SpreadsheetApp.getUi().showModelessDialog(ui, "Display and Set Active Range Formats")
}
function setFormat(row,col,format) {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
sh.getRange(row,col).setNumberFormat(format);
}

JSON.parse doesn't work with url links

I'm a junior javascript/google-apps-script developer and I wanted to add some functionality to some of my worksheets at Google Sheets. I'm working with many URLs and need to track what time they were last modified by the author.
I've built some script which I thought will work but apparently (after some reading) needs some professional touch.
The idea is to iterate through a column of URLs (2500~) and output each URL's modified date (from its meta-data) into a cell from the right. Here is my code:
function iteration1() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
**//The list to iterate on.**
var sheet = ss.getSheetByName("Fund List");
**//The column of which the links are stored**
var urls = sheet.getRange("D2:D150").getValues();
for (var row = 0; row < urls.length; row++) {
for (var col = 0; col < urls[row].length; col++)
**//Varifying if there is a URL within the cell**
if (urls[row][col] != '') {
**//Storing each URL in a new array**
var url = UrlFetchApp.fetch(urls[row][col].valueOf());
**//Parsing the meta-data of the URL into an array**
var tweets = JSON.parse(url);
**//Retrieve the link modification date from the meta-data array & outputs to the cell from the right respectivley.**
sheet.getRange(row+2, 13).setValue(Logger.log(tweets[4][2]).getLog());
}
}
}
For Example: the link http://documents.financialexpress.net/Literature/37773008.pdf
Its meta-data is:
{Accept-Ranges=bytes, X-Robots-Tag=noindex, nofollow, noarchive,nosnippet, Cache-Control=max-age=604800, Server=Microsoft-IIS/7.0, ETag="01827159b1d11:0", Access-Control-Allow-Origin=*, Access-Control-Allow-Methods=GET,PUT,POST,DELETE,OPTIONS, Last-Modified=Wed, 18 May 2016 23:00:00 GMT, Content-Length=113029, Access-Control-Allow-Headers=Content-Type, Date=Thu, 01 Sep 2016 11:43:52 GMT, Content-Type=application/pdf}
I only need the Last-Modified field Date within this meta-data array and output it to the cell from the right.
Thanks in advance for the helpers! great community here!
I have added a screenshot of my current code and the debugger mode which gives an example of the links I'm working on:
From what I see from the google documentation ( https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetch(String) ) the result you are storing in the variable url isn't a string.
JSON.parse accept a string and transform it into a javascript Object/Array/String/whatever
You need to use instead of JSON.parse(url), JSON.parse(url.getContentText('utf-8')) as documented here : https://developers.google.com/apps-script/reference/url-fetch/http-response
After few days working on it, I have managed to retrieve the value for the Last-Modified date key per each URL within my sheet.
My code:
function iteration1() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
//The Google sheet to access
var sheet = ss.getSheetByName("Sheet Name");
//The array of URLs to check
var urls = sheet.getRange("D2:D150").getDisplayValues();
for (var row = 0; row < urls.length; row++) {
for (var col = 0; col < urls[row].length; col++) {
if (urls[row][col].toString() != '') {
//Converting each URL to string and retrieving its Properties into a new Array
var url = UrlFetchApp.fetch(urls[row][col].toString());
var tweets = url.getAllHeaders();
//Forming an array of Properties by Keys & Values
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperties(tweets);
var tweetsKeys = Object.keys(tweets);
}
}
//Retrieving the link modification date from the property meta-data & outputs it as a String to the cell from the right respectivley.
sheet.getRange(row+2, 12).setValue(userProperties.getProperty(tweetsKeys[7]));
}
}
Thank you very much for your responses!

Categories