function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Michael MMichael M 

Save VF page with lightningstylesheets as PDF

Hello, I have a VF with lightningstylesheets = "true". (This needs to stay this way-- when I take that away the whole page doesn't look right.) I need to save this VF page as a PDF to my Lead record, from an after update trigger. 

I am seeing that I cannot use renderas="pdf" together with lightningstylesheets="true". 

I am also seeing that when I try to save the page as is as a pdf, it does not work-- the logs say Internal Salesforce.com Error. 

Does anyone have experience with a similar issue? How can I make this work? 

Here is the code I'm using to attach the page (called from a trigger)

@future(callout = true)
public static void generatePdf(Id leadId){
     PageReference pref = Page.SEEK_MVP_PDF_Display;
        pref.getParameters().put('id',leadId);  
        Blob b;
if(Test.isRunningTest()) {
  b = blob.valueOf('Unit.Test');
} else {
   b = pref.getContentaspdf(); 
}
        ContentVersion cv = new ContentVersion();
        cv.versionData = b;
        cv.title = 'SEEK Medicare Eligibility Check';
        cv.PathOnClient = 'SEEK_Eligibility_Check.pdf';
        insert cv;
    
        ContentVersion Content = [SELECT id, ContentDocumentId FROM ContentVersion where Id = :cv.Id];
        ContentDocumentLink contentlink=new ContentDocumentLink();
        contentlink.LinkedEntityId= leadId;
        contentlink.ShareType= 'V';
        contentlink.ContentDocumentId= Content.ContentDocumentId;
        insert contentlink; 

 
Best Answer chosen by Michael M
VinayVinay (Salesforce Developers) 
Hi Michael,

The <apex:slds> component has known issues when creating PDF files from Visualforce pages. For this reason, lightningStyleSheets does not support <apex:page renderAs="pdf"> or calls to PageReference.getContentAsPDF().  You would need to use CSS.

Review below link for more details.

https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/vf_dev_best_practices_slds_lightningstylesheets.htm

Kindly review below Idea and vote for this feature 

https://trailblazer.salesforce.com/ideaView?id=0873A000000U3GIQA0

Hope above information was helpful.

Please mark as Best Answer so that it can help others in the future.

Thanks,
Vinay Kumar

All Answers

VinayVinay (Salesforce Developers) 
Hi Michael,

The <apex:slds> component has known issues when creating PDF files from Visualforce pages. For this reason, lightningStyleSheets does not support <apex:page renderAs="pdf"> or calls to PageReference.getContentAsPDF().  You would need to use CSS.

Review below link for more details.

https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/vf_dev_best_practices_slds_lightningstylesheets.htm

Kindly review below Idea and vote for this feature 

https://trailblazer.salesforce.com/ideaView?id=0873A000000U3GIQA0

Hope above information was helpful.

Please mark as Best Answer so that it can help others in the future.

Thanks,
Vinay Kumar
This was selected as the best answer
Michael MMichael M
Hi Vinay,

In order to use  b = pref.getContentaspdf();  , is it required to use renderAs="pdf" in the VF page? 

Is there any other workaround you can think of? 

Here is basically my page-- what specifically do I need to change, if you don't mind?

<apex:page standardcontroller="Lead" extensions="SEEK_MVP_Extension" lightningStylesheets="true">

   <style>
           body .bPageBlock .pbBody .boldHeader .pbSubheader{
        font-weight:bold;
        background-color:  #b3d9ff;
            }
          .colstyle {width:25%}

    </style>
<apex:pageBlock mode="maindetail" >
<apex:outputPanel styleClass="boldHeader" rendered="{!IF(mspFromDate1 ='',false,true)}">
<apex:pageBlockSection title="MSP" collapsible="false" >
    <div style="width: 100%;">
      <table>
         <tr style= "border-bottom:1px solid #000;">
         <th>Effective</th>
         <th>Terminated</th>
         <th>Policy Number</th>
         <th>Insurer</th>
         <th>Type</th>
         </tr>
   <!--1-->        
         <tr>
         <th>{!mspFromDate1}</th>
         <th>{!mspToDate1}</th>
         <th>{!mspPatientId1}</th>
         <th>{!mspPayerName1}</th>
         <th>{!mspType1}</th>
      </tr> 
         <tr>
         <th></th>
         <th></th>
         <th></th>
         <th>{!mspAddress1}</th>
         <th></th>
      </tr> 
   <!--2-->        
         <tr>
         <th>{!mspFromDate2}</th>
         <th>{!mspToDate2}</th>
         <th>{!mspPatientId2}</th>
         <th>{!mspPayerName2}</th>
         <th>{!mspType2}</th>
      </tr> 
         <tr>
         <th></th>
         <th></th>
         <th></th>
         <th>{!mspAddress2}</th>
         <th></th>
      </tr> 
   <!--3-->        
         <tr>
         <th>{!mspFromDate3}</th>
         <th>{!mspToDate3}</th>
         <th>{!mspPatientId3}</th>
         <th>{!mspPayerName3}</th>
         <th>{!mspType3}</th>
      </tr> 
         <tr>
         <th></th>
         <th></th>
         <th></th>
         <th>{!mspAddress3}</th>
         <th></th>
      </tr> 
  <!--4-->        
         <tr>
         <th>{!mspFromDate4}</th>
         <th>{!mspToDate4}</th>
         <th>{!mspPatientId4}</th>
         <th>{!mspPayerName4}</th>
         <th>{!mspType4}</th>
      </tr> 
         <tr>
         <th></th>
         <th></th>
         <th></th>
         <th>{!mspAddress4}</th>
         <th></th>
      </tr> 
   <!--5-->        
         <tr>
         <th>{!mspFromDate5}</th>
         <th>{!mspToDate5}</th>
         <th>{!mspPatientId5}</th>
         <th>{!mspPayerName5}</th>
         <th>{!mspType5}</th>
      </tr> 
         <tr>
         <th></th>
         <th></th>
         <th></th>
         <th>{!mspAddress5}</th>
         <th></th>
      </tr> 
  <!--6-->        
         <tr>
         <th>{!mspFromDate6}</th>
         <th>{!mspToDate6}</th>
         <th>{!mspPatientId6}</th>
         <th>{!mspPayerName6}</th>
         <th>{!mspType6}</th>
      </tr> 
         <tr>
         <th></th>
         <th></th>
         <th></th>
         <th>{!mspAddress6}</th>
         <th></th>
      </tr> 
      </table>
    </div>
</apex:pageBlockSection>
</apex:outputPanel>  
    <apex:outputPanel style="font-weight:bold">
    {!missingSectionsMessage}
    </apex:outputPanel>

</apex:pageBlock>
</apex:page>
Michael MMichael M
Just a thought- is it possible to use JS to render the page as pdf instead of apex markup? And would that work?
VinayVinay (Salesforce Developers) 
Yes, it is required to use renderAs='pdf' and PDF rendering doesn’t support JavaScript-rendered content.

https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_output_pdf_considerations.htm

Found below examples which has workaround to use render as pdf.

https://www.vermanshul.com/2018/12/lightning-generate-pdf-within-lightning.html
https://medium.com/@ToAnshulVerma/salesforce-lightning-generate-pdf-from-lightning-components-with-in-memory-data-cd5dffe0fe25

Check if you can use PDF.JS library to render pdf.
https://github.com/kumarrk21/PDFViewer

Thanks,
Michael MMichael M
Hi Vinay,

Thanks for the resources. The only thing is it seems those require the user to click on a button to save the file. I need to automatically save this file as a pdf from a trigger.

I see that it is possible to load a VF page in a lightning component. Would that help? Is it possible to then render that lightning component as a blob body and save it as a pdf record?
VinayVinay (Salesforce Developers) 
Yes that should help to load VF page in the lightning component.

https://developer.salesforce.com/forums/?id=9060G0000005WmhQAE
https://gist.github.com/toanshulverma/16244d19ac68364cb75443695d81403b

Thanks,
Michael MMichael M
Thanks! This will be my final questoin on this thread :) ...

I am trying to do it like this:
1. Save my VF page (with lightningstylesheets="true", without renderas="pdf") to lightning component.
2. Save that component to a new VF page with renderas = "pdf". 

I am trying that now but the new VF page is coming up as blank. Am I doing it correct?
Here is the component that gets the first VF page... this works and displays correctly ... this component is called "SEEK_Component"
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId" access="global" >
    <iframe src="{!  'https://centers--partial--c.visualforce.com/apex/SEEK_MVP_PDF_DISPLAY?Id=' + v.recordId }" width="100%" height="500px;" frameBorder="0"/>
</aura:component>

And for the new VF page:
Lightning App (called ""SEEKLightningApp)
<aura:application access="GLOBAL" extends="ltng:outApp" >
    <c:SEEK_Component />
</aura:application>

VF page:

<apex:page standardController="Lead">        
    <apex:includeLightning /> 
    <script>
        $Lightning.use(“c:SEEKLightningApp”, function() {
            $Lightning.createComponent(
                "c:SEEK_Component",
                {},
                function(cmp) {
                    console.log(“Component is created!”);
                    console.log(cmp);
                });
            });        
      </script>
</apex:page>

When I display the new VF page it is empty. What is missing from it? Thanks !!
VinayVinay (Salesforce Developers) 
Sorry for the delay response somehow I missed this.

This will not work using stylesheet in one page and another with renderas,  Try to use visualforce component and that should help or invoke VF from lightning component(haven't tried this).

Thanks,
Michael MMichael M
Thanks-- what would I put in the visualforce component? 
VinayVinay (Salesforce Developers) 
I do not have any sample code to share but you can give a try else you can proceed with button click process considering limitations on lightning for using rederas=pdf.

Thanks,
Michael MMichael M
OK I can try-- what should I put in the visualforce component?