Import Range, get all data IF column C matches several values - javascript

The code below is my current code that works fine. It lets me import all data from one spreadsheet tab to another spreadsheet giving me the full range A:J. But now I do not want all data to be imported but I want to filter out specific stores (in sales data) based on their id number. The ID numbers are located in column C in source spreadsheet. I want to Filter for 8 different values in column C and import all data matching that condition into the targeted spreadsheet.
function importhistorical_sales_ee() {
//geth values to be imported from the source sheet
var values = SpreadsheetApp.openById('1mVECYu27lnOIFf7vHk1kI_55DID3APvWr_toWuZho14').
getSheetByName('Historical sales for SC planning -.csv').getRange('A:J').getValues();
//set values imported
var target = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('test_ee');
target.getRange("A3:J").clearContent();
target.getRange(3,1,values.length,values[0].length).setValues(values);
}
I tested several options like the one below (but it is not working). I am expecting to be able to set the column I want to filter on and then also set which values I want to look for in that column.

Here is a simple example.
I have sample data in a spreadsheet like this.
I then filter the data for an array of 3 values as shown in the script. You can make it 8 or whatever you want. I prefer to use getDataRange() but you could use getRange(1,1,sheet.getLastRow(),9).getValues(). This ensures your not getting a bunch of blank rows.
Code.gs
function filterStores () {
try {
let wanted = [1,3,5];
let spread = SpreadsheetApp.getActiveSpreadsheet();
let sheet = spread.getSheetByName("Sheet1");
let stores = sheet.getRange(1,1,sheet.getLastRow(),9).getValues();
let filtered = stores.filter( store => {
return wanted.some( id => store[2] === id );
}
);
let target = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('test_ee');
target.getRange(3,1,target.getLastRow()-2,9).clearContent();
target.getRange(3,1,filtered.length,filtered[0].length).setValues(filtered);
console.log(filtered);
}
catch(err) {
console.log(err);
}
}
Execution log
9:16:03 AM Notice Execution started
9:16:05 AM Info [ [ 'a1', 'b1', 1, 'd1', 'e1', '', 'g1', '', '', 'j1' ],
[ 'a3', 'b3', 3, 'd3', 'e3', '', 'g3', '', '', 'j3' ],
[ 'a5', 'b5', 5, 'd5', 'e5', '', 'g5', '', '', 'j5' ],
[ 'a3', 'b3', 3, 'd3', 'e3', '', 'g3', '', '', 'j3' ] ]
9:16:05 AM Notice Execution completed
References
Array.filtere()
Array.some()
Arrow function

Related

Find row and set value in column google app scripts

I have a 2d array:
const arr = [ [ 'John Doe',
'john#something.com',
'Some text here',
'' ],
[ 'Steven Smith',
'steven#something.com',
'Another irrelevant text here',
'' ],
]
I want to find a row in the tab that matches the name in each array in this list and add a text value in the last column (where the '' is).
For example:
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName(sheetName);
const range = sheet.getDataRange()
const data = range.getValues()
const people = data.slice(1)
if a name in arr is found in people, add the text 'Found' in the last column in people for that name.
people looks like this:
[ [ 'John Doe',
'john#something.com',
'Some text here',
'' ] ]
I was able to find the match using this:
const peopleTarget = arr.map(person => people.find(el => el[0] === person[0]))
However, I need the row number to be able to set a value.
I know I need the getRange to be able to use setValue but I'm having difficulty grabbing the row number based on matching value between two arrays.
Any help is appreciated.
Create a set of names from arr, iterate over data and modify them in-place. Then setValues the modified array.
const arr = [
['John Doe', 'john#something.com', 'Some text here', ''],
[
'Steven Smith',
'steven#something.com',
'Another irrelevant text here',
'',
],
],
arrSet = new Set(arr.map((el) => el[0]));
data.forEach((people) =>
arrSet.has(people[0]) ? (people[3] = 'found') : null
);
range.setValues(data);

Nested loop of array of dicts doesn't work in Google Sheets script

So I want to loop a column Text in a Google sheet and assign values to columns main_category, item_category and item based on the value of Text which maps to an array of dictionaries for each rule applied. I'm struggling at setting up the nested loop for the dictionary.
Sheet structure / source data:
Text main_category item_category item
-------------------------------------------------
Banana
Tomato
Choco
Desired outcome:
Text main_category item_category item
-------------------------------------------------
Banana Fruits Yellow Banana
Tomato Vegetables Red Tomato
Choco Sweets Brown Choco
My approach:
function process_actuals() {
// Initiating an array of dicts
var rules_array = [
{contains: 'Bana', main_category: 'Fruits', item_category: 'Yellow', item: 'Banana'},
{contains: 'Tomato', main_category: 'Vegetables', item_category: 'Red', item: 'Tomato'},
{contains: 'Choco', main_category: 'Sweets', item_category: 'Brown', item: 'Choco'},
];
// Get active Spreadsheet
var s = SpreadsheetApp.getActiveSpreadsheet();
// Get sheet "Source"
var sht = s.getSheetByName('Source')
// Get the range where data is present in sht
var drng = sht.getDataRange();
// Get the range size
var rng = sht.getRange(2,1, drng.getLastRow(),drng.getLastColumn());
// Get an array of values within rng
var rngA = rng.getValues();
// Set up loop
for (var i = 2; i < rngA.length; i++) {
// Get the search string
let search_cell = sht.getRange(i, 1)
search_string = search_cell.getValue()
// Loop array of dicts and check if search string is within "contains" key
for (var dict in rules_array) {
// If search string is in contains key, populate row
if (search_string in dict['contains']) { // breaks here
// Populate rows
var target_cell = sht.getRange([i][2]) // main_category
target_cell.setValue(dict['main_category'])
}
}
}
}
I receive the error TypeError: Cannot use 'in' operator to search for 'Banana' in undefined.
Modification points:
When your rules_array is used, dict of for (var dict in rules_array) { is 0, 1, 2,,,. I thought that this might be the reason for your issue. This has already been mentioned in the comments.
When setValue is used in the loop, the process cost will become high.
When these points are reflected in a sample script, how about the following sample script?
Sample script:
function process_actuals() {
var rules_array = [
{ contains: 'Bana', main_category: 'Fruits', item_category: 'Yellow', item: 'Banana' },
{ contains: 'Tomato', main_category: 'Vegetables', item_category: 'Red', item: 'Tomato' },
{ contains: 'Choco', main_category: 'Sweets', item_category: 'Brown', item: 'Choco' },
];
// 1. Retrieve values from "Source" sheet.
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Source');
var [[,...header], ...values] = sheet.getDataRange().getValues();
// 2. Create an array for putting to the sheet.
var v = values.map(([a]) => {
var t = rules_array.filter(o => a.includes(o.contains));
return t.length == 1 ? header.map(h => t[0][h]) : Array(3).fill("");
});
// 3. Put the array to "Source" sheet.
sheet.getRange(2, 2, v.length, v[0].length).setValues(v);
}
In this sample script, an array for putting to Spreadsheet is created using the retrieved values and rules_array, and put it to the sheet of Source.
Note:
In this sample script, from your question, it supposes that the header row of your script is Text, main_category, item_category, item. Please be careful about this.
Reference:
map()
Added:
From your following replying,
However when I log v it is empty, thus the macro doesn't populate anything. Do I have to further enrich your sample script before? Re process cost, we aretalking about a couple of thousand rows only
In this case, I'm worried that your Spreadsheet might not have the header row. If my understanding is correct, how about the following sample script?
Sample script:
function process_actuals() {
var rules_array = [
{ contains: 'Bana', main_category: 'Fruits', item_category: 'Yellow', item: 'Banana' },
{ contains: 'Tomato', main_category: 'Vegetables', item_category: 'Red', item: 'Tomato' },
{ contains: 'Choco', main_category: 'Sweets', item_category: 'Brown', item: 'Choco' },
];
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Source')
var values = sheet.getDataRange().getValues();
var header = ["main_category", "item_category", "item"];
var v = values.map(([a]) => {
var t = rules_array.filter(o => a.includes(o.contains));
return t.length == 1 ? header.map(h => t[0][h]) : Array(3).fill("");
});
sheet.getRange(1, 2, v.length, v[0].length).setValues(v);
}
In this sample script, it supposes that your Spreadsheet has no header row. And, the order of values is given by var header = ["main_category", "item_category", "item"];.

Merge different Arrays and Calculate Average price Javascript

I am trying to calculate and create an Array with Average Prices for different stocks.
For every stock, I have the Data in this format:
{
prices: [
[
1634304009628,
0.7118076876774715
],
[
1634307586874,
0.7063647246346818
],
[
1634311139365,
0.7049706990925925
],
[
1634313858611,
0.7085543691926037
],
[
1634318343009,
0.7057442983161784
]
]
}
For every stock API call I get the data like how I posted above, it has 2 values timestamp and the second one is the price. Now let's say I want the average trend for 5 stocks I will get the data in 5 different arrays and I just want to somehow make an average out of those 5 arrays in one to find the trend.
For the final result, I want the Array to be in the same format just with the calculated average altogether (the goal is to identify the trend direction).
What would be the best way to do that? I am Using React
first create and array of prices only and then using reduce you can just do this:
let myObj = {
prices: [
[
1634304009628,
0.7118076876774715
],
[
1634307586874,
0.7063647246346818
],
[
1634311139365,
0.7049706990925925
],
[
1634313858611,
0.7085543691926037
],
[
1634318343009,
0.7057442983161784
]
]
};
const average = arr => arr.reduce( ( p, c ) => p + c, 0 ) / arr.length;
const pricesArr = myObj.prices.map(function(value,index) { return value[1]; })
const result = average( pricesArr );
console.log(result);

Using [Sequelize.Op.in] for json object arrays

I have a meta tag table which contains a tagId and a value.
I have an array of tagId,value objects
Eg : [{'tagId':2, 'value':33}, {'tagId':2, 'value':34}, {'tagId':1,
'value':34}, etc.. ]
My metaTag table consists of a virtual column which will return the {tagId,value} object for each entry in table. My question is how can I select rows with each {tagId, value} pair in the array.
In other words, I want to be able to do something like
[Sequelize.Op.in]:[{'tagId':2, 'value':33}, {'tagId':2, 'value':34}]
This doesn't work, however.
I might not have explained this well, English isn't my first language. Please ask if you need any clarification on the issue.
You can attain this by using Op.or. If I am not wrong you are trying
('tagId' = 2 and 'value' = 33) or ('tagId' = 2, 'value' = 34):
where: { [Sequelize.Op.or]: [{'tagId':2, 'value':33}, {'tagId':2, 'value':34}] }
You can add n number of values to the or array. As per your requirement.
if you want to do a in like this:
tagId in(2, 2) and value in (33, 34) then:
where: {'tagId':[2], 'value':[33, 34]}
You don't need the explicit Op.in for the array.
You can use there:
const myDeviceIds = [1, 2, 3, 4, 7, 9, 29];
const macroDevices = await MacroDevice.findAll({
where: {
deviceId: {
[Op.in]: myDeviceIds,
},
life: {
[Op.not]: null,
},
status: {
[Op.is]: null,
}
},
order: [
['id', 'DESC']
],
limit,
offset,
include: [
Macro,
Targets,
]
});

java script 2D array find unique array combinations

I need to know the best way to get following results
courseFrequency : [
{
'courses': [
'a.i'
],
'count' : 1
},
{
'courses': [
'robotics'
],
'count' : 2
},
{
'courses': [
'software engineering', 'a.i'
],
'count' : 2
},
{
'courses': [
'software engineering', 'a.i','robotics'
],
'count' : 1
}
]
from following json data.
arr = [
{
'courses': [
'a.i'
]
},
{
'courses': [
'robotics'
]
},
{
'courses': [
'software engineering', 'a.i'
]
},
{
'courses': [
'robotics'
]
},
{
'courses': [
'software engineering', 'a.i'
],
'courses': [
'software engineering', 'a.i','robotics'
]
}];
Basically i need to find out the unique courses and their frequency. What is the most optimal way to do that ?
const hash = {}, result = [];
for(const {courses} of arr){
const k = courses.join("$");
if(hash[k]){
hash[k].count++;
} else {
result.push(hash[k] = { courses, count : 1 });
}
}
Simply use a hashmap to find duplicates. As arrays are compared by reference, we need to join it to a string for referencing ( note that this will fail if a coursename contains the joining symbol ($))
There both of them are best for area relates to them.These concepts are heaving their own property and methods to accomplish a certain task like JSON used for data transfer and cross browsing aspect as the common type data value.Arrays are really good at storing ordered lists and ordering things while the cost of removing/splicing elements is a bit higher.
JSON is a representation of the data structure, it's not an object or an array.
JSON can be used to send data from the server to the browser, for example, because it is easy for JavaScript to parse into a normal JavaScript data structure.for doing an action on JSON data you need to convert it into an object which is also seamed some property like ARRAY.
Arrays are really good at storing ordered lists and ordering things while the cost of removing/splicing elements is a bit higher.
Relative link
Relative link

Categories