Salesforce PDF打印

一:基础设置

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;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;https://www.cnblogs.com/</span>
 8             <span style="font-size:12px;">
 9                 <span style="color: #808080;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;博客地址:</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;">&nbsp;&nbsp;&nbsp;&nbsp;ADD:Salesforce开发整理[八]</span>
21         <span style="font-size:12px;color: #808080;">&nbsp;&nbsp;&nbsp;&nbsp;TEL: 152-0721-6593</span>
22         <span style="font-size:12px;color: #808080;">&nbsp;&nbsp;&nbsp;&nbsp;EMAIL: luqinghua621@gmail.com</span>
23     </div>
24 </div>

页面预览效果

三:中文自动换行

在PDF上换行,如果是前端可以使用<br/> 强制换行,或者文字内使用&#10;换行,但是经常会有传递的中文参数,如果长度超出的情况下,需要自动换行的情况,此时我们可以在后台将中文字符串转换成一个字符串的集合,再在前端页面输出,此时可以看到自动换行的效果。

后台控制器代码

 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'>&nbsp;</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;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;https://www.cnblogs.com/</span>
67                 <span style="font-size:12px;">
68                     <span style="color: #808080;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;博客地址:</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;">&nbsp;&nbsp;&nbsp;&nbsp;ADD:Salesforce开发整理[八]</span>
80             <span style="font-size:12px;color: #808080;">&nbsp;&nbsp;&nbsp;&nbsp;TEL: 152-0721-6593</span>
81             <span style="font-size:12px;color: #808080;">&nbsp;&nbsp;&nbsp;&nbsp;EMAIL: luqinghua621@gmail.com</span>
82         </div>
83     </div>
84  </html>
85 </apex:page>

 

posted @ 2018-07-17 23:19  Ricardo.M.Lu  阅读(2991)  评论(4编辑  收藏  举报