How to combine multiple pdf’s into a single pdf file?

I have written a map reduce script to generate and combine multiple pdf’s into a single pdf. My script is generating multiple pdfs properly, but it shows only last pdf in a combined pdf. please help!

 

/**
 * @NApiVersion 2.0
 * @NScriptType MapReduceScript
 */
define([‘N/search’, ‘N/record’, ‘N/runtime’,’N/render’,’N/file’,’N/url’,’N/xml’],
function(search, record, runtime,render,file,url,xml)
{
  function getInputData() {
      try{
        var soIdArray=[];
          // var waveId = runtime.getCurrentScript().getParameter({name: ‘custscriptstandard_wave_id’});
          // log.debug(“waveId”,waveId);
         var waveRecord = record.load({
          type:record.Type.WAVE,
          id: 131830,
          isDynamic: true,
      });
      log.debug(“waveRecord”,waveRecord);
      var totalLines = waveRecord.getLineCount({
          sublistId: ‘waveorders’
      });
      log.debug(“totalLines”,totalLines);
      for(var s=0;s<totalLines;s++)
      {
          var soId= waveRecord.getSublistValue({
              sublistId: ‘waveorders’,
              fieldId: ‘ordernumberid’,
              line: s
          });
          log.debug(“soId–> “,soId);
          soIdArray.push(soId);
        }
        log.debug(“soIdArray”,soIdArray);
           return soIdArray;
            }
      catch(e)
      {
          log.debug(“error in getinput”,e);
      }
  }
 var n=0;
 var pdfFileIds = [];
 function map(context) {
    try {
      log.debug(“map stage executing”);
      log.debug(“context”,context);
      var searchResult = JSON.parse(context.value);
      log.debug(“searchResult”, searchResult);
      var result = {
        internalid: searchResult,
        };
      log.debug(“result”, result);
      var fileId=renderBolPdf (result)
      n += 1;
      // Emit the key-value pair to trigger the reduce function
      context.write({
        key: searchResult, // Use the file ID as the key
        value: fileId,
      });
    } catch (er) {
      log.debug(“error in map”, er);
    }
  }
  function reduce(context) {
    try {
      log.debug(“Reduce stage executing”,context);
       log.debug(‘context.values’,context.values)
       log.debug(‘context.key’,context.key)
       var reduceObj=context.values
     var pdfFile= renderSet (reduceObj,context.key);
     log.debug(‘pdfFile’,pdfFile)
    } catch (er) {
      log.debug(“error in reduce”, er);
    }
  }
  function renderBolPdf (jsonData) {
   log.debug(“json data2–>”,jsonData);
    try {
      var renderer = render.create()
      renderer.setTemplateByScriptId(‘CUSTTMPL_MAP_REDUCE_TEST’);
    log.debug(‘294’,jsonData);
      renderer.addCustomDataSource({
        format: render.DataSource.OBJECT,
        alias: ‘JSON’,
        data: { record: jsonData }
      })
      renderer.addRecord({
        templateName: ‘record’,
        record: record.load({
          type: ‘salesorder’,
          id: jsonData.internalid
        })
      });
     log.debug(‘299′,’299’);
      var bol = renderer.renderAsPdf()
      log.debug(‘302′,’302’);
      log.debug(‘jsonData.internalid–>’,jsonData.internalid);
      bol.folder = 1797
      bol.name = ‘PDF’+jsonData.internalid;
      log.debug(“bol.name”,bol.name);
      bol.isOnline = true
     log.debug(“bol”, bol);
      var fileid = bol.save()
      log.debug(“fileid single”,fileid);
      return fileid
    } catch (error) {
      log.debug(‘error in renderBolPdf’, error)
    }
  }
  function renderSet (opts,jsonData) {
    try {
      //10 x files + 30 + 10(search) –> 95 files combine per custom record
      log.debug(‘inside RenderSet’,opts)
      log.debug(‘inside i_IFInternalId’,jsonData)
      var tpl = [‘<?xml version=”1.0″?>’, ‘<pdfset>’]
      var output = url.resolveDomain({
        hostType: url.HostType.APPLICATION
      })
      opts.forEach(function (id, idx) {
        id = parseInt(id)
        const partFile = file.load({ id: id }) //10 per file
        var pdf_fileURL = xml.escape({ xmlText: partFile.url })
        tpl.push(“<pdf src='” + pdf_fileURL + “‘/>”)
      })
      tpl.push(‘</pdfset>’)
      pdfFinal = render.xmlToPdf({
        xmlString: tpl.join(‘\n’)
      })
      pdfFinal.name = ‘Traveler_PRINT’ + ‘_’+ ‘.pdf’
      pdfFinal.isOnline = true
      pdfFinal.folder = 1797
      var fileId = pdfFinal.save() //20
      log.debug(“fileId”,fileId)
  //     record.submitFields({
  //      type:’itemfulfillment’,
  //      id:parseInt(i_IFInternalId) ,
  //      values: {
  //         custbody_carton_pdf_url:fileId//fileObj.url
  //      }
  //  })
    log.debug(‘fileId renderset’, fileId)
      return fileId
      log.debug(‘fileId renderset’, fileId)
       //10
       pdfFinal = file.load(fileId)
      output = ‘https://’ + output + pdfFinal.url
      return output
    } catch (error) {
      log.debug({
        title: ‘error in renderSet’,
        details: error
      })
    }
  }
       return {
        getInputData: getInputData,
        map: map,
        reduce: reduce
        //summarize: summarize
    };
});
Beginner Asked on November 6, 2023 in SuiteScript.
Add Comment
5 Answer(s)

Hi. What do you see logged on this line:

log.debug("inside RenderSet", opts);

Do you see multiple entries in the array?

Intermediate Answered on November 6, 2023.
Add Comment

I think that means the related data isn’t making its way to the same instance of reduce(). These should be in a single array, right?

Maybe you need to be more specific in this line:

context.write({
  key: searchResult, // Use the file ID as the key
  value: fileId,
});
What do you see logged here:
log.debug(“map stage executing”);
log.debug(“context”,context);
var searchResult = JSON.parse(context.value);
log.debug(“searchResult”, searchResult);
Intermediate Answered on November 6, 2023.
Add Comment

I see [“19032″] and [” 19033″]  logged on

log.debug("inside RenderSet", opts);  which is file id's of 2 pdf files
Beginner Answered on November 6, 2023.
Add Comment

You are correct! If I pass hardcoded combined array then pdf generates properly. But array is going one by one from map stage. how to combine them in reduce stage to pass to for each loop?

I see following in these logs

context–>{“type”:”mapreduce.MapContext”,”isRestarted”:false,”executionNo”:1,”key”:”0″,”value”:”131828″}

searchResult–>131828

context–>{“type”:”mapreduce.MapContext”,”isRestarted”:false,”executionNo”:1,”key”:”1″,”value”:”131829″}

searchResult–>131829

Beginner Answered on November 6, 2023.
Add Comment

Hi,

You want the key here to be something that connects the files together:

context.write({
  key: searchResult, // Use the file ID as the key
  value: fileId,
});

Unless the values are the same, they will end up in separate instances of reduce.

Thanks,

Chris

Intermediate Answered on November 7, 2023.
Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.
  • This site made possible by our sponsors:   Tipalti   Celigo   Become a Sponsor   Become a Sponsor