Does anyone have a script example for render.addSe...
# suitescript
j
Does anyone have a script example for render.addSearchResults() with an advanced pdf template? I've got some unexpected errors, and have been trying everything to get this to work.
s
You are actually running the search first before trying to give it to the renderer, right?
j
Yes
Copy code
var checkSearchObj = search.create({
    		   type: "check",
    		   filters:
    		   [
    		      ["tobeprinted","is","T"], 
    		      "AND", 
    		      ["internalid","anyof",allCheckedIds], 
    		      "AND", 
    		      ["type","anyof","Check"]
    		      
    		   ],
    		   columns:
    		   [
    		      "internalid"
    		   ]
		});
    	
    	var results = checkSearchObj.run().getRange(0,1000);
    	
    	log.debug('results', JSON.stringify(results))
    	
    	var renderer = render.create();
    	renderer.setTemplateById(118);
    	renderer.addSearchResults({
            templateName: 'Checks Account - ',
            searchResult: results
        })
s
Change the template id to a string instead of number
j
Unfortunately that doesn't make a difference
l
Try to remove spaces and hyphen from Template name
j
Also I've tried renderAsPDF and renderAsString then render.xmlToPdf()
@Luiz Morais That's a no go 😞
l
I used to get unexpected errors on rendering PDF with special chars... try to render with just one result to check if the issue is on template or in your data
j
Yeah I've got the filter down to one result, but I'll look through the template to make sure it's not the issue
I've gotten it to finally render and create a pdf with xml.escape, but now it's just displaying the raw xml template as the pdf
👍 1
k
I convert results to an array which allows me to set the column names, and pass them in with addCustomDataSource. Works fine. Let me know if code example would help.
I do render as a string first and have to do some character replacements to get it to render as a PDF.
j
@Kit Vera (she/her) Thanks for your response, I would love a code example. I've been trying to get this to work for ages. When working with a template, does it require you to bring in all the fields as columns in the search? I thought it would let you just pass in the record and fill out the template natively
c
@JacksonP yes -- right now, the only field available to the template is the
internalid
column you've specified as your search result column.
That differs from
TemplateRenderer.addRecord
/help/helpcenter.nl?fid=section_456543212890.html
j
@Clay Roper I really have to specify all the fields for the template then? That kind of sucks
c
If you want to use search results or a custom data source to power a template, then yes, you need to explicitly specify the fields to pass in the results. There's a lot of flexibility from this in terms of saved search formulas for data manipulation outside the template, making the template function as a dumb view. There's also no way for the template to know what results you might be adding to the template -- e.g. formulas, summary results, fields from joined records. For single records, you can use the
addRecord
method and pick up those record fields (and some fields a single join away) within the template.
j
hmm, okay. Thanks so much for your help
👍 1
k
@JacksonP I had a lot of problems getting this to work as expected as well. Here is an adaptation of what is working for us:
Copy code
var folder_id; //the internal ID to save the test HTML file
var allCheckedIds; //The check IDs for search filter

var datasource = {
  lines: [],
  summary: {
    total: 0
  }
};

var checkSearchObj = search.create({
  type: "check",
  filters:
    [
      ["tobeprinted", "is", "T"],
      "AND",
      ["internalid", "anyof", allCheckedIds],
      "AND",
      ["type", "anyof", "Check"]
    ],
  columns:
    [
      search.createColumn({
        name: "internalid",
        label: "id"
      }),
      search.createColumn({
        name: "tranid",
        label: "tranid"
      }),
      search.createColumn({
        name: "amount",
        label: "amount"
      })
    ]
});

checkSearchObj.run().getRange(0, 1000).forEach(function (result) {
  var this_obj = {};
  
  //I use the labels to set the column names to avoid ambiguity when using
  //formulas
  checkSearchObj.columns.forEach(function (col) {
    this_obj[col.label] = result.getValue(col);
  });

  datasource.lines.push(this_obj);
  datasource.summary.total += Number(this_obj.amount);

  return true;
});

//log.debug('transactions.summary', JSON.stringify(transactions.summary));

var renderer = render.create();
renderer.setTemplateByScriptId('CUSTTMPL_MY_TEMPLATE');

renderer.addCustomDataSource({
  format: render.DataSource.OBJECT,
  alias: 'results',
  data: datasource
});

var contents = renderer.renderAsString();
contents = contents.replace(/&([^;]+(?!(?:\\w|;)))/g, '&$1');

//Do this to test the raw output of the file
if (runtime.getCurrentUser().role === 3) {
  var fileObj = file.create({
    name: 'template_merged.html',
    fileType: file.Type.HTMLDOC,
    contents: contents,
    description: 'These are the merged results from ' + (new Date()).toString(),
    encoding: file.Encoding.UTF8,
    folder: folder_id,
    isOnline: true
  });

  fileObj.save();
}

context.response.renderPdf({xmlString: contents});
Can't send the exact code (confidentiality), but this should help get you up and running
j
I'll check it out, thanks!