I want to sum the values from an API response. The values are stored in JSON format. My code looks like this:
var returnCode;
var getUrl = "url";
returnCode = httpGet(getUrl);
var objekt = JSON.parse(returnCode);
function httpGet(url){
var response = requestSync(
'GET',
url
);
return response.body;
}
var price = 0;
for(i=0; i<30; i++)
{
price = price + objekt.data.sales[i].price;
}
price /= 30;
console.log(price); //displays NaN
console.log(objekt.data.sales[1].price); //displays correct price of one element
The problem is that when I try to output price it returns NaN, but if i just display a value of a single element it works fine. Any ideas why it does that? there are 30 elements in the array BTW.
Actually Json values are coming as string
Change the for loop
for(i=0; i<30; i++)
{
price = price + parseInt(objekt.data.sales[i].price);
}
Related
In here I am trying to make a checking where if the "STATUS" column is 'NEW FILE', then i would like to perform a file conversation from excel to spreadsheet.
For the "STATUS" column i created an IF-ELSE statement,
if (row[0] === "last week file") {
newValues.push(['OLD FILE'])
}
else{
newValues.push(['NEW FILE'])
ConvertFiles()
return
}
Therefore, I am making a check through the "STATUS", if the status column is empty it will be written as 'NEW FILE', and then it will perform an file conversion from excel to spreadsheet since i already called the method inside it.
Here is the EDITED version code of the file conversion:
function ConvertFiles() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var range = sheet.getRange(2, 1, sheet.getLastRow()-1, 5); // get A2:E6 range
var data = range.getValues(); // get A2:E6 data
for(var i = 0; i < data.length; i++){
if(data[i][2] == " "){
for( var r= 2;r < sheet.getLastRow()+1; r++){
var fileId = sheet.getRange(r,1).getValue();
var folderID = sheet.getRange(r,2).getValue(); //for destination folder
var files = DriveApp.getFileById(fileId);
var name = files.getName().split('.')[0];
var blob = files.getBlob();
var newFile = {
title: name.replace('_converted','') + '_converted',
parents: [{id: folderID}] };
var destinationFolderId = DriveApp.getFolderById(folderID);
var existingFiles = destinationFolderId.getFilesByName(newFile.title);
while(existingFiles.hasNext()) {
var oldConvertedFileWithSameNameID = existingFiles.next().getId();
Drive.Files.remove(oldConvertedFileWithSameNameID,{supportsAllDrives: true});
}
var newFileID = Drive.Files.insert(newFile, blob, { convert: true,supportsAllDrives: true }).id;
Logger.log(newFileID);
var Url = "https://drive.google.com/open?id=" + newFileID;
//sheet.getRange(r,4).setValue(newFileID);
//sheet.getRange(r,5).setValue(Url);
}
sheet.getRange(i+2,4).setValue(newFileID); //set value in column D
sheet.getRange(i+2,5).setValue(Url); //set value in column E
}
}
}
The error that i am facing is, when i call the method ConvertFiles() inside the if statement, the conversion happens from row 2 until 6 CONTINOUSLY without stopping as shown in sample in red circle.
I only wanted to make conversion on the "NEW FILES" only which will be on row 5 and 6.
How can i make a conversion on the selected/specified row?
It would be more efficient if you obtain all the values in your Sheet, loop the 2D array the getValues() method will return and add an if statement that will only process new files.
Example:
Here in my example below I created a script that will only process rows that have a blank value for the status column.
Code:
function ConvertFiles() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var range = sheet.getRange(2, 1, sheet.getLastRow()-1, 5); // get A2:E6 range
var data = range.getValues(); // get A2:E6 data
/*the content of data is 2D array,
each sub array represent rows in your table*/
for(var i = 0; i < data.length; i++){
if(data[i][2] == ""){ //the 2 in [i][2] represent the value of C column in sheet
//Add your file conversion code here
sheet.getRange(i+2,4).setValue("Test only"); //set value in column D
sheet.getRange(i+2,5).setValue("Test only"); //set value in column E
}
}
}
Data:
Output:
References:
Sheet.getRange(row, column, numRows, numColumns)
Range.getValues()
Range.setValue(value)
EDIT:
The value of data variable in the code below is a 2D array containing all the data in the range provided. In your example, it is the data of A2:E6.
Example output:
[
[fileId1,folderId1,Status1,,],
[fileId2,folderId2,Status2,,],
[fileId3,folderId3,Status3,,],
[fileId4,folderId4,,,],
[fileId5,folderId5,,,],
]
The for loop will access each sub array per iteration and since we already knew the position of our target data (fileID and folderID) we don't need to create another for loop to access it, instead we just specify the index on which the data is located. data[i][0] for file id and data[i][1] for folder id. The if(data[i][2] == "") is added to check if the column C of each row is empty and ignore the one with data.
Code:
function ConvertFiles() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var range = sheet.getRange(2, 1, sheet.getLastRow()-1, 5);
var data = range.getValues();
for(var i = 0; i < data.length; i++){
if(data[i][2] == ""){
var fileId = data[i][0];
var folderID = data[i][1];
var files = DriveApp.getFileById(fileId);
var name = files.getName().split('.')[0];
var blob = files.getBlob();
var newFile = {
title: name.replace('_converted','') + '_converted',
parents: [{id: folderID}] };
var destinationFolderId = DriveApp.getFolderById(folderID);
var existingFiles = destinationFolderId.getFilesByName(newFile.title);
while(existingFiles.hasNext()) {
var oldConvertedFileWithSameNameID = existingFiles.next().getId();
Drive.Files.remove(oldConvertedFileWithSameNameID,{supportsAllDrives: true});
}
var newFileID = Drive.Files.insert(newFile, blob, { convert: true,supportsAllDrives: true }).id;
var Url = "https://drive.google.com/open?id=" + newFileID;
sheet.getRange(i+2,4).setValue(newFileID);
sheet.getRange(i+2,5).setValue(Url);
}
}
}
I am new to Google Sheet scripting.
I am writing a code to strip the sixth components from a long text that is based on a naming convention. The text have 6 parts all separated by an underscore. However, my code is not returning anything
function RetailerStrip(account) {
var count = 0;
var retname = "";
var retcount = 0;
for(var i = 0, len = account.length; i < len; i++) {
if (account[i] =="_") {
++count;
}
if (count == 5) {
retname[retcount]= account[i];
++retcount;
}
}
return retname;
}
I then call this function from sheet as below
=RetailerStrip("abc_def_ghi_jkl_mno_pqr")
When I tried to declare 'retname' as an array the function did return the required text (fifth component) but the text was spread across multiple cells with on character in each cell, and not as a single string in one cell
var retname = [];
Please help
You could try this:
function RetailerStrip(str) { return str.split('_')[5]; }
The split() method creates an array.
But if you prefer to stick with the string-iteration method, you could use this:
function RetailerStrip(account) {
var count = 0;
var retname = []; // Array
var retcount = 0;
for (var i = 0, len = account.length; i < len; i++) {
if (account[i] =="_") {
++count;
}
if (count == 4) {
retname[retcount]= account[i];
++retcount;
}
}
retname.shift(); // To get rid of the underscore from the array
var retnameString = retname.join(''); // To convert the array to a string
return retnameString;
}
In apps script I want to obtain formatted 'number' strings. The input is an unformatted number. With an earlier answer posted by #slandau, I thought I had found a solution by modifying his code (see code snippet). It works in codepen, but not when I am using apps script.
1. Does anyone know what went wrong here?
2. I noticed this code works except when entering a number ending in .0, in that case the return value is also .0 but should be .00. I would like some help fixing that too.
Thanks!
I have tried to look for type coercion issues, but wasn't able to get it down. I am fairly new to coding.
function commaFormatted(amount)
{
var delimiter = ","; // replace comma if desired
var a = amount.split('.', 2);
var preD = a[1]/(Math.pow(10,a[1].length-2));
var d = Math.round(preD);
var i = parseInt(a[0]);
if(isNaN(i)) { return ''; }
var minus = '';
if(i < 0) { minus = '-'; }
i = Math.abs(i);
var n = new String(i);
var a = [];
while(n.length > 3)
{
var nn = n.substr(n.length-3);
a.unshift(nn);
n = n.substr(0,n.length-3);
}
if(n.length > 0) { a.unshift(n); }
n = a.join(delimiter);
if(d.length < 1) { amount = n; }
else { amount = n + '.' + d; }
amount = minus + amount;
return amount;
}
console.log(commaFormatted('100000.3532'))
The expected result would be 100,000.35.
I am getting this in the IDE of codepen, but in GAS IDE is stops at the .split() method => not a function. When converting var a to a string = I am not getting ["100000", "3532"] when logging var a. Instead I am getting 100000 and was expecting 3532.
Based on this answer, your function can be rewritten to
function commaFormatted(amount)
{
var inputAmount;
if (typeof(amount) == 'string') {
inputAmount = amount;
} else if (typeof(amount) == 'float') {
inputAmount = amount.toString();
}
//--- we expect the input amount is a String
// to make is easier, round the decimal part first
var roundedAmount = parseFloat(amount).toFixed(2);
//--- now split it and add the commas
var parts = roundedAmount.split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
console.log(commaFormatted(100000.3532));
console.log(commaFormatted('1234567.3532'));
Below is code I came up with to run a Saved Search in NetSuite using SuiteScript, create a CSV with the Saved Search results and then email the CSV. The trouble is, the results are limited to 1000 records. I've researched this issue and it appears the solution is to run a loop that slices in increments of 1000. A sample of what I believe is used to slice searches is also below.
However, I cannot seem to be able to incorporate the slicing into my code. Can anyone help me combine the slicing code with my original search code?
var search = nlapiSearchRecord('item', 'customsearch219729');
// Creating some array's that will be populated from the saved search results
var content = new Array();
var cells = new Array();
var temp = new Array();
var x = 0;
// Looping through the search Results
for (var i = 0; i < search.length; i++) {
var resultSet = search[i];
// Returns an array of column internal Ids
var columns = resultSet.getAllColumns();
// Looping through each column and assign it to the temp array
for (var y = 0; y <= columns.length; y++) {
temp[y] = resultSet.getValue(columns[y]);
}
// Taking the content of the temp array and assigning it to the Content Array.
content[x] += temp;
// Incrementing the index of the content array
x++;
}
//Inserting headers
content.splice(0, 0, "sku,qty,");
// Creating a string variable that will be used as the CSV Content
var contents;
// Looping through the content array and assigning it to the contents string variable.
for (var z = 0; z < content.length; z++) {
contents += content[z].replace('undefined', '') + '\n';
}
// Creating a csv file and passing the contents string variable.
var file = nlapiCreateFile('InventoryUpdate.csv', 'CSV', contents.replace('undefined', ''));
// Emailing the script.
function SendSSEmail()
{
nlapiSendEmail(768, 5, 'Inventory Update', 'Sending saved search via scheduled script', 'cc#email.com', null, null, file, true, null, 'cc#email.com');
}
The following code is an example of what I found that is used to return more than a 1000 records. Again, as a novice, I can't seem to incorporate the slicing into my original, functioning SuiteScript. Any help is of course greatly appreciated.
var filters = [...];
var columns = [...];
var results = [];
var savedsearch = nlapiCreateSearch( 'customrecord_mybigfatlist', filters, columns );
var resultset = savedsearch.runSearch();
var searchid = 0;
do {
var resultslice = resultset.getResults( searchid, searchid+1000 );
for (var rs in resultslice) {
results.push( resultslice[rs] );
searchid++;
}
} while (resultslice.length >= 1000);
return results;
Try out this one :
function returnCSVFile(){
function escapeCSV(val){
if(!val) return '';
if(!(/[",\s]/).test(val)) return val;
val = val.replace(/"/g, '""');
return '"'+ val + '"';
}
function makeHeader(firstLine){
var cols = firstLine.getAllColumns();
var hdr = [];
cols.forEach(function(c){
var lbl = c.getLabel(); // column must have a custom label to be included.
if(lbl){
hdr.push(escapeCSV(lbl));
}
});
return hdr.join(",");
}
function makeLine(srchRow){
var cols = srchRow.getAllColumns();
var line = [];
cols.forEach(function(c){
if(c.getLabel()){
line.push(escapeCSV(srchRow.getText(c) || srchRow.getValue(c)));
}
});
return line.join(",");
}
function getDLFileName(prefix){
function pad(v){ if(v >= 10) return v; return "0"+v;}
var now = new Date();
return prefix + '-'+ now.getFullYear() + pad(now.getMonth()+1)+ pad(now.getDate()) + pad( now.getHours()) +pad(now.getMinutes()) + ".csv";
}
var srchRows = getItems('item', 'customsearch219729'); //function that returns your saved search results
if(!srchRows) throw nlapiCreateError("SRCH_RESULT", "No results from search");
var fileLines = [makeHeader(srchRows[0])];
srchRows.forEach(function(soLine){
fileLines.push(makeLine(soLine));
});
var file = nlapiCreateFile('InventoryUpdate.csv', 'CSV', fileLines.join('\r\n'));
nlapiSendEmail(768, 5, 'Test csv Mail','csv', null, null, null, file);
}
function getItems(recordType, searchId) {
var savedSearch = nlapiLoadSearch(recordType, searchId);
var resultset = savedSearch.runSearch();
var returnSearchResults = [];
var searchid = 0;
do {
var resultslice = resultset.getResults(searchid, searchid + 1000);
for ( var rs in resultslice) {
returnSearchResults.push(resultslice[rs]);
searchid++;
}
} while (resultslice.length >= 1000);
return returnSearchResults;
}
I looked into your code but it seems you're missing the label headers in the generated CSV file. If you are bound to use your existing code then just replace
var search = nlapiSearchRecord('item', 'customsearch219729');
with
var search = getItems('item', 'customsearch219729');
and just use the mentioned helper function to get rid off the 1000 result limit.
Cheers!
I appreciate it has been a while since this was posted and replied to but for others looking for a more generic response to the original question the following code should suffice:
var search = nlapiLoadSearch('record_type', 'savedsearch_id');
var searchresults = search.runSearch();
var resultIndex = 0;
var resultStep = 1000;
var resultSet;
do {
resultSet = searchresults.getResults(resultIndex, resultIndex + resultStep); // retrieves all possible results up to the 1000 max returned
resultIndex = resultIndex + resultStep; // increment the starting point for the next batch of records
for(var i = 0; !!resultSet && i < resultSet.length; i++){ // loop through the search results
// Your code goes here to work on a the current resultSet (upto 1000 records per pass)
}
} while (resultSet.length > 0)
Also worth mentioning, if your code is going to be updating fields / records / creating records you need to bear in mind script governance.
Moving your code to a scheduled script to process large volumes of records is more efficient and allows you to handle governance.
The following line:
var savedsearch = nlapiCreateSearch( 'customrecord_mybigfatlist', filters, columns );
can be adapted to your own saved search like this:
var savedsearch = nlapiLoadSearch('item', 'customsearch219729');
Hope this helps.
I am not able to get the list of item.I am using a saved search and want to create a list of all the item record id from it.
But it is not working.
my code
var loadSearch=nlapiLoadSearch('item','customsearch12');
var getData = loadSearch.runSearch();
var itemCol=new Array();
for(var i=0;i<getData.length;i++)
{
itemCol.push(getData[i].getId());
}
Can somebody help me with this
try this code
var loadSearch=nlapiLoadSearch('item','customsearch12');
var getData = loadSearch.runSearch();
var itemCol=new Array();
getData.forEachResult(function (searchRow) {
itemCol.push(searchRow.getId());
return true;
});
when you use a nlapiLoadSearch, the result is nlobjSearchResultSet and not an array like in the case of nlapiSearchRecord.
if you use nlapiSearchRecord, then you can loop through the result like you were trying in your code, i.e. using index
The answer given above by Nitish is perfectly correct but you need to consider one more thing.
nlapiLoadSearch api returns 4000 records at a time.
The nlapiSearchRecord api returns only 1000 records at a time , so what if your saved search consists of more than 1000 records.
So you will miss those extra items.
so here is the code to have better results
//Searching the items
var searchResults = nlapiSearchRecord('item', 'customsearch12',null,null);
var searchedItemId;
var lastId;
var completeResults = new Array();
var arrNewFilters=[];
if (searchResults != null) {
completeResults = completeResults.concat(searchResults);
}
else {
completeResults = null;
nlapiLogExecution('Debug', 'No item found',
weight + ' Null result');
}
if (completeResults != null) {
if (searchResults.length == 1000) {
while (searchResults.length == 1000) {
//Initialize variable
lastId = "";
//Get Record Id of Last record,
//to search the item record again from that record
lastId = searchResults[999].getId();
//start after the last id searched
arrNewFilters.push(new nlobjSearchFilter("internalidnumber",
null, "greaterthan", lastId));
//Lets search again
var searchResults = nlapiSearchRecord('item', 'customsearch12',
arrNewFilters, null);
if (searchResults != null) {
//Append the search result to the result present before
completeResults = completeResults.concat(searchResults);
}
}
}
for (var result = 0; result < completeResults.length; result++) {
//Loop through the items
}
Hope you got me Nitish!!!
Here's a sample of how to fetch over 1k of results in NetSuite/NetScript.
The search "customsearch_tel_tg_by_trunk_type" is not really relevant.
Complete sample of 1k+ results fetch in NetSuite/NetScript
You could get all the results one by one using a callback function till all the records are iterated.
var search = nlapiLoadSearch('item','customsearch12');
var resultSet = loadSearch.runSearch();
var itemCol=new Array();
resultSet.forEachResult(function (iterator) {
itemCol.push(iterator.getId());
return true;
});
or you could load few records of it using the getResults of the nlobjResultSet
var search = nlapiLoadSearch('item', 'customsearch12');
var resultSet = search.runSearch();
var results = resultSet.getResults(0, 100);//get the results from 0 to 100 search results
var itemCol = new Array();
for(var i in results)
{
itemCol.push(results[i].getValue('id'));
}