Find Text in a Named Range - google-apps-script

I'm trying to get the row or index number of a string That is put in by the user. I retrieve the data in an array using spreadsheet.getRangeByName("Symbols").getValues(). The problem is it doesn't retrieve the data as strings it retrieves it as an array. So the result is an array of arrays. I wanted to use the function indexOf(result.getResponseText().toUpperCase()), but that doesn't work. Here is my code:
var aSymbols = spreadsheet.getRangeByName("Symbols").getValues();
Logger.log(aSymbols);
var row = aSymbols.indexOf(result.getResponseText().toUpperCase());
Logger.log(row);
And the results are:
[[ ], [XOM], [PLTR], [IBM], [VWAGY], [LIT], [ ], []]
I tried adding "[" and "]" to the search string, but that didn't work. I also tried using spreadsheet.getRangeByName("Symbols").getValues().toString(), but it returned 1 big long string. What am I missing?

Solution:
You can use findIndex() to get the index in 2D array:
var aSymbols = spreadsheet.getRangeByName("Symbols").getValues();
Logger.log(aSymbols);
var row = aSymbols.findIndex(function check(e) {return e[0] === result.getResponseText().toUpperCase()});
Logger.log(row);
Reference:
findIndex()

You could try this:
let aSymbolsArray = aSymbols.flat();
This will convert the double Array into a Array of strings.
function test(){
let aSymbols = [['' ], ['XOM'], ['PLTR'], ['IBM'], ['VWAGY'], ['LIT'], ['' ], ['']];
console.log(aSymbols);
//
// [ 'XOM' ],
// [ 'PLTR' ],
// [ 'IBM' ],
// [ 'VWAGY' ],
// [ 'LIT' ],
// [ '' ],
// [ '' ] ]
//
let aSymbolsArray = aSymbols.flat();
console.log(aSymbolsArray);
//
// [ '', 'XOM', 'PLTR', 'IBM', 'VWAGY', 'LIT', '', '' ]
//
}

Related

Dobbelt foreach function

I'm trying to import data from a JSON array to Google sheet. However, its a nested array which complexity exceeds my abilities.
This is My JSON (I have deleted irrelevant objects):
{"result":[
{"MyEnergyData_MarketDocument":{
"TimeSeries"[{
"Period":[{
"Point":[
{"position":"1","quantity":"0.489"},
{"position":"2","quantity":"7.57"},
{"position":"3","quantity":"0.131"}…] ETC
"Point":[
{"position":"1","quantity":"0.136"},
{"position":"2","quantity":"0.131"},
{"position":"3","quantity":"0.134"}…] ETC
“Point” … ETC
This is my GAS code
var meterdatajson = Utilities.jsonParse(meterdata);
var meterdataArray = meterdatajson['result'];
var arrayProperties = [];
meterdataArray.forEach(function(el) {
arrayProperties.push(
el.MyEnergyData_MarketDocument.TimeSeries[0].Period[0].Point.map(p => [
p.position,
p.quantity
]));});
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Forbrug");
sheet.getRange(1, 1, arrayProperties.length, arrayProperties[0].length).setValues(arrayProperties);
Secondly, when the “quantity” gets imported to sheets, it converts to a date. Makes no sense.
I have tried with a double "foreach" function. But regardless, I only get the first interval of "Point" and not the rest.
All the “position” and “quantity” need to be pushed to the same array in the same lever.
Try this
function dumpData() {
let testData = {"result":[
{"MyEnergyData_MarketDocument":
{ "TimeSeries":[
{ "Period":[
{ "Point":[
{"position":"1","quantity":"0.489"},
{"position":"2","quantity":"7.57"},
{"position":"3","quantity":"0.131"}]
},
{ "Point":[
{"position":"1","quantity":"0.136"},
{"position":"2","quantity":"0.131"},
{"position":"3","quantity":"0.134"}]
}
]
}
]
}
}
]
};
let arrayProperties = [];
let period = testData.result[0].MyEnergyData_MarketDocument.TimeSeries[0].Period.map( point => {
point.Point.forEach( position => arrayProperties.push([position.position,position.quantity]));
}
);
console.log(arrayProperties);
}
8:03:34 AM Notice Execution started
8:03:35 AM Info [ [ '1', '0.489' ],
[ '2', '7.57' ],
[ '3', '0.131' ],
[ '1', '0.136' ],
[ '2', '0.131' ],
[ '3', '0.134' ] ]
8:03:35 AM Notice Execution completed

Sorting values from JSON by values in React

I have a React form that uses i18 next translations from JSON file in a dropdown. The objects are very simple: one key, one translation, like this (but the file is very long, there are dozens of keys).
JSON:
{
"country": "Country",
"big": "Big",
"dog": "Dog",
"integration": "Integration"
}
Code that uses data from JSON:
const createField = (parentName: string, item: any) => {
const field = {
type: `${item.type}`,
name: `${parentName ?? ''}${parentName?.length ? '.' : ''}${item.name}`,
label: t(`${item.label ?? item.name}`),
properties: {
placeholder: `${item.placeholder ?? ''}`
} as any,
};
if (item.type === 'select' ) {
field.properties = {
...field.properties,
options: [].concat(item.options?).sort((a,b) =>
t(`${a.value}`) > t(`${b.value}`) ? 1 : -1).map((option: any) => {
return {
label: t(`${option.label}`),
value: option.value
};
}),
};
};
};
I want the dropdown to be sorted according to the value alphabetically because in each language the order would be different. Everything I tried sorts the array from this JSON according to the key.
I tried concat(item.options?) for sorting but getting errors "Expression expected" and "property doesn't exist".
Also tried this solution, but the dropdowns turned from text into random numbers.
if (item.type === 'select' ) {
field.properties = {
...field.properties,
options: Object.entries(item.options)
.sort(([key1], [key2]) => t(key1).localeCompare(t(key2)))
.map(([label, value]) => ({
label: t(label),
value
}))
};
};
Issue
Assuming that item.options is the JSON data you are trying to sort and convert to a list of options, then the issue is that you've appended the entire options object instead of each individual option. The result is an array of length 1. Another issue is that your data is a dictionary of key-value pairs, not an array of objects with label and value properties.
Solution
You can use both Object.entries and Object.fromEntries to convert the object to an array of key-value pairs and back. For the sorting function you want to sort by the key, and since the keys are strings, use localeCompare for the string comparison.
const data = {
country: "Country",
big: "Big",
dog: "Dog",
integration: "Integration"
};
const sortedData = Object.fromEntries(
Object.entries(data).sort(([key1], [key2]) => key1.localeCompare(key2))
);
console.log(sortedData);
Since you really want an array of shape [{ label: '...', value: '...' }, ...] you can use an array.map to map the array of key-value pairs to an array of objects with the shape you need for mapping in the option values.
const data = {
country: "Country",
big: "Big",
dog: "Dog",
integration: "Integration"
};
const sortedData = Object.entries(data)
.sort(([key1], [key2]) => key1.localeCompare(key2))
.map(([label, value]) => ({
label,
value
}));
console.log(sortedData);
For the actual rendering of your options:
options: Object.entries(item.options)
.sort(([key1], [key2]) => t(key1).localeCompare(t(key2)))
.map(([label, value]) => ({
label: t(label),
value
}))
Since it's not very clear which of the key or value of the JSON data is your option label/value you may needs to tweak the above to fit. I can help here if needed.
Hope it helps:
sort object by key and result is an array of sorted keys
const obj={
"country": "Country",
"big": "Big",
"dog": "Dog",
"integration": "Integration"
}
const sortedKeys=Object.keys(obj).sort();
console.log(sortedKeys);
sort object by value and result is an array of sorted values
const obj={
"country": "Country",
"big": "Big",
"dog": "Dog",
"integration": "Integration"
}
const sortedValues=Object.values(obj).sort();
console.log(sortedValues)
sort object by value and result is an object
const obj={
"country": "Country",
"big": "Big",
"dog": "aDog",
"integration": "Integration"
}
//for case insensitive use this function
const sortedByValue=Object.values(obj).sort(function(a, b) {
return (a.toUpperCase() < b.toUpperCase()) ? -1 : (a.toUpperCase() > b.toUpperCase()) ? 1 : 0;
})
function getKeyByValue(value) {
return Object.keys(obj).find(key => obj[key] === value);
}
const sortedObj={};
sortedByValue.map(value=>{
const key=getKeyByValue(value)
sortedObj[key]=value;
})
console.log(sortedObj)

javascript, remove double quotes inside multiple array

I am trying to build a custom visual for datastudio, I got it working but there is a step, i can't fix, Datastudio generate a json file like this
export const message = {
"tables": {
"DEFAULT": [
{
"coordinateid": [
"143.4999336,-34.777302"
],
"colorid": [
"169,255,169"
],
"sizeid": [
1
]
},
{
"coordinateid": [
"143.4999358,-34.7773749"
],
"colorid": [
"169,169,169"
],
"sizeid": [
1
]
},
{
in deckgl the relevant code is
const drawViz = (data) => {
var data1 = data.tables.DEFAULT;
getPosition: d => d.coordinateid,
the only way to make it work, is when i remove the quotes from the values inside the array
"coordinateid": [
143.4999336,-34.777302
]
is there a way either to remove the double quotes between the bracket or a way just to parse the values and ignoring the double quotes
DataStudio returns GEO LatLong coordinates as a comma separated string. The correct way to parse this would be the following:
var baseCoordinate = "143.4999336,-34.777302";
// Split out the coordinates into multiple strings
var coordinates = baseCoordinate.split(",");
// Turn the strings into floats
var coordinatesAsNumbers = coordinates.map((coord) => parseFloat(coord));
This will give you the coordinates as floats in an array, which seems to be the format that deckgl is expecting.
find the answer
basically, change the javascript object to string using JSON.stringify the using regex to replace the strings then use Json.parese to change it back to an object
var data1 = data.tables.DEFAULT;
var data2 = JSON.stringify(data1);
var data3 = data2.replace(/\"]/g, "]");
var data4 = data3.replace(/\["/g, "[");
var data4 = JSON.parse(data4);

Restructuring a large amount of values in a JSON file

I have a JSON file with a large amount of the following values:
"values": [
"Foo": 1,
"Bar": 2,
"Baz": 3,
...
],
How do I efficiently convert this into:
"values": [
{
"name": "Foo",
"value": 1
},
{
"name": "Bar",
"value": 2
},
{
"name": "Baz",
"value": 3
},
...
],
Any help would be appreciated!
Okay, so there are two problems with your input. The first is the fact that the given JSON is invalid, so can't directly be parsed. The square brackets after "values" should be curly brackets, to allow for a hash instead of an array:
let raw_old_data =
// Read the old file
fs.readFileSync('./input_data.json').toString()
// Remove all newlines which could interfere with the regex
.replace(/[\r\n]/g, '')
// Replace the square brackets after `"values"` with curly braces
.replace(/"values": \[(.+?)\]/g, '"values": { $1 }');
To convert this (now valid) string to a JSON object, you use JSON.parse:
let old_data = JSON.parse(raw_old_data);
The second problem is that the format in which the values are stored doesn't match your needs. You want to convert from { key: "value" } to [ name: "key", value: "value" ]. The following function can do that, assuming your version of Node supports ES6 (If not, look at Murillo's answer):
function fix_format(obj) {
// This is where we keep the new items in the correct format
let res = [];
// Loop over all values
Object.keys(obj.values).forEach(name => {
let value = obj.values[name];
// Change the format and add to resulting array
res.push({
// If the variable is the same as the key of the hash, it doesn't have to be specified
name,
value,
});
});
return res;
}
All that's then left to do is loop all data from the old object through that function with the Array.map function:
let new_data = old_data.map(fix_format);
And optionally write it back to a file to use with a different program:
fs.writeFileSync('./formatted_data.json', JSON.stringify(data, null, 2));
Note: The 2 in the JSON.stringify function indicates that the resulting JSON should be padded with 2 spaces, to keep it readable.
With ES6:
Object.keys(values).map(name => ({
name,
value: values[name]
}))
Without ES6:
var keys = Object.keys(values);
var newValues = [];
for(var i = 0; i < keys.length; i++){
newValues.push({
name: keys[i],
value: values[keys[i]]
})
}
If your intention is to use the received data i.e obtain data from DB (e.g MSSql, MySql...) using the connection.query(your_custom_sql_query, (err, rows, fields)
for more info:Node.js MySQL Select From Table
I'll recommend you to use:
const myJson = JSON.stringify(rows[0]);

sorting json arrays in json array using angular js

I have json array in the following format,
$scope.data = [{
"values" : [["2 Day", 103.89], ["NextDay", 107.41], ["Ground", 428.75]],
"key" : "FedEx"
}, {
"values" : [["Ground", 117.8], ["NextDay", 10], ["2 Day", 15]],
"key" : "UPS"
}]
I need to sort it in to the following format :
$scope.data = [{
"values" : [["2 Day", 103.89], ["NextDay", 107.41], ["Ground", 428.75]],
"key" : "FedEx"
}, {
"values" : [["2 Day", 15], ["NextDay", 10], ["Ground", 117.8]],
"key" : "UPS"
}]
How can I do it using Angularjs?
A similar data set for which I want similar sorting to be applied, but here I have time (in long format) instead strings.
$scope.data1 = [{
"values" : [[1359072000000, 103.89], [1365116400000, 107.41], [1357516800000, 428.75]],
"key" : "FedEx"
}, {
"values" : [[1357516800000, 117.8], [1359072000000, 100], [1365116400000, 15]],
"key" : "UPS"
}];
To be formatted as
$scope.data1 = [{
"values" : [[1359072000000, 103.89], [1365116400000, 107.41], [1357516800000, 428.75]],
"key" : "FedEx"
}, {
"values" : [[1359072000000, 100],[1365116400000, 15], [1357516800000, 117.8], ],
"key" : "UPS"
}];
Natural sorting can be applied in js like this. Natural sorting is required since strings in your array contains numbers.
function strcmp(a, b) {
return a > b ? 1 : a < b ? -1 : 0;
}
function natcmp(a, b) {
var x = [], y = [];
a[0].replace(/(\d+)|(\D+)/g, function($0, $1, $2) { x.push([$1 || 0, $2]) })
b[0].replace(/(\d+)|(\D+)/g, function($0, $1, $2) { y.push([$1 || 0, $2]) })
while(x.length && y.length) {
var xx = x.shift();
var yy = y.shift();
var nn = (yy[0]-xx[0]) || strcmp(yy[1],xx[1]);
if(nn) return nn;
}
if(x.length) return -1;
if(y.length) return +1;
return 0;
}
Apply sorting in your array using javascript sort function as shown below.
$scope.data = $scope.data.map(function(d){ d.values = d.values.sort(natcmp); return d; });
Natural sorting is not needed for the second dataset. To sort the array in descending order by time, try this.
$scope.data1 = $scope.data1.map(function(d) {
d.values = d.values.sort(function(a, b) {
return new Date(b[0]) - new Date(a[0])
});
return d;
});
for displaying the array with some ng-repeat, you could use a filter
https://docs.angularjs.org/api/ng/filter/filter
There is orderBy filter but you can create your own filters.
for the data model to be sorted and not only for presentation, you could use the javascript sort function for arrays and give it a sorting implementation which compares 2 elements.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort