JavaScript: else if won't work in for loops [Spreadsheet] - javascript

I am trying to loop through the whole row in my google sheet and break it at the last row +1
'i' as an indicator for stopping the loop, using else-if condition.
But somehow the loop won't go through else-if condition.
The loop stops when 'i' doesn't meet the for-loop condition, How can I make it stop when meeting else-if condition instead ?
I'm fresh and new to Javascript and Appscript, will grateful for every advise.
function makedict(){
var product = {}
var code = code_dicted
var name = name_dicted
var unit = unit_dicted
var balance = balance_dicted
var value0 = sheet.getRange("C:M").getValues().map(row => [ row[0]]); //code
var value1 = sheet.getRange("C:M").getValues().map(row => [ row[1]]); //name
var value5 = sheet.getRange("C:M").getValues().map(row => [ row[5]]); //bal
var value6 = sheet.getRange("C:M").getValues().map(row => [ row[10]]); //unit
var range = sheet.getRange("C:M").getValues().length
var lastRow = sheet.getLastRow()
var dict = {}
var result = "\n\n\n"
for (i = 1;i < range;i++){
dict["code"] = value0[i]
var code_dicted = dict["code"]
var code = code_dicted
dict["name"] = value1[i]
var name_dicted = dict["name"]
var name = name_dicted
dict["balance"] = value5[i]
var balance_dicted = dict["balance"]
var balance = balance_dicted
dict["unit"] = value6[i]
var unit_dicted = dict["unit"]
var unit = unit_dicted
product["detail"] = {code,name,balance,unit}
// console.log(product)
if (product.detail["balance"]<product.detail["unit"]){
var text = product.detail["code"]+product.detail["name"]+product.detail["balance"]+product.detail["unit"];
result = result.concat(text)+"\n\n"
}
else if (i === lastRow+1){
console.log(result)
break
}
}

Solved
Thank you. I've solved it following the above advise.
using While-loop instead.
var i = 1;
while (i < range){
dict["code"] = value0[i]
var code_dicted = dict["code"]
var code = code_dicted
dict["name"] = value1[i]
var name_dicted = dict["name"]
var name = name_dicted
dict["balance"] = value5[i]
var balance_dicted = dict["balance"]
var balance = balance_dicted
dict["unit"] = value6[i]
var unit_dicted = dict["unit"]
var unit = unit_dicted
i = i+1
product["detail"] = {code,name,balance,unit}
// console.log(product)
if (product.detail["balance"]<product.detail["unit"]){
var text = product.detail["code"]+product.detail["name"]+product.detail["balance"]+product.detail["unit"];
result = result.concat(text)+"\n\n"
}
else if (i === lastRow+1){
console.log(result)
break
}
}

for (i = 1;i < range + 1 ;i++){
Try the above code, I'm assuming lastRow is a number and it ranges from 0 to range

Related

How to recurring the loop to map an array values with another array values?

I am working with the loop and need some help.
Actually, I have the 6 cases and want to assign them with two or three Representatives one by one. for exam :
caseIds = [1,2,3,4,5,6]
Representatives = [A, B]
now cases should be assign like
1 with A,
2 with B,
3 with A,
4 with B,
5 with A
so and so.
what should I do?
var array = [1, 2, 3, 4];
var ilength = array.length;
for (var i = 0; i < ilength; ++i) {
//console.log(array[i]);
//window.alert(array[i]+ " "+s[m]);
var s = ['A', 'B', 'C'];
var slength = s.length;
for (var m = 0; m < slength; ++m) {
//console.log(array[i]);
console.log(array[i] + " " + s[m]);
}
}
I tried with above code. but did not get desired output.
How can I do the same in below NetSuite suitescript?
function caseAssignement() {
var filters = new Array();
filters[0] = new nlobjSearchFilter('internalid', null, 'anyof', 1234,9876);
//Setting up the columns.
var columns = new Array();
columns[0] = new nlobjSearchColumn('internalid');
var searchResult = nlapiSearchRecord('recordid', null, filters, columns);
nlapiLogExecution('DEBUG', 'searchResult', searchResult);
for(var i = 0; searchResult != null && i < searchResult.length; i++)
{
try{
//obtain a result
var result = searchResult[i];
nlapiLogExecution('DEBUG', 'result', result);
var id = result.getValue('internalid');
nlapiLogExecution('DEBUG', 'id', id);
var employeeid = searchEmp();
var rec = nlapiLoadRecord('recordid',id);
rec.setFieldValue('field_id',empid); //I want to set each employee id in the field of each record.
nlapiSubmitRecord(rec);
}catch (e) {
var error = e.details || e.message || e.toString();
nlapiLogExecution('DEBUG', 'Email error', error );
}
}
}
// Search Employee based on file name.
function searchEmp(searchResult) {
var i_emp_id = null;
var filters = new Array();
filters[0] = new nlobjSearchFilter('isinactive', null, 'is', 'F');
filters[1] = new nlobjSearchFilter('internalid', null, 'anyof', 2222,1111);
var columns = new Array();
columns[0] = new nlobjSearchColumn('internalid');
var o_emp_search = nlapiSearchRecord('employee_record', null, filters, columns);
for(var i = 0; o_emp_search != null && i < o_emp_search.length; i++)
{
var result = o_emp_search[i];
i_emp_id = result.getValue('internalid');
return i_emp_id;
}
}
You can use like this code for your scenario .
It will execute the same. You can run and check it.
Take the case id in array1 and representative record id in array2.
var arr1=[1,2,3,4,5,6,7,8,9, 10,11,12,13];
var arr2=["a","b"];
var k=0, j, l =arr2.length;
for(var i=k;i<arr1.length;i+k){
if(arr2.length>arr1.length){
l= arr1.length;
}
for(j=0;j<l;j++){
console.log(arr2[j]+" with "+arr1[j]);
}
k=j;
arr1= arr1.slice(arr2.length); // current sliced arr1 value
}

Javascript to get the Random sample of data

Hi all,
I am working on a dataset on Google Sheet and I need to get the random data (specified number) by the col 3 names to audit I am using google app script for the same but couldn't able to get the data. Here's the code I tried but I don't want the % of data I want the equally distributed random data for each employee in col 3.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var trn = ss.getSheetByName('Data');
var originalData = trn.getRange(2, 1, trn.getLastRow() - 1, 3).getValues();
var ReviewerEmail = data;
var data = originalData.filter(function(item) {
return item[1] === 'rob' || item[1] === 'john' || item[1] === 'toger';
});
//Logger.log(data);
var targetsheet = ss.insertSheet(Reviewer);
targetsheet.getRange(1, 1, data.length, data[0].length).setValues(data);
}
function getsampledata() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange('A:C');
var values = range.getValues();
var headers = values.shift();
var nameColumn = 1;
var uniqueNames = values
.map((row) => row[nameColumn])
.filter((item, i, ar) => ar.indexOf(item) === i)
.filter(String);
var data = [headers];
uniqueNames.forEach(function(name) {
var nameEntries = values.filter((row) => row[nameColumn] == name);
var entries = nameEntries.length;
var tenth = Math.round((entries / 100) * 27.35); //Sampling Percentage
for (i = 0; i < tenth; i++) {
var random = Math.floor(Math.random() * nameEntries.length);
data.push(nameEntries[random]);
nameEntries.splice(random, 1);
}
});
return data;
}
If you want a specific number of sample, then use a parameter to indicate how many you want for each.
Whole working script:
function getsampledata(sample) {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange('A:C');
var values = range.getValues();
var headers = values.shift();
var nameColumn = 2;
var uniqueNames = values
.map((row) => row[nameColumn])
.filter((item, i, ar) => ar.indexOf(item) === i)
.filter(String);
var data = [headers];
uniqueNames.forEach(function(name) {
var nameEntries = values.filter((row) => row[nameColumn] == name);
for (i = 0; i < sample; i++) {
var random = Math.floor(Math.random() * nameEntries.length);
data.push(nameEntries[random]);
nameEntries.splice(random, 1);
}
});
return data;
}

How to write a For Loop with variables that include an incremental split [] to minify JS code?

Hopefully I am asking this question in the right way, I am a total noob to For Loops in JavaScript...
I have to write a For Loop for this:
var file = '/home/xxxxx/xxxx/xxxx/xxxx';
var obj = result.rows;
var split = JSON.stringify(obj).split(',');
var date1rpl = split[0].replace(/\"/g,"");
var date1og = date1rpl.slice(2,100);
var date1 = splitabc(date1og);
var usr1 = split[1].replace(/\"/g,"");
var session1 = split[2].replace(/("|])/g,"");
var date2rpl = split[3].replace(/\"/g,"");
var date2og = date2rpl.slice(1,100);
var date2 = splitabc(date2og);
var session2 = split[5].replace(/("|])/g,"");
var usr2 = split[4].replace(/\"/g,"");
var date3rpl = split[6].replace(/\"/g,"");
var date3og = date3rpl.slice(1,100);
var date3 = splitabc(date3og);
var session3 = split[8].replace(/("|])/g,"");
var usr3 = split[7].replace(/\"/g,"");
var date4rpl = split[9].replace(/\"/g,"");
var date4og = date4rpl.slice(1,100);
var date4 = splitabc(date4og);
var session4 = split[11].replace(/("|])/g,"");
var usr4 = split[10].replace(/\"/g,"");
var date5rpl = split[12].replace(/\"/g,"");
var date5og = date5rpl.slice(1,100);
var date5 = splitabc(date5og);
var session5 = split[14].replace(/("|])/g,"");
var usr5 = split[13].replace(/\"/g,"");
jsonfile.writeFile(file, obj);
The split[] seems to be incrementing by +3 for each user, session, date1rpl. How can I include this in a for loop that would run through the variables so that I can just have daterpl, dateog, date, usr, and session as variables and not have to number each variable and repeat it?
var date1rpl = split[0].replace(/\"/g,"");
var date1og = date1rpl.slice(2,100);
var date1 = splitabc(date1og);
var usr1 = split[1].replace(/\"/g,"");
var session1 = split[2].replace(/("|])/g,"");
So you want to loop over ever item in the split array and do some work on it and then save the updated version for later use.
You can use a For Loop
var dates = [];
var split = JSON.stringify(obj).split(',');
for(var i = 0; i< split.length; i++){
var dateRpl = split[i].replace(/\"/g,"");
var dateOG = dateRpl.slice(2,100);
dates.push(splitabc(dateOG));
}
// dates is now an array of all the processed dates
Or you can use the forEach method on arrays
var dates = [];
var split = JSON.stringify(obj).split(',');
split.forEach(function(string) {
var dateRpl = string.replace(/\"/g,"");
var dateOG = dateRpl.slice(2,100);
dates.push(splitabc(dateOG));
});
// dates is now an array of all the processed dates

Return multiple lines instead of console.log

I have the following code that produces the output I need using console.log
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
for(i = 0; i < productId.length; i++) {
console.log(advertiserId+"|"+ord+"|"+productId[i]+"|"+productName[i]+"|"+productItemPrice[i]);
}
}
product()
console.log result -
1234|543210|id1|product1|10
1234|543210|id2|product2|20
1234|543210|id3|product3|30
1234|543210|id4|product4|40
When changing console.log to return, only the first line is returned. return result -
1234|543210|id1|product1|10
Is there a way to return the same results as console.log?
You would usually push the lines to an array and return the array
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
var ret = [];
for(i = 0; i < productId.length; i++) {
ret.push(advertiserId+"|"+ord+"|"+productId[i]+"|"+productName[i]+"|"+productItemPrice[i]);
}
return ret;
}
let data = product();
console.log(data); // array holding the lines
// or join it with a newline
console.log(data.join("\n")); // lines as string
Push the results into an array then use the Array#join function.
function product() {
const advertiserId = 1234;
const ord = 543210;
const productId = "id1|id2|id3|id4".split("|");
const productName = "product1|product2|product3|product4".split("|");
const productItemPrice = "10|20|30|40".split("|");
const results = [];
for (let i = 0; i < productId.length; i++) {
results.push(`${advertiserId}|${ord}|${productId[i]}|${productName[i]}|${productItemPrice[i]}`);
}
return results;
}
const data = product();
console.log(data.join('\n'));
You could also use other console commands:
console.dir(data);
When you return from a function, it won't continue to execute. In your case, you can store each result and return them all at once.
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
var results = [];
for(i = 0; i < productId.length; i++) {
results.push(advertiserId + "|" + ord + "|" + productId[i] + "|" + productName[i]+ "|" +productItemPrice[i]);
}
return results;
}
results is now an array of strings that you can do what you want with.
Write the output to a variable then return. using return inside the loop will exit the loop
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
var output = "";
for(i = 0; i < productId.length; i++) {
output += advertiserId+"|"+ord+"|"+productId[i]+"|"+productName[i]+"|"+productItemPrice[i] + "\n";
}
return output;
}
product()
I think what you need is to store every result of the iteration on a variable, and then after the for loop you return it. Like
var a;
for loop... {
a += (all of your stuff) + '\n'
}
return a;
This should keep the break lines into the variable and so keep the indentation you want like console.log but into a variable.
If you need to have separated values you could store every line into a array and return the array after the for loop.
A return statement stops the function immediately and can only return a single value. You can add up data in the loop and then return at the end.
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
var result = [];
for(i = 0; i < productId.length; i++) {
result.push(advertiserId+"|"+ord+"|"+productId[i]+"|"+productName[i]+"|"+productItemPrice[i]);
}
return result;
}
product()
Can map() the values into an array and return the array or array joined to string
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
return productId.map(function(id, idx) {
return [
advertiserId,
ord,
productId[idx],
productName[idx],
productItemPrice[idx]
].join('|')
}).join('\n')
}
console.log(product());

Javascript: Adding final element to array after for loop completes

Explanation of Desired Results
My source is over 30,000 lines of very structured text with incrementing front numbers followed by incrementing back numbers and separated by a colon. Stripping out the non-essentials, I am left with the following sourceArray, truncated for convenience :)
sourceArray = ["001:001", "001:002", "001:003",
"002:001", "002:002",
"003:001", "003:002"];
I am trying to count how many back numbers for each front number and push that to an array. In pseudocode, my final results should look like this:
myArray[totalNumberOf_001_Items, totalNumberOf_002_Items, totalNumberOf_003_Items]
Which in my simple example should give me a final value of:
[3, 2, 2]
Problem and Question
My for loop ends at the end of my data and I am therefore one element short in my array.
How do I make an "extra pass" through the loop or is there another way to get the final element pushed to my array?
var sourceArray = ["001:001", "001:002", "001:003",
"002:001", "002:002",
"003:001", "003:002"
];
var myArray = [];
var frontCounter = 1;
var backCounter = 1;
for (var i = 0; i < sourceArray.length; i++) {
var text = sourceArray[i];
var front = text.substr(0, 3);
front = Number(front);
var back = text.substr(4, 3);
back = Number(back);
if (front == frontCounter) {
backCounter++;
} else {
myArray.push(backCounter - 1);
backCounter = 2;
frontCounter++;
}
}
console.log(myArray); // result [3, 2]
You could use an object like below to keep track of how many times the the piece of text appear, the text would be the keys and as value the number of times they appear. From that you can build you array
var sourceArray = ["001:001", "001:002", "001:003",
"002:001", "002:002",
"003:001", "003:002"];
var frontEncounters = {};
function updateFrontEncounters(frontEncounters, front){
var keys = Object.keys(frontEncounters);
if(keys.indexOf(front) == -1)
{
frontEncounters[front] = 1;
}
else
{
frontEncounters[front] += 1;
}
}
for(var item in sourceArray){
var text = sourceArray[item];
var front = text.substr(0, 3);
var back = text.substr(4, 3);
updateFrontEncounters(frontEncounters, front);
}
var keys = Object.keys(frontEncounters);
var myArr = [];
for(var key in keys)
{
myArr.push(frontEncounters[keys[key]])
}
console.log(myArr);
Use an object to store the "front" numbers along with their count.
for (var i = 0; i < sourceArray.length; i++) {
var num = sourceArray[i].slice(0,3);
counts[num] = counts[num] ? counts[num]+1 : 1;
}
Once done, you can very easily convert that to an array:
var result = Object.keys(counts).map(function (key) {
return counts[key];
});
With ES-2017, it is even easier:
var result = Object.values(counts)
Working Snippet:
var sourceArray = ["001:001", "001:002", "001:003",
"002:001", "002:002",
"003:001", "003:002"];
var counts = {};
for (var i = 0; i < sourceArray.length; i++) {
var num = sourceArray[i].slice(0,3);
counts[num] = counts[num] ? counts[num]+1 : 1;
}
console.log(counts);
var result = Object.keys(counts).map(function (key) {
return counts[key];
});
console.log(result);
// ES-2017
//console.log(Object.values(counts));
Here's an alternative that you can use so that you don't have to go through the entire source of lines (30,000) . Use a while loop so that you can break as soon as you reach a 0; use Map to store the unique number by making the index/frontnumber the key and make its value an object that serves as a counter to keep track of it's total. If the key exists, update the total; if it doesn't, create a new counter object. Then just return the Map by transforming it into the desired array by map'ing it to an array with only the totals.
var sourceArray = ["001:001", "001:002", "001:003",
"002:001", "002:002",
"003:001", "003:002"
];
function getTotal(sourceArray) {
let count = new Map();
let update = item => count.get(item).total++;
let create = item => count.set(item, {total: 1});
const getItem = index => {
let text = sourceArray[index];
return text.substr(0, 3);
}
let index = -1;
let start = 0;
while (index != 0 && start < sourceArray.length) {
index = getItem(start++);
count.has(index) ? update(index) : create(index);
}
return [...count.values()].map(item => item.total);
}
console.log(getTotal(sourceArray));

Categories

Resources