一:基礎設置
Salesforce中的PDF頁面本質上還是Visualforce[簡稱VF]頁面,所以只需要給VF頁面加上一個屬性[renderAs="pdf"] 即可生成一個PDF頁面
1 <apex:page renderAs="pdf">
2 this is a Visualforce page!!! 這是一個VF頁面
3 </apex:page>
預覽頁面,可以看到生成了一個PDF頁面,但是只顯示了英文,涉及的中文字體都沒有出現
對於中文,在PDF中,需要設置font-family: Arial Unicode MS;才能顯示中文字體。
添加上屬性
1 body { 2 font-family: Arial Unicode MS; 3 font-size:14px; 4 font-weight:200; 5 }
此時還需要額外設置幾個屬性,applyHtmlTag="false" applyBodyTag="false" showheader="false"
原因是Salesforce對自己的頁面做了相當程度的封裝,所以在這樣的全部都是自定義的情況下,設置上面的屬性將VF自帶的樣式關閉,此時預覽頁面
可以看到中文的正常顯示。需要注意的,PDF頁面不支持JS,不支持文字的加粗,只能通過文字的字號大小進行區分。
我們來看一個基本的PDF頁面模板
1 <apex:page renderAs="pdf" showheader="false" standardstylesheets="false" applyBodyTag="false" applyHtmlTag="false" contentType="text/html; charset=UTF-8"> 2 <html> 3 <head> 4 <style> 5 body { 6 font-family: Arial Unicode MS; 7 font-size:14px; 8 font-weight:200; 9 } 10 </style> 11 </head> 12 this is a Visualforce page!!! 這是一個VF頁面 13 <!-- 輸入你想要的頁面內容 --> 14 </html> 15 </apex:page>
二:頁眉和頁腳
經常需要使用的PDF頁面內容肯定包括頁眉和頁腳的顯示設置,下面用一個demo進行示范
1 @page { 2 @top-center { 3 content: element(header); 4 } 5 @bottom-left { 6 content: element(footer); 7 } 8 } 9 div.header { 10 display: block; 11 height: 20px; 12 position: running(header); 13 } 14 div.footer { 15 display: block; 16 padding: 5px; 17 position: running(footer); 18 } 19 .pagenumber:before { 20 content: counter(page); 21 } 22 .pagecount:before { 23 content: counter(pages); 24 }
頁眉頁腳對應的頁面代碼如下
1 <!-- 設置頁眉和頁腳 --> 2 <!-- 頁眉 --> 3 <div class="header" style="border-bottom: 1px solid #ccc"> 4 <div> 5 <img src="{!$Resource.Logo}" style="display: block;height: 20px;float:left;" /> 6 <div style="float:left;"> 7 <span style="font-size:12px;color: #808080;"> https://www.cnblogs.com/</span> 8 <span style="font-size:12px;"> 9 <span style="color: #808080;"> 博客地址:</span> 10 https://www.cnblogs.com/luqinghua/ 11 </span> 12 </div> 13 <div style="clear: both;"></div> 14 </div> 15 </div> 16 <!-- 頁腳 --> 17 <div class="footer"> 18 <div style="text-align: center;"> Page <span class="pagenumber"/>/<span class="pagecount"/></div> 19 <div style="border-top: 1px solid #ccc;text-align: center;"> 20 <span style="font-size:12px;color: #808080;"> ADD:Salesforce開發整理[八]</span> 21 <span style="font-size:12px;color: #808080;"> TEL: 152-0721-6593</span> 22 <span style="font-size:12px;color: #808080;"> EMAIL: luqinghua621@gmail.com</span> 23 </div> 24 </div>
頁面預覽效果
三:中文自動換行
在PDF上換行,如果是前端可以使用<br/> 強制換行,或者文字內使用 換行,但是經常會有傳遞的中文參數,如果長度超出的情況下,需要自動換行的情況,此時我們可以在后台將中文字符串轉換成一個字符串的集合,再在前端頁面輸出,此時可以看到自動換行的效果。
后台控制器代碼
1 public with sharing class PrintPDFController { 2 public List<String> list_Name{get;set;} // PDF標題 3 public PrintPDFController() { 4 String CompanyName = '公司名稱特別長超出你需要限制的長度比如15個字公司名稱特別長超出你' 5 + '需要限制的長度比如15個字公司名稱特別長超出你需要限制的長度比如15' 6 + '個字公司名稱特別長超出你需要限制的長度比如15個字'; 7 list_Name = spliteStringToList(CompanyName); 8 } 9 10 11 public List<String> spliteStringToList(String field){ 12 List<String> StringList = new List<String>(); 13 for(integer i = 0 ; i < field.length(); i++){ 14 StringList.add(field.Substring(i,i+1)); 15 } 16 return StringList; 17 } 18 }
前端輸出
1 <apex:repeat value="{!list_Name}" var="name"><apex:outputText value="{!name}"/><textarea/></apex:repeat>
可以看到前端的預覽
所有的超出頁面長度顯示的中文都會自動換行顯示
四:保留系統中的長文本字段樣式輸出
打印系統中的長文本字段時需要保留原本的樣式進行輸出,譬如在業務機會上的描述里面寫這樣的格式信息,在后台獲取並輸出
后台控制器代碼
1 public with sharing class PrintPDFController { 2 public Integer Index{get;set;} 3 public List<String> IndexList{get;set;} 4 public List<List<List<String>>> ContentList{get;set;} 5 public Map<String,List<List<String>>> ContentMap{get;set;} 6 7 public PrintPDFController() { 8 Opportunity opp = [ SELECT 9 Id, 10 Description 11 FROM 12 Opportunity 13 WHERE 14 Id =:'0066F00000sAyL1QAK' Limit 1]; 15 Index = 0; 16 IndexList = new List<String>(); 17 ContentList = new List<List<List<String>>>(); 18 ContentMap = new Map<String,List<List<String>>>(); 19 spliteString(opp.Description); 20 } 21 public void spliteString(String s){ 22 Index++; 23 IndexList.add(String.valueOf(Index)); 24 List<String> str = s.split('\n'); 25 List<String> str_temp; 26 List<List<String>> sTable = new List<List<String>>(); 27 for(String tr:str){ 28 str_temp = new List<String>(); 29 for(Integer i=0;i<tr.length();i++){ 30 str_temp.add(tr.subString(i,i+1)); 31 } 32 sTable.add(str_temp); 33 } 34 ContentList.add(sTable); 35 ContentMap.put(String.valueOf(Index),sTable); 36 } 37 }
前端代碼
1 <div> 2 <h3>業務機會描述</h3> 3 <div> 4 <table> 5 <apex:repeat value="{!IndexList}" var="index"> 6 <tr style="border:0px"> 7 <td width="90%" style="border:0px;font-size:13px;"> 8 <apex:repeat value="{!ContentMap[index]}" var="contentList"> 9 <apex:repeat value="{!contentList}" var="con">{!con}<textarea/></apex:repeat> 10 <br/> 11 </apex:repeat> 12 </td> 13 </tr> 14 </apex:repeat> 15 </table> 16 </div> 17 </div>
預覽頁面效果
五:小技巧匯總
最后記錄幾個小技巧:
1、控制PDF某一區域作為一個整體不能被分頁切割,使用 page-break-inside:avoid; ,可用於div,span,table,tr,td等一切你想要要保持在同一個頁面顯示的內容;
2、與之相對的就是強制換頁使用:<P style='page-break-after:always'> </P> ,類似WORD中的分頁符,缺點是其本身也占有一行。
3、PDF頁面不支持Javascript的使用,對於某些條件限制的需求,可以使用IF作為判斷,比如
value="{!IF(ord.Deals__c=='01-標准','■','□')}"
或者 用於style元素中控制樣式的顯示
style="{!IF(pi.Company__c!="幾米",'display:none;','width:100%;')}"
4、VF頁面時間格式化
<apex:outputText value="{0, date, yyyy-MM-dd}"> <apex:param value="{!con.PlanStartDate__c}" /> </apex:outputText>
如有錯漏,歡迎指正,有問題可以在評論區留言,大家共同進步。
----------------------------------------------------- end -----------------------------------------------
最后貼上本文使用的demo頁面源碼
后台控制器:PrintPDFController
1 public with sharing class PrintPDFController { 2 public List<String> list_Name{get;set;} // PDF標題 3 4 public Integer Index{get;set;} 5 public List<String> IndexList{get;set;} 6 public List<List<List<String>>> ContentList{get;set;} 7 public Map<String,List<List<String>>> ContentMap{get;set;} 8 9 public PrintPDFController() { 10 String CompanyName = '公司名稱特別長超出你需要限制的長度比如15個字公司名稱特別長超出你' 11 + '需要限制的長度比如15個字公司名稱特別長超出你需要限制的長度比如15' 12 + '個字公司名稱特別長超出你需要限制的長度比如15個字'; 13 list_Name = spliteStringToList(CompanyName); 14 15 Opportunity opp = [ SELECT 16 Id, 17 Description 18 FROM 19 Opportunity 20 WHERE 21 Id =:'0066F00000sAyL1QAK' Limit 1]; 22 23 Index = 0; 24 IndexList = new List<String>(); 25 ContentList = new List<List<List<String>>>(); 26 ContentMap = new Map<String,List<List<String>>>(); 27 28 spliteString(opp.Description); 29 } 30 31 32 public List<String> spliteStringToList(String field){ 33 List<String> StringList = new List<String>(); 34 for(integer i = 0 ; i < field.length(); i++){ 35 StringList.add(field.Substring(i,i+1)); 36 } 37 return StringList; 38 } 39 40 public void spliteString(String s){ 41 Index++; 42 IndexList.add(String.valueOf(Index)); 43 List<String> str = s.split('\n'); 44 List<String> str_temp; 45 List<List<String>> sTable = new List<List<String>>(); 46 for(String tr:str){ 47 str_temp = new List<String>(); 48 for(Integer i=0;i<tr.length();i++){ 49 str_temp.add(tr.subString(i,i+1)); 50 } 51 sTable.add(str_temp); 52 } 53 ContentList.add(sTable); 54 ContentMap.put(String.valueOf(Index),sTable); 55 } 56 }
前端VF頁面
1 <apex:page renderAs="pdf" showheader="false" standardstylesheets="false" applyBodyTag="false" applyHtmlTag="false" contentType="text/html; charset=UTF-8" controller="PrintPDFController"> 2 <html> 3 <head> 4 <style> 5 body { 6 font-family: Arial Unicode MS; 7 font-size:14px; 8 font-weight:200; 9 } 10 @page { 11 @top-center { 12 content: element(header); 13 } 14 @bottom-left { 15 content: element(footer); 16 } 17 } 18 div.header { 19 display: block; 20 height: 20px; 21 position: running(header); 22 } 23 div.footer { 24 display: block; 25 padding: 5px; 26 position: running(footer); 27 } 28 .pagenumber:before { 29 content: counter(page); 30 } 31 .pagecount:before { 32 content: counter(pages); 33 } 34 </style> 35 </head> 36 this is a Visualforce page!!! 這是一個VF頁面 37 <br/> 38 <!-- 輸入你想要的頁面內容 --> 39 <apex:repeat value="{!list_Name}" var="name"><apex:outputText value="{!name}"/><textarea/></apex:repeat> 40 <br/> 41 42 <div> 43 <h3>業務機會描述</h3> 44 <div> 45 <table> 46 <apex:repeat value="{!IndexList}" var="index"> 47 <tr style="border:0px"> 48 <td width="90%" style="border:0px;font-size:13px;"> 49 <apex:repeat value="{!ContentMap[index]}" var="contentList"> 50 <apex:repeat value="{!contentList}" var="con">{!con}<textarea/></apex:repeat> 51 <br/> 52 </apex:repeat> 53 </td> 54 </tr> 55 </apex:repeat> 56 </table> 57 </div> 58 </div> 59 60 <!-- 設置頁眉和頁腳 --> 61 <!-- 頁眉 --> 62 <div class="header" style="border-bottom: 1px solid #ccc"> 63 <div> 64 <img src="{!$Resource.Logo}" style="display: block;height: 20px;float:left;" /> 65 <div style="float:left;"> 66 <span style="font-size:12px;color: #808080;"> https://www.cnblogs.com/</span> 67 <span style="font-size:12px;"> 68 <span style="color: #808080;"> 博客地址:</span> 69 https://www.cnblogs.com/luqinghua/ 70 </span> 71 </div> 72 <div style="clear: both;"></div> 73 </div> 74 </div> 75 <!-- 頁腳 --> 76 <div class="footer"> 77 <div style="text-align: center;"> Page <span class="pagenumber"/>/<span class="pagecount"/></div> 78 <div style="border-top: 1px solid #ccc;text-align: center;"> 79 <span style="font-size:12px;color: #808080;"> ADD:Salesforce開發整理[八]</span> 80 <span style="font-size:12px;color: #808080;"> TEL: 152-0721-6593</span> 81 <span style="font-size:12px;color: #808080;"> EMAIL: luqinghua621@gmail.com</span> 82 </div> 83 </div> 84 </html> 85 </apex:page>