I am using this function to pull information from coinmarketcap using their v2 api. The problem I am getting is that if a "website_slug" does not exist on coinmarketcap, I get an incorrect range width error instead of the function just putting xxx in the cell. This can be recreated by having a cell in column B that doesn't match a website_slug on cmc (https://api.coinmarketcap.com/v2/ticker/).
function getMarketCap(sheetname) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sheetname);
var assets = [];
var idRange = sheet.getRange("B1:B");
var lastRow = getLastRowOfRange(idRange);
var cellRange = sheet.getRange(1, 2, lastRow).getValues();
var mcRange = sheet.getRange(1, 3, lastRow);
var mcValues = [];
for (var i = 0; i < cellRange.length; i++) {
assets[i] = cellRange[i];
}
var req = [];
for (var i = 0; i < 16; i++) {
req.push({
muteHttpExceptions: true,
method: "get",
url: "https://api.coinmarketcap.com/v2/ticker/?start=" + (i * 100 + 1),
});
}
var responses = UrlFetchApp.fetchAll(req);
var res = responses.filter(function(e){return e.getResponseCode() == 200}).map(function(e){return JSON.parse(e.getContentText())});
if (responses.length != res.length) Logger.log("%s errors occurred.", responses.length - res.length);
var mcValues = [];
assets.forEach(function(e, h) {
mcValues[h] = []
res.some(function(f) {
Object.keys(f.data).some(function(g) {
if (f.data[g].website_slug == e[0]) {
mcValues[h][0] = f.data[g].quotes.USD.market_cap;
return true;
}
});
if (mcValues[h][0]) return true;
});
if (!mcValues[h][0]) mcValues[h][0] = 'xxx';
});
mcRange.setValues(mcValues);
}
Related
I am learning Javascript and this is my first time working with Google Sheets Apps Script. What I am doing is taking a large JSON file and importing it into my sheet. After that I am populating a few hundred properties based on the key:value found in the JSON.
This is how it kinda works right now:
Go to first column and first row of my sheet.
Get the name (property name).
Search the JSON for the key and then grab the value.
Update a neighbor cell with the value found in the JSON.
Right now it all works the only issue is it seems to be pretty slow. It takes about .5-1 second per lookup and when I have 200+ properties it just seems slow. This might just be a limitation or it might be my logic.
My sheet can be found here: https://docs.google.com/spreadsheets/d/1tt3eh1RjL_CbUIaPzj10DbocgyDC0iNRIba2B4YTGgg/edit#gid=0
My function that does everything:
function parse() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange(2,1);
var range1 = sheet.getRange("A2");
var cell = range.getCell(1, 1);
var event_line = cell.getValue();
var tmp = event_line.split(". ");
var col_number = tmp[0];
var event_name = tmp[1];
event_json = get_json_from_cell(col_number);
const obj = JSON.parse(event_json);
var traits = obj.context.traits;
var properties = obj.properties;
//Get the range for the section where properties are
var traits_range = sheet.getRange("contextTraits");
var allprop = sheet.getRange("testAll");
var alllen = allprop.getNumRows();
var length = traits_range.getNumRows();
for (var i = 1; i < length; i++) {
var cell = traits_range.getCell(i, 1);
var req = traits_range.getCell(i, 4).getValue();
var trait = cell.getValue();
var result = traits[trait];
var result_cell = traits_range.getCell(i, 3);
if (result == undefined) {
if (req == "y"){
result = "MISSING REQ";
result_cell.setBackground("red");
} else {
result = "MISSING";
result_cell.setBackground("green");
}
} else {
result_cell.setBackground("blue");
}
result_cell.setValue(result);
Logger.log(result);
}
for (var i = 1; i < alllen; i++) {
var cell = allprop.getCell(i,1);
var req = allprop.getCell(i, 4).getValue();
var prop = cell.getValue();
var result = properties[prop];
var result_cell = allprop.getCell(i, 3);
if (result == undefined) {
if (req == "y"){
result = "MISSING REQ";
result_cell.setBackground("red");
} else {
result = "MISSING";
result_cell.setBackground("green");
}
} else {
result_cell.setBackground("blue");
}
result_cell.setValue(result);
}
Logger.log(result);
}
I am trying to make a script to automate deleting duplicate data based on column A. This is the current script I am using and it works.
// This scripts works but deleting new data instead of old data
function removeDuplicates() {
var sheetName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName(sheetName);
var vA = sh.getDataRange().getValues();
var hA = vA[0];
var hObj = {};
hA.forEach(function(e, i) {
hObj[e] = i;
});
var uA = [];
var d = 0;
for (var i = 0; i <= vA.length; i++) {
if (uA.indexOf(vA[i][hObj['key']]) == -1) {
uA.push(vA[i][hObj['key']]);
} else {
//sh.deleteRow(i + 1 - d++);
sh.deleteRow((parseInt(i)+1) - d);
d++;
}
}
};
But this one is deleting the newly added row, what I want to achieve is it should delete the old duplicate row instead. How can I do that?
In else part instead of using i which represent your current row, use the indexOf the row you want to delete. Delete it first and then push the new one into array
// This scripts works but deleting new data instead of old data
function removeDuplicates() {
var sheetName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName(sheetName);
var vA = sh.getDataRange().getValues();
var hA = vA[0];
var hObj = {};
hA.forEach(function(e, i) {
hObj[e] = i;
});
var uA = [];
var d = 0;
for (var i = 0; i <= vA.length; i++) {
if (uA.indexOf(vA[i][hObj['key']]) == -1) {
uA.push(vA[i][hObj['key']]);
} else {
//sh.deleteRow(i + 1 - d++);
let j = uA.indexOf(vA[i][hObj['key']]);
sh.deleteRow((parseInt(j)+1) - d);
d++;
uA.push(vA[i][hObj['key']]);
}
}
};
About extracting G-mails to a Google spreadsheet, how can I do to include an IF for dismissing specific e-mails by subject? For example: e-mails responses (with "RE:" in subject). I don't want these e-mails in my spreadsheet.
I've tried with a LOOP but it didn't work because LOOP keeps sending all e-mails to my spreadsheet without a previous selection.
Here's the code:
function GetEmails() {
var label = GmailApp.getUserLabelByName("MY LABEL");
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
var message = messages[j];
var from = message.getFrom()
var to = message.getTo();
var subject = message.getSubject();
var RE = subject.startsWith("RE:")
if ([RE != "RE:") {
process1(message);
} else {
process2(message)
}
}
}
function process1(message) {
var body = message.getPlainBody();
var subject = message.getSubject();
var date = message.getDate();
var from = message.getFrom();
var url = "GOOGLE SPREADSHEET"
var ss = SpreadsheetApp.openByUrl(url)
var sheet = ss.getActiveSheet();
sheet.appendRow([date, from, subject, body]);
}
function process2(message) {
var body = message.getPlainBody();
var subject = message.getSubject();
var date = message.getDate();
var from = message.getFrom();
var url = "GOOGLE SPREADSHEET"
var ss = SpreadsheetApp.openByUrl(url)
var sheet = ss.getActiveSheet();
sheet.appendRow([date, from, subject, body]);
}
}
RE is a boolean in your script.
Also DRY (Don't Repeat Yourself)
You likely meant to do
const url = "GOOGLE SPREADSHEET";
const ss = SpreadsheetApp.openByUrl(url);
const sheet = ss.getActiveSheet();
function process(message) {
var subject = message.getSubject();
if (subject.toUpperCase().startsWith("RE:")) {
return; // ignore RE
}
var body = message.getPlainBody();
var date = message.getDate();
var from = message.getFrom();
sheet.appendRow([date, from, subject, body]);
}
function GetEmails() {
var label = GmailApp.getUserLabelByName("MY LABEL");
var threads = label.getThreads();
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
process(messages[j]);
}
}
}
I wrote the code that gets data from a device.
The form of the data is csv. Below is the data value.
1,1.635946,1.636609,1.640240,1.636091
2,1.642825,1.640267,1.639013,1.636568
3,1.636835,1.636022,1.637664,1.637144
4,1.641332,1.641166,1.637950,1.640760
5,1.636041,1.637437,1.640702,1.633678
But I want the data in json format. So I tried using an online converter and got the following values:
[
{
"1": 2,
"1.635946": 1.642825,
"1.636609": 1.640267,
"1.640240": 1.639013,
"1.636091": 1.636568
},
{
"1": 3,
"1.635946": 1.636835,
"1.636609": 1.636022,
"1.640240": 1.637664,
"1.636091": 1.637144
}
]
What parts of my code should I modify if I want to get these values?
Below is my code.
var Timer;
var i = 0 ;
setTimeout(function(){
Timer = setInterval(function(){
port.write(meascommand+'\n');
i++;
if(i==5){
clearInterval(Timer);
}
},5000);
},1000);
port.on('data',function(devicevalue){
arrayvalue = devicevalue.toString();
eachvalue = arrayvalue.split(';');
var results = [];
var index = i ;
var ch0value = eachvalue[0] ;
var ch1value = eachvalue[1] ;
var ch2value = eachvalue[2] ;
var ch3value = eachvalue[3] ;
results[0] = index ;
results[1] = ch0value ;
results[2] = ch1value ;
results[3] = ch2value ;
results[4] = ch3value ;
console.log(results);
fs.appendFile(file,results+'\r\n',function(err){
if(err)
console.log(err);
});
});
};
function processFiles(files) {
var file = files[0];
var reader = new FileReader();
reader.onload = function (e) {
var output = document.getElementById("fileOutput");
var texto = e.target.result;
csvJSON(texto);
};
reader.readAsText(file);
}
function csvJSON(csv) {
var lines = csv.split("\n");
var result = [];
var headers;
for (var i = 0; i < lines.length; i++) {
headers = lines[i].split("\n");
}
var cont = 0;
for (var i = 0; i < lines.length; i++) {
var obj = {};
var currentline = lines[i].split("\n");
for (var j = 0; j < headers.length; j++) {
obj[cont] = currentline[j];
}
cont++;
result.push(obj);
}
return JSON.stringify(result); //JSON
}
Try to use below code. Credits go to: https://gist.github.com/iwek/7154578
NOTE: split(","). If lines contains , snippet won't work. But thats not the case in your data, as far as I can see.
function csvJSON(csv){
var lines=csv.split("\n");
var result = [];
var headers=lines[0].split(",");
for(var i=1;i<lines.length;i++){
var obj = {};
var currentline=lines[i].split(",");
for(var j=0;j<headers.length;j++){
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
//return result; //JavaScript object
return JSON.stringify(result); //JSON
}
I am using this code but I can't see anything in the logger. I can just see a message "Preparing for execution"
function testfunc() {
var s = SpreadsheetApp.getActiveSpreadsheet()
var sheet = s.getSheetByName("data")
var lastRow = sheet.getLastRow() - 1
var data = sheet.getRange(2,2,lastRow,5).getValues()
var fms = s.getSheetByName("FMS")
for (var i = 0;i < data.length; ++i){
var row = data[i]
var a = row[0]
var b = row[1]
var c = row[2]
var d = row[3]
var e = row[4]
Logger.log(i)
if (i = 1) {
Logger.log(i)
}
}
}
Where did I go wrong?
EDIT: As pointed out by #FedericoklezCulloca, I was missing an equal to sign in my if statement. The code should be :
function testfunc() {
var s = SpreadsheetApp.getActiveSpreadsheet()
var sheet = s.getSheetByName("data")
var lastRow = sheet.getLastRow() - 1
var data = sheet.getRange(2,2,lastRow,5).getValues()
var fms = s.getSheetByName("FMS")
for (var i = 0;i < data.length; ++i){
var row = data[i]
var a = row[0]
var b = row[1]
var c = row[2]
var d = row[3]
var e = row[4]
Logger.log(i)
if (i == 1) {
Logger.log(i)
}
}
}