how can I loop through a unciode json string in javascript? - javascript

I get the following string returned by the CBOE options api:
{u'inputs': {u'stock_price_max': 50.0, u'high_low_stock_max': None, u'time_frame': u'middle', u'hv30_max': None, u'high_low_stock_min': None, u'symbols': None, u'hv30_min': None, u'low_strike': 3.0, u'high_strike': 4.0, u'industry_codes': None, u'spread_ask_price_max': None, u'stock_price_min': 10.0}, u'output': [{u'stock_price': 43.2, u'stock_hi_lo_percent': 72.9651, u'symbol': u'EWZ', u'industry_code': 55501010, u'max_gain': 0.52, u'high_strike_otm_percent': 0.463, u'low_strike_otm_percent': 2.7778, u'spread_ask': 0.48, u'spread': u'43/42 Put', u'expiry': u'2019-04-18', u'max_gain_to_spread_ask_percent': 108.3333, u'hv30': 27.3836}, {u'stock_price': 41.37, u'stock_hi_lo_percent': 21.7957, u'symbol': u'FXI', u'industry_code': 55501010, u'max_gain': 0.26, u'high_strike_otm_percent': 0.8944, u'low_strike_otm_percent': 2.103, u'spread_ask': 0.24, u'spread': u'41/40.5 Put', u'expiry': u'2019-05-17', u'max_gain_to_spread_ask_percent': 108.3333, u'hv30': 20.2925}
I want to loop through it and place elements into cells in a Google spreadsheet. I have this code:
function myFunction() {
var response = UrlFetchApp.fetch(endpoint);
var data = response.getContentText();
sheet.getRange("A8").setValue(data);
}
This puts the entire string into cell A8.
I have tried to loop through the string with
for (i = 0; i < jsonlen; i++) {
sheet.getRange("A:A").setValaue(data['output']['symbol']);
}
This returns "undefined". So problems are:
1) how can I extract the elements I need form the "output" part of the string
2) put the symbols into A3, A4 etc then stock_price into B3, B4 etc
3) how to identify the length of the string in order to make the loop work correctly
until the string has been entirely looped over?
Many thanks!

You want to retrieve the values of symbol and stock_price the property of output and want to put them to the columns "A" and "B" of the active Spreadsheet, respectively.
You want to put the values from the row 3.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification points:
the property of output has an array. And symbol and stock_price are in the array.
So at first, it is required to prepare the values for putting to Spreadsheet.
Modified script:
function myFunction() {
var response = UrlFetchApp.fetch(endpoint);
var data = JSON.parse(response.getContentText());
var values = data.output.map(function(e) {return [e.symbol, e.stock_price]});
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(3, 1, values.length, values[0].length).setValues(values);
}
In this case, the values are put to the row 3 of column "A" and "B" on the active sheet.
Note:
In your case, if data is actually the string value of {u'inputs': {###}, u'outputs': [###]} which has the unicode literal of python 2, u is required to be replaced. So in this case, please put data = JSON.parse(data.replace(/u\'|\'/g, "\"").replace(/None/g, "null")); before var values = data.output.map(function(e) {return [e.symbol, e.stock_price]});. Please be careful this.
References:
map()
getRange(row, column, numRows, numColumns)
setValues(values)
If I misunderstood your question and this was not the result you want, I apologize.

Related

(JS) Google Script App Search / Filter for keyword

I have been stumped on this for a while. I am fairly new to Google script app and wanted to see if there is a way to make this happen. So far, I've used a few methods within Google Sheet but seem to not get it working.
The code below does give me an output of all the data, however, the data that is nested in the data.custom_fields[x] has multiple objects that is separated by ",". I would like to be able to filter out the other key words and just use whatever is inside "display_value=". The display_value= is not always in the same area so have to run a search for them.
I am assuming some kind of If statement would be used here..
An example of the object is:
{type=x, resource_subtype=x, created_by={name=x, gid=x, resource_type=x}, display_value=Cool Value, description=x, enabled=x, resource_type=custom_field, gid=x, enum_options=[x.lang.Object;x, enum_value={x}, name=x}
I've tried to split function as well but not sure how to filter out the words I need.
function Users() {
var options = {
"headers" : {
"Authorization": "API Key here"
}
}
var response = UrlFetchApp.fetch("URL here", options);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sheet = ss.getSheetByName("Tab Name here"); // specific sheet name getSheetByName(""); alternatively use ss.getActiveSheet()
var dataAll = JSON.parse(response.getContentText()); //
var dataSet = dataAll.data; // "data" is the key containing the relevant objects
var rows = [],
data;
for (i = 0; i < dataSet.length; i++) {
data = dataSet[i];
rows.push([
data.gid,
data.name,
data.permalink_url,
data.due_on,
data.custom_fields[1],
data.custom_fields[2],
data.custom_fields[4],
data.custom_fields[5],
data.custom_fields[6],
data.custom_fields[7],
data.custom_fields[8],
data.custom_fields[9],
]); //your JSON entities here
}
// [row to start on], [column to start on], [number of rows], [number of entities]
dataRange = sheet.getRange(2, 1, rows.length, 12);
dataRange.setValues(rows);
Thank you in advance!
Example Image of JSON imported data
Although they appear separated by ,'s, that is only how they're displayed in the log. Because you're using JSON.parse, you're receiving/converting to an Object, not a string.
Because data.custom_fields is an array of objects, you can access the property/key values as : data.custom_fields[x].display_value.
Learn More:
JSON.parse()
Accessing Object Properties
If you want to extract display_value, try
let myVal = myData.match(/(?<=display_value=)[^,]+/g)[0]
I guess that myData could be data.custom_fields[5], so replace it by
data.custom_fields[5].match(/(?<=display_value=)[^,]+/g)[0]

Multiple fields to a single row

Going to start with, I am extremely new to this. We are using a google sheet as different forms of sorts where we want to capture data in a single source. I am trying to avoid having to individually map each cell. below is the start of the 100 fields i'll have to capture. I am getting the error that my data of 3 doesn't match my columns of 10. Is there way to lay out different ranges and get them to all push to one row?
//Input Values
function SubmitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getActiveSheet();
var datasheet = ss.getSheetByName("Data");
var values = [[formS.getRange("B1:B4").getValues(),
formS.getRange("D2:D4").getValues(),
formS.getRange("F2").getValue()]];
datasheet.getRange(datasheet.getLastRow()+1, 1, 1,10).setValues(values)
I think that in your script, values for putting to Spreadsheet is required to be 2 dimensional array. But, formS.getRange("B1:B4").getValues() and formS.getRange("D2:D4").getValues() are 2 dimensional array and formS.getRange("F2").getValue() is not array. I think that this is the reason of your issue.
In order to put those values to one row of the sheet Data, how about the following modification?
Modified script:
From:
var values = [[formS.getRange("B1:B4").getValues(),
formS.getRange("D2:D4").getValues(),
formS.getRange("F2").getValue()]];
datasheet.getRange(datasheet.getLastRow()+1, 1, 1,10).setValues(values)
To:
var values = [[
...formS.getRange("B1:B4").getValues().flat(),
...formS.getRange("D2:D4").getValues().flat(),
formS.getRange("F2").getValue()
]];
datasheet.getRange(datasheet.getLastRow() + 1, 1, 1, values[0].length).setValues(values);
By this modification, values is like [ [ 'B1', 'B2', 'B3', 'B4', 'D2', 'D3', 'D4', 'F2' ] ]. Each value of the array is the a1Notation of the cell. And, this is put to the next row of the last row of sheet Data.
In this case, the length of values[0] is 8. It's not 10. So I used values[0].length.
References:
getValues()
setValues(values)
flat()
Spread syntax (...)

Cross reference names on spreadsheets to get specific data points (looping through an array)

I have two sheets. Test Data has 3-4k entries of many columns of data and Order Changes has no data at all. I would like to search two specific columns on Test Data, a column of names and a column of yes or no. If column two of Test Data contains a 'yes' in the cell then the name of that person would be placed into a cell on order changes.
This is what I have so far:
function isThreshold(){
var data = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Test Data");
var cdata = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Order Changes");
var lc = data.getLastColumn();
var lookUp = data.getRange(1,6,3,2).getValues();
lookUp.forEach(var info in lookUp){
}
Logger.log(lookUp);
}
I probably shouldn't loop through that many entries but I don't know of any other way. Should I combine the forEach loop with an if loop to get the desired result or use some other method?
I believe your goal as follows.
You want to retrieve the values from the cells "F1:G" of sheet "Test Data".
You want to search yes from the column "G" and when the column "G" is yes, you want to put the value of the column "F" to the sheet "Order Changes".
Modification points:
SpreadsheetApp.getActiveSpreadsheet() can be declared one time.
In this case, you can retrieve the values from the range of "F1:G" + data.getLastRow() of "Test Data", and create the array for putting to the sheet "Order Changes", and put it.
When above points are reflected to your script, it becomes as follows.
Modified script:
function isThreshold(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getSheetByName("Test Data");
var cdata = ss.getSheetByName("Order Changes");
var valuesOfTestData = data.getRange("F1:G" + data.getLastRow()).getValues();
var valuesForOrderChanges = valuesOfTestData.reduce((ar, [f, g]) => {
if (g.toLowerCase() == "yes") ar.push([f]);
return ar;
}, []);
if (valuesForOrderChanges.length > 0) {
cdata.getRange(1, 1, valuesForOrderChanges.length, valuesForOrderChanges[0].length).setValues(valuesForOrderChanges);
// or cdata.getRange(cdata.getLastRow() + 1, 1, valuesForOrderChanges.length, valuesForOrderChanges[0].length).setValues(valuesForOrderChanges);
}
}
In this modified script, from your question, it supposes that the columns "F" and "G" are the value of name and yes or no.
References:
getRange(a1Notation) of Class Sheet
reduce()

node red array / how to "use" specific place

in node red i collect values with "Collector" the collector sends me an "Object" with all pairs of values when one of them is updated:
{ "mqtt/1/": "-127.00", "mqtt/0/": "41.94" }
with "json" and after with "stringsplit" i got an array of f.e. 9 values:
array [9] (can be up to 80 pairs of values)!
[ "{", "mqtt/1/", ":", "-127.00", ",", "mqtt/0/", ":", "41.61", "}" ]
now i want to have a function node which compares the Value (-127.00) from the Topic (mqtt/1/) with the Value (41.61) from the Topic (mqtt/0/).
this i working ...BUT only if i know which is the first topic/value and which is the second...
var outputMsgs = msg.payload;
var top1=outputMsgs[1];
var val1=outputMsgs[3];
var top2=outputMsgs[5];
var val2=outputMsgs[7];
msg = {payload: val1}
var msg2 = {payload: val2}
if (val1>val2)
{var msgOUT={payload: "BIGGER"};}
return [msg, msg2, msgOUT];
But the Problem is, that sometimes "mqtt/1/" comes first, sometimes "mqtt/0/" and values will be switched. So now, maybe somebody can help to write a function to pick the right value with the right topic to compare them in the next step.
Maybe is there a Way to look if the topic contains 0, 1 ...80, and then save it in this order in a array???
Thank you in advance!
If the initial msg.payload is truly a javascript object as you describe, ie:
msg.payload = { "mqtt/1/": "-127.00", "mqtt/0/": "41.94" }
then you can reference the two values as:
var value1 = msg.payload["mqtt/1/"];
var value1 = msg.payload["mqtt/2/"];
If msg.payload is actual a JSON string, then pass the message through a JSON node first to convert it to the object.
There is no need to try splitting the string yourself and parsing the content.

getRange/setValues does not always work

I help maintain a Google spreadsheet where new data is added via a HTML form.
When it comes to add new data the insertion point of the new data depends on one of the form fields (Application Received date).
The script finds where in the sheet the data should be inserted and does 3 things:
Inserts a blank row at the correct location
Copies the row above (so formulas and conditional formatting are copied)
Replaces the data in the cells from the copy with the values entered into the form
The issue is cells A to I are value based (populated from the form) and so are cells M to O, but cells J,K,L are calculations based on some cells in A to I.
This means I have to make 2 calls to getRange/setValues and sometimes the second call (the call to set cells M,N,O does not work. The result is a new row created with the correct data in cells A to I (and thus J,K,L) but cells M,N,O stay as whatever is in those cells in the row above.
Here is the relevant code.
// Assign object data for cells A to I
var newvalues = [
[ username, applyDate, maritalStatus, sponsorApprovalDate, processingOffice, inProcessDate, extraDocsRequestedDate, nonVisaExempt, decisionMadeDate ]
];
// Set cells A to I with data from form
sheet.getRange('A' + startingRowIndex + ':I' + startingRowIndex).setValues(newvalues);
// Now assign object data for cells M to O
newvalues = [
[ coprReceivedDate, location, notes ]
];
// Set cells M to O with data from form
sheet.getRange('M' + startingRowIndex + ':O' + startingRowIndex).setValues(newvalues);
As stated above the second sheet.getRange('...').SetValues() call fails to set the values.
Any ideas?
Instead of completely recalculating the locations of your output ranges, you could get an "anchor" point at the start of the row, then use the Range.offset() method to define additional ranges relative to the anchor.
// Assign object data for cells A to I
var newvalues = [
[ username, applyDate, maritalStatus, sponsorApprovalDate, processingOffice, inProcessDate, extraDocsRequestedDate, nonVisaExempt, decisionMadeDate ]
];
// Get range "anchor" for data from form
var newRow = sheet.getRange('A' + startingRowIndex );
// Set cells A to I with data from form
newRow.offset(0,0,newvalues.length,newvalues[0].length).setValues(newvalues);
// Now assign object data for cells M to O
newvalues = [
[ coprReceivedDate, location, notes ]
];
// Set cells M to O with data from form
newRow.offset(0,13,newvalues.length,newvalues[0].length).setValues(newvalues);

Categories