5

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;
Accounting
  • 134
  • 1
  • 8

3 Answers3

9

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!

Rockstar
  • 2,228
  • 3
  • 20
  • 39
  • Rockstar, your answer is a Rockstar! It worked beautifully....thank you so much for time and effort helping me out! So very much appreciated. – Accounting Jul 02 '15 at 00:22
  • @Accounting Glad to know it helped. Cheers!! – Rockstar Jul 02 '15 at 04:53
  • I've encountered a bit of an issue. If the Saved Search is slow to execute, the script errors out and no file is generated. I tuned up the Criteria in my Saved Search to execute more efficiently and the issue is for now resolved. But I fear that it may re-emerge when the Saved Search grows to 1000s of records. Is there any bit of code that can be added to give the SS time to execute before erroring the whole thing out? Thanks in advance for your insight! – Accounting Jul 14 '15 at 08:48
  • I set-up the Deployment to email me errors so I get an email with the error below. I was able to determine it was caused by the Saved Search timing out. Thanks for any thoughts you may have! – Accounting Jul 15 '15 at 12:14
  • Environment: Production Date & Time: 7/13/2015 11:36 pm Execution Time: 0.40s Script Usage: 5 Script: SSEmailScript Type: Scheduled Function: returnCSVFile Error: UNEXPECTED_ERROR Ticket: ic2ujgxd1u8l7evkntq3l Stack Trace: getItems(1000.js$109256:64) returnCSVFile(1000.js$109256:41) – Accounting Jul 15 '15 at 12:16
5

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.

Chris Johnson
  • 20,650
  • 6
  • 81
  • 80
0

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.

dangig
  • 179
  • 7
  • Thanks for your answer. But where/how do I insert the code into my main SuiteScript code? And I'm not sure if that second code snipet even works...I just included it as an example of what I'm able to find on how to generate saved searches over a 1000 records long. Thanks! – Accounting Jun 26 '15 at 18:15
  • Encapsulate the second code snippet in its own function, let's say getAllResults(). Then, replace the first line of your code by: var search = getAllResults(). – dangig Jun 29 '15 at 20:09