Idea: Page to Print, Page to PDF, Page to Email, Page to Content actions

edited May 20, 2020 in Ideas
I'm sure there are bigger issues the Skuid team is tackling, but I'll continue to post my "practical wish list": It would be neat if there was an action that would convert a Skuid page to PDF/HTML and allow it to be presented for printing, uploaded into content like the Skuid upload component does, or sent through email. Then you could build custom email templates right in Skuid that leverage Skuid models, UI fields, etc... If you build email templates in Salesforce, I can't easily get.... Say a table of my top 5 opportunities that all begin with the letter j and have addresses in Alaska with summary totals of vaious fields displayed in decorative boxes at the top of the template and headers and footers that match my theme. If I could build email/PDF templates in Skuid as regular pages, I could rule the world (I may be exaggerating)
17 votes

Under Consideration · Last Updated


  • Rob HatchRob Hatch 💎💎💎
    edited September 1, 2016
    Yes.  Often discussed.  But every time our devs point out a big bundle of complexity that would have to be resolved.  Definitely on our roadmap, definitely not in the immedate future. 

  • edited October 15, 2019
    As I have said before, it is a lot easier to have the ideas than to build them. I'll keep having ideas. You guys do the hard part! ;)
  • MansourMansour ✭✭✭✭
    edited January 4, 2017
    We've been able to achieve this using DocRaptor
  • edited October 15, 2019
    Awesome! I'll give it a look. Thanks Mansour
  • edited February 25, 2019
    We are taking a look at Doc Raptor thanks to this thread.  Can anyone tell me the basics on how to do it via Skuid?
  • edited June 3, 2016
    Hi Folks,

    The solution Mansour is referring to goes a little something like this:

    1) Sign up for Docraptor and get your API Key

    2) Wrap what you're interested in turning a PDF using the 'Wrapper' component and give it a unique id.

    3) Add a custom Inline Javascript snippet that we'll attach to a button (or some other trigger for that matter)

    var params = arguments[0], $ = skuid.$;

    var downloadPDF = function(url, data, method){
      //url and data options required
      if( url && data ){
        $('<form style="display: none" id="dr_submission" action="' + url
               + '" method="' + (method||'post') + '">'
               + '</form>').appendTo('body');
        $('form#dr_submission').append('<textarea name="user_credentials"></textarea>');
        $('form#dr_submission textarea[name=user_credentials]').val(data.user_credentials);

        //doc values
        for(var key in data.doc) {
          $('form#dr_submission').append('<textarea name="doc['+key+']"></textarea>');
          $('form#dr_submission textarea[name="doc['+key+']"]').val(data.doc[key]);

        //submit the form
        if(confirm("Submit Form")) {$('form#dr_submission').submit().remove(); }

    // setup the string represeting the html we want to submit
    var content = $('#pdf-export').html();

    var data = {
      doc: {
        test: true,
        document_type: 'pdf',
        name: 'test.pdf',
        document_content: content,
        strict: 'none'
      user_credentials: "<DOCRAPTOR API KEY>"

    // this drops a form on the page and submits, which will result in a download dialog popping up
    downloadPDF("";, data);
    4) Run Multiple actions on button click, and trigger the snippet

    5) Preview the page, click your new button and you should be prompted to download the pdf.

    It will likely take a few tries to get the page looking the way you'd like, so keep at it. If the styles aren't showing up, it means that Docraptor can't access the .css and you'll have to inject the stylesheet directly into the 'content' variable you send over. Fortunately you can set 'test: true,' (See the bolded above) and not incur an costs while you tweak it.

  • edited February 25, 2019
    Thank you very much! Have it working.

    FYI - I had to chnage the last line of code to:
    downloadPDF("", data);
    That semicolon in there was throwing an error.

    Question - had any success attaching the prodcued pdf back to a record in salesfroce (easily/automatically)?

    Thank you,
  • edited June 3, 2016
    I was actually just able to get that working with Zapier a few days ago. Some issues arise with the asynchronous nature of the generation that has spotty results. I'm actually currently discussing a ticket with them.
  • edited December 6, 2016
    One more question for the docraptor experts.... How do I get local css on my page?  I use a skuid custom theme, and I opened the static resource and see all the files in the zip.  I opened the skuidtheme file and copied all the text into a new css resource on my document skuid page, and then applied the css to my wrapper that is the content for my document.  It didn't work.  :(  Am I close, or what else can I do to "send css to docraptor?"

  • edited March 11, 2017
    Hi Chandra,

    You can inject the css from a different location with an 'Inline' Javascript snippet like this:
    (function(skuid){  var $ = skuid.$;  $(document.body).one('pageload',function(){      //Change the static resource to the org's static resource location TODO: Dynamically set this              $.when($.get("/resource/###############/<THEME_NAME>/skuidtheme.css"))             .done(function(response) {                 // Create style tag to inject                 var style = $('<style />');                 style.append(response);                 //inject it into the page                 style.appendTo($('#pdf-export'));             });  }); })(skuid);
  • edited December 6, 2016
    Henry - this worked perfectly.  Thank so much!  Please tell me you are going to Dreamforce or something, and I will buy you a beer or 12.  

    Last question (haha).... I have a record detail page and want my user to click the "print doc" button.  The document layout (in my pdf wrapper) is not the same as the detail page.  I don't want the user to see the wrapper/pdf but if I hide it with conditional rendering, then the pdf ends up blank.  What do you do with your wrapper/pdf on your detail page so it loads on your page, but the users don't see it?
  • edited June 10, 2016
    Chandra if I find myself in San Fransisco for Dreamforce I'll certainly take you up on the beer offering!

    As for hiding your print button, you can either put the button outside of the wrapper of id 'pdf-export' or do the following.

    1) Create a UI only checkbox called 'hideprintbutton' or something like that.
    2) Put a render condition on the button on the 'hideprintbutton' being true.
    3) Then perform the following 'multiple actions' on the button click:


    We currently perform the latter option and it works very nicely. Hope this does the trick for you too!

  • edited December 6, 2016
    Worked again!!  :)))
  • edited December 6, 2016
    New problem - page loading in the skuidtheme.css has caused this portion of the Theme to apply to my whole page, so that means my pages are missing the skuidicon.css portion of the Theme.  So no icons on my page.  :(

    I moved this problem to a more detail new thread here:
  • edited December 4, 2019
  • Jack SanfordJack Sanford San Antonio, TX 💎💎
    edited October 15, 2019
    so, yeah #Mansourisagenius. DocRaptor is pretty amazing too. I've been implementing this today, and their tech support said that the above snippet I was using was old, that they've got a JS library now, so it's better to reference that. 

    So, step 1, create an external snippet with this url:
    (or download that and upload as a static resource)

    step 2, create an new snippet, remove all the standard code skuid adds in, then use this:
    function downloadPDF() {        DocRaptor.createAndDownloadDoc("YOUR_API_KEY_HERE", {                    test: true,          document_type: 'pdf',          name: 'test.pdf',          document_content: document.querySelector('#pdf-export').innerHTML,          strict: 'none',          javascript: 'true',          prince_options: {  // if you want relative links to work              baseurl: 'YOUR_SALESFORCE_BASE_URL'          }        });  }     downloadPDF();
    Everything else about the inlineJS to append your them to the wrapper is key, as is naming your wrapper with a unique id "pdf-export". 

    also, in the inlineJS to append the theme css, you can add extra styles. for example, I had trouble adding the docrapter-specific @page selector to my theme (that controls landscape vs. portrait, and other page sizes), so I added it directly in the inlineJS, as such:
     var style2 = $('<style> @page { size : US-Legal landscape } </style>');
  • edited September 26, 2017
    Great stuff!  We have several doc raptor docs incorporated into our skuid processes.  I did a new one this morning using the new DocRaptor library.  Worked great!

    Thanks for the update on this!
  • Jack SanfordJack Sanford San Antonio, TX 💎💎
    edited September 26, 2017
    You're welcome Chandra! Thank YOU for all the formatting tips you shared. Any chance you could share the apex code you used to grab the document that DocRaptor created and attach it back to a record in Salesforce? Did you have to run the async call to DocRaptor and get the callback_url?
  • edited September 26, 2017
    ok, here we go.  First, the apex class which is generic and will attach to any record id that you pass it.  So we use this class for lots of objects.
    ---       Program Name          : AFLattachAsPDF
    ---       Program Description   : This APEX class attaches pdf documents from given url
    ---                               to the record specified.
    ---       Date Written          :  25-Jun-2016
    global class AFLattachAsPDF{
        webservice static void attachAsPDF(string downloadURL, ID theId, string theName){
            Http h = new Http();
            HttpRequest req = new HttpRequest();
            string theURL = downloadURL;
            //another example would be 'image/jpeg'
            req.setHeader('Content-Type', 'application/pdf');
            HttpResponse res = null;
            res = h.send(req);
            //next three lines for dealing with error situations
            //string responseValue = '';
            //responseValue = res.getBody();
            //system.debug('Response Body for File: ' + responseValue);
            blob thePDF = res.getBodyAsBlob();
            Attachment attachment = new Attachment();
            attachment.Body = thePDF;
            attachment.Name = theName + '.pdf';
            attachment.ContentType = 'application/pdf';
            attachment.ParentId = theId;
          insert attachment;

    Then, the Skuid snippet that runs.  It has the DocRaptor call, brings in our special custom Skuid theme that we use just for documents, polls docraptor checking for completion of the pdf, creates a document name and passes all the info to the apex class (the url exposed by DocRaptor, the Id to attach the pdf to and the document name you want.)

    This example is from our Quote page where the user clicks a button which calls the document skuid page in a pop up window, and this snippet runs on page load.  Once the document is done, the window closes and poof the pdf is attached to the quote.

    var params = arguments[0],
    $ = skuid.$;

    var quoteModel = skuid.model.getModel('quote');
    var quoteRow = quoteModel.getFirstRow();
    var quoteNum = quoteModel.getFieldValue(quoteRow,'Name');
    var quoteRev = quoteModel.getFieldValue(quoteRow, 'Quote_Revision__c');
    var docName = quoteNum + 'R' + quoteRev;
    var docURL;

    // pull in the Skuid theme to apply to the page
       // Create style tag to inject
       var style = $('<style />');
       // apply a custom border to a dynamically created table
       style.append('table, th, td {border: 1px solid black;border-collapse: collapse;padding: 1px;text-align: left;}thead {background-color: #000000;color: #FFFFFF;}');

       //inject it into the page
        function checkDocumentStatus(id){ 
               $('.status span').html('Polling...'); 
                 type: 'GET', 
                 url: ''+id
                 dataType: 'JSON', 
                 beforeSend: function(req) { 
                     req.setRequestHeader('Authorization', 'Basic ' + btoa('YOUR ACCESS CODE')); 
                 success: function(data){ 
                   if(data.status == 'queued' || data.status == "working"){ 
                     // wait 1 second, check again 
                     setTimeout(checkDocumentStatus, 1000, id); 
                   }else if(data.status == 'completed'){ 
                     $('.status span').html('Completed'); 
                     $('.url span').html(data.download_url);
                     docURL = data.download_url;
                        var attName = quoteModel.getFieldValue(quoteRow, 'Name') + 'R' + quoteModel.getFieldValue(quoteRow, 'Quote_Revision__c');
                        var result = sforce.apex.execute('AFLattachAsPDF', 'attachAsPDF', {downloadURL: docURL, theId: quoteModel.getFieldValue(quoteRow, 'Id'), theName: attName});
                     //window.prompt('Download URL', data.download_url); 
                     $('.status span').html(data.status);
        function makeDocument(content){ 
               $('.status span').html('Requested'); 
               content = content || '<html></html>'; 
                 type: 'POST', 
                 url: '', 
                 data: JSON.stringify({ 
                   'type': 'pdf', 
                   'document_content': content, 
                   'name': docName, 
                   //'test': true, 
                   'async': true,
                   //'pipeline': 6,
                   'prince_options': {
                        'media': 'print',
                        'owner_password': quoteNum,
                        'disallow_modify': true,
                        'encrypt': true,
                        'key_bits': '128'
                 contentType: 'application/json', 
                 dataType: 'json', 
                 beforeSend: function(req) { 
                     req.setRequestHeader('Authorization', 'Basic ' + btoa('YOUR ACCESS CODE')); 
                 // upon success of the ajax request 
                 success: function(data){ 
                   $('.status span').html('request made'); 
        // setup the string represeting the html we want to submit
        var content = $('#pdf-export').html();


  • edited September 26, 2017
    Wow! Awesome... thanks for sharing!
  • edited December 4, 2019
    Hi everyone, I'm a member of the DocRaptor support team and just stumbled across this. Thanks for sharing this info, Henry. If anyone needs assistance with DocRaptor, please don't hesitate to reply to me here or contact [email protected] Thanks!
  • Jack SanfordJack Sanford San Antonio, TX 💎💎
    edited February 20, 2018
    Hi James, thanks for finding us. I was just reading a bit about Domains on the DocRaptor site. Seems like this could make implementation within skuid even easier, just create a link on a skuid page with the right query parameters. Also keeps it more secure because you don't have to put your api key into a js snippet. 

    However, i've been unable to get this to work with some minor tests. I was wondering if, given some of the examples people have shown above, you could give us an expanded example of how to use the domains feature?

    I've already gone through the documentation here: 
  • edited February 20, 2018
    Jack - we saw this as well, although our stuff is on auto-pilot so we did not go back and update it.  The only change we made since my old posts is to have the apex insert the returned pdf as a File instead of an attachment, since we have now moved our org off of notes and attachments.
  • edited February 20, 2018
    Jack, could you send [email protected] your code and what URL the code is being tested on? 

    The examples included on the documentation page already are as advanced as the code gets, from a code perspective. It's mainly a matter of troubleshooting any domain vs referrer problems (not all websites all the sending of referrers, for example).
  • edited June 28, 2018
    I wanted to follow up on this topic as I now have a much better understanding of how Skuid works. I don't think DocRaptor's Referrer Based system will work for Skuid users because it requires that the page to be converted by public (not secured behind a login and password). I'm working on better documenting the process for adding DocRaptor to your Skuid app and hope to have a streamlined guide for that shortly (mainly drawn from Chandra's code above).
  • David ForderDavid Forder ✭✭
    edited August 1, 2019
    A quick question.. I have the docraptor solution working but we have attachments (photos) that we would like to render in the document. They appear on the screen but not the pdf?

    Anyone else sorted this one out? 
  • David ForderDavid Forder ✭✭
    edited December 4, 2019
    Hi James.. We have the docraptor solution working to generate a pdf for a report but we have files attached (photos) that we would like to render in the document. They appear on the screen but not the pdf? Any assistance would be greatly appreciated
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!