您可以使用 PDF 生成 Visualforce 页面的可下载、可打印的 PDF 文件 渲染服务。通过更改标签将页面转换为 PDF。
<apex:page>
<apex:page renderAs="pdf">
呈现的 Visualforce 页面 PDF文件要么显示在浏览器中,要么被下载,这取决于 浏览器的设置。具体行为取决于浏览器、版本、 和用户设置,并且不受 Visualforce 的控制。以下页面包含一些帐户详细信息,并以 PDF 格式呈现 文件。
<apex:page standardController="Account" renderAs="pdf">
<apex:stylesheet value="{!URLFOR($Resource.Styles,'pdf.css')}"/>
<h1>Welcome to Universal Samples!</h1>
<p>Thank you, <b><apex:outputText value=" {!Account.Name}"/></b>, for
becoming a new account with Universal Samples.</p>
<p>Your account details are:</p>
<table>
<tr><th>Account Name</th>
<td><apex:outputText value="{!Account.Name}"/></td>
</tr>
<tr><th>Account Rep</th>
<td><apex:outputText value="{!Account.Owner.Name}"/></td>
</tr>
<tr><th>Customer Since</th>
<td><apex:outputText value="{0,date,long}">
<apex:param value="{!Account.CreatedDate}"/>
</apex:outputText></td>
</tr>
</table>
</apex:page>
Visualforce 页面 呈现为 PDF 文件
将 Visualforce 页面渲染为 PDF 格式 顶点
您可以使用 Apex 中的方法将 Visualforce 页面呈现为 PDF 数据。然后使用 Apex 代码将该 PDF 数据转换为电子邮件附件、文档、 喋喋不休的帖子,等等。
PageReference.getContentAsPDF()下面的示例是一个简单的三元素窗体,用于选择帐户和报表 格式,然后将生成的报告发送到指定的电子邮件 地址。
<apex:page title="Account Summary" tabStyle="Account"
controller="PdfEmailerController">
<apex:pageMessages />
<apex:form >
<apex:pageBlock title="Account Summary">
<p>Select a recently modified account to summarize.</p>
<p/>
<apex:pageBlockSection title="Report Format">
<!-- Select account menu -->
<apex:pageBlockSectionItem>
<apex:outputLabel for="selectedAccount" value="Account"/>
<apex:selectList id="selectedAccount" value="{! selectedAccount }"
size="1">
<apex:selectOption /> <!-- blank by default -->
<apex:selectOptions value="{! recentAccounts }" />
</apex:selectList>
</apex:pageBlockSectionItem>
<!-- Select report format menu -->
<apex:pageBlockSectionItem >
<apex:outputLabel for="selectedReport" value="Summary Format"/>
<apex:selectList id="selectedReport" value="{! selectedReport }"
size="1">
<apex:selectOptions value="{! reportFormats }" />
</apex:selectList>
</apex:pageBlockSectionItem>
<!-- Email recipient input field -->
<apex:pageBlockSectionItem >
<apex:outputLabel for="recipientEmail" value="Send To"/>
<apex:inputText value="{! recipientEmail }" size="40"/>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
<apex:pageBlockButtons location="bottom">
<apex:commandButton action="{! sendReport }" value="Send Account Summary" />
</apex:pageBlockButtons>
</apex:pageBlock>
</apex:form>
</apex:page>
此页面是一个简单的用户界面。当您从 Apex 生成 PDF 文件时,所有 该操作位于 Apex 代码中。在此示例中,该代码位于指定为页面的 控制器。
PdfEmailerController
public with sharing class PdfEmailerController {
// Form fields
public Id selectedAccount { get; set; } // Account selected on Visualforce page
public String selectedReport { get; set; } // Report selected
public String recipientEmail { get; set; } // Send to this email
// Action method for the [Send Account Summary] button
public PageReference sendReport() {
// NOTE: Abbreviated error checking to keep the code sample short
// You, of course, would never do this little error checking
if(String.isBlank(this.selectedAccount) || String.isBlank(this.recipientEmail)) {
ApexPages.addMessage(new
ApexPages.Message(ApexPages.Severity.ERROR,
'Errors on the form. Please correct and resubmit.'));
return null; // early out
}
// Get account name for email message strings
Account account = [SELECT Name
FROM Account
WHERE Id = :this.selectedAccount
LIMIT 1];
if(null == account) {
// Got a bogus ID from the form submission
ApexPages.addMessage(new
ApexPages.Message(ApexPages.Severity.ERROR,
'Invalid account. Please correct and resubmit.'));
return null; // early out
}
// Create email
Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
message.setToAddresses(new String[]{ this.recipientEmail });
message.setSubject('Account summary for ' + account.Name);
message.setHtmlBody('Here\'s a summary for the ' + account.Name + ' account.');
// Create PDF
PageReference reportPage =
(PageReference)this.reportPagesIndex.get(this.selectedReport);
reportPage.getParameters().put('id', this.selectedAccount);
Blob reportPdf;
try {
reportPdf = reportPage.getContentAsPDF();
}
catch (Exception e) {
reportPdf = Blob.valueOf(e.getMessage());
}
// Attach PDF to email and send
Messaging.EmailFileAttachment attachment = new Messaging.EmailFileAttachment();
attachment.setContentType('application/pdf');
attachment.setFileName('AccountSummary-' + account.Name + '.pdf');
attachment.setInline(false);
attachment.setBody(reportPdf);
message.setFileAttachments(new Messaging.EmailFileAttachment[]{ attachment });
Messaging.sendEmail(new Messaging.SingleEmailMessage[]{ message });
ApexPages.addMessage(new
ApexPages.Message(ApexPages.Severity.INFO,
'Email sent with PDF attachment to ' + this.recipientEmail));
return null; // Stay on same page, even on success
}
/***** Form Helpers *****/
// Ten recently-touched accounts, for the Account selection menu
public List<SelectOption> recentAccounts {
get {
if(null == recentAccounts){
recentAccounts = new List<SelectOption>();
for(Account acct : [SELECT Id,Name,LastModifiedDate
FROM Account
ORDER BY LastModifiedDate DESC
LIMIT 10]) {
recentAccounts.add(new SelectOption(acct.Id, acct.Name));
}
}
return recentAccounts;
}
set;
}
// List of available reports, for the Summary Format selection menu
public List<SelectOption> reportFormats {
get {
if(null == reportFormats) {
reportFormats = new List<SelectOption>();
for(Map <String,Object> report : reports) {
reportFormats.add(new SelectOption(
(String)report.get('name'), (String)report.get('label')));
}
}
return reportFormats;
}
set;
}
/***** Private Helpers *****/
// List of report templates to make available
// These are just Visualforce pages you might print to PDF
private Map<String,PageReference> reportPagesIndex;
private List<Map<String,Object>> reports {
get {
if(null == reports) {
reports = new List<Map<String,Object>>();
// Add one report to the list of reports
Map<String,Object> simpleReport = new Map<String,Object>();
simpleReport.put('name', 'simple');
simpleReport.put('label', 'Simple');
simpleReport.put('page', Page.ReportAccountSimple);
reports.add(simpleReport);
// Add your own, more complete list of PDF templates here
// Index the page names for the reports
this.reportPagesIndex = new Map<String,PageReference>();
for(Map<String,Object> report : reports) {
this.reportPagesIndex.put(
(String)report.get('name'), (PageReference)report.get('page'));
}
}
return reports;
}
set;
}
}
这个 Apex 控制器在概念上可以分为四个部分。
- 开头的三个公共属性捕获 表单上的三个输入元素。
- 操作方法触发 单击“发送帐户摘要”按钮时。sendReport()
- 两个公共帮助程序属性提供要在两个选择列表中使用的值 input 元素。
- 末尾的私人帮助程序封装了可能的 PDF 报告列表 格式。您可以通过创建 Visualforce 页面来添加自己的报告,然后 在本节中为其添加一个条目。
当 action 方法触发时, 代码执行以下操作。
sendReport()
- 它执行基本的错误检查,以确保表单字段具有 有用的值。注意对于必须 在与真人接触后幸存下来。在生产代码中执行更多 完成表单验证。
- 接下来,它使用所选帐户的值来查找该帐户的名称 帐户。帐户名称用于添加到电子邮件的文本中。 此查找也是进一步验证表单值并确保 选择了真实账户。
- 它使用该类来组合电子邮件,并设置“收件人”、“主题”和“正文”电子邮件 消息值。Messaging.SingleEmailMessage
- 该代码为 选择报表格式,然后在其上设置页面请求参数。这 参数名为“id”,其值设置为所选帐户的 ID。这代表了一个特定的 请求在指定帐户的上下文中访问此页面。调用时, 引用 Visualforce 页面有权访问指定的帐户,并且页面将使用该帐户呈现 帐户的详细信息。PageReferencePageReferencegetContentAsPdf()
- 最后,将 PDF 数据添加到附件中,并将附件添加到 之前创建的电子邮件。然后发送消息。
使用 时, 方法调用的返回类型为 ,其中 代表“二进制大对象”。在 Apex 中,数据类型表示非类型化二进制数据。只有当变量被添加到内容类型为 “application/pdf”,表示二进制数据成为 PDF 文件。PageReference.getContentAsPdf()BlobBlobreportPdfMessaging.EmailFileAttachment
此外,对 的调用是 包裹在块中。如果调用失败, 将希望的 PDF 数据替换为异常消息的版本 发短信。getContentAsPdf()try/catchcatchBlob
将 Visualforce 页面呈现为 PDF 数据在语义上被视为对各种外部服务的标注 原因。原因之一是渲染服务可能以与 外部服务可能会失败。例如,该页面引用了以下外部资源: 不可用。另一个例子是,当页面包含太多数据时,通常在 图像的形式 – 或渲染时间超过限制。因此,在将 Visualforce 页面渲染为 PDF 数据时,请始终将渲染调用包装在一个块中 顶点。getContentAsPdf()try/catch为了完整起见,下面是报告模板页面,该页面由 顶点 法典。
<apex:page showHeader="false" standardStylesheets="false"
standardController="Account">
<!--
This page must be called with an Account ID in the request, e.g.:
https://<salesforceInstance>/apex/ReportAccountSimple?id=001D000000JRBet
-->
<h1>Account Summary for {! Account.Name }</h1>
<table>
<tr><th>Phone</th> <td><apex:outputText value="{! Account.Phone }"/></td></tr>
<tr><th>Fax</th> <td><apex:outputText value="{! Account.Fax }"/></td></tr>
<tr><th>Website</th><td><apex:outputText value="{! Account.Website }"/></td></tr>
</table>
<p><apex:outputText value="{! Account.Description }"/></p>
</apex:page>
使用 Visualforce PDF 渲染时可用的字体
Visualforce PDF 渲染 支持一组有限的字体。要确保 PDF 输出按预期呈现,请使用 支持的字体名称。对于每种字体,列出的第一个名称是 推荐。
font-family
字体 | font-family值 |
---|---|
Arial Unicode MS | Arial Unicode MS |
黑体 | 无衬线无衬线对话 |
次 | 衬线次 |
邮差 | 等宽邮差等宽DialogInput(对话输入) |
注意
- 这些规则适用于服务器端 PDF 呈现。在 Web 浏览器中查看页面 可以有不同的结果。
- 使用此处未列出的值设置样式的文本使用“时间”。例如,如果您使用 单词“Helvetica”,它呈现为 Times,因为这不是 Helvetica 字体。我们建议使用“sans-serif”。
- Arial Unicode MS 是唯一可用的多字节字体。这是唯一一种 为不使用 拉丁字符集。
- Arial Unicode MS 不支持粗体或斜体。font-weight
- 当页面呈现为 PDF 文件时,不支持 Web 字体。你可以使用 Visualforce 页面中的 Web 字体(当它们正常呈现时)。
测试字体呈现
您可以使用以下页面使用 Visualforce PDF 渲染测试字体渲染 发动机。
<apex:page showHeader="false" standardStylesheets="false"
controller="SaveToPDF" renderAs="{! renderAs }">
<apex:form rendered="{! renderAs != 'PDF' }" style="text-align: right; margin: 10px;">
<div><apex:commandLink action="{! print }" value="Save to PDF"/></div>
<hr/>
</apex:form>
<h1>PDF Fonts Test Page</h1>
<p>This text, which has no styles applied, is styled in the default font for the
Visualforce PDF rendering engine.</p>
<p>The fonts available when rendering a page as a PDF are as follows. The first
listed <code>font-family</code> value for each typeface is the recommended choice.</p>
<table border="1" cellpadding="6">
<tr><th>Font Name</th><th>Style <code>font-family</code> Value to Use (Synonyms)</th></tr>
<tr><td><span style="font-family: Arial Unicode MS; font-size: 14pt; ">Arial
Unicode MS</span></td><td><ul>
<li><span style="font-family: Arial Unicode MS; font-size: 14pt;">Arial Unicode MS</span></li>
</ul></td></tr>
<tr><td><span style="font-family: Helvetica; font-size: 14pt;">Helvetica</span></td>
<td><ul>
<li><span style="font-family: sans-serif; font-size: 14pt;">sans-serif</span></li>
<li><span style="font-family: SansSerif; font-size: 14pt;">SansSerif</span></li>
<li><span style="font-family: Dialog; font-size: 14pt;">Dialog</span></li>
</ul></td></tr>
<tr><td><span style="font-family: Times; font-size: 14pt;">Times</span></td><td><ul>
<li><span style="font-family: serif; font-size: 14pt;">serif</span></li>
<li><span style="font-family: Times; font-size: 14pt;">Times</span></li>
</ul></td></tr>
<tr><td><span style="font-family: Courier; font-size: 14pt;">Courier</span></td>
<td><ul>
<li><span style="font-family: monospace; font-size: 14pt;">monospace</span></li>
<li><span style="font-family: Courier; font-size: 14pt;">Courier</span></li>
<li><span style="font-family: Monospaced; font-size: 14pt;">Monospaced</span></li>
<li><span style="font-family: DialogInput; font-size: 14pt;">DialogInput</span></li>
</ul></td></tr>
</table>
<p><strong>Notes:</strong>
<ul>
<li>These rules apply to server-side PDF rendering. You might see different results
when viewing this page in a web browser.</li>
<li>Text styled with any value besides those listed above receives the default font
style, Times. This means that, ironically, while Helvetica's synonyms render as
Helvetica, using "Helvetica" for the font-family style renders as Times.
We recommend using "sans-serif".</li>
<li>Arial Unicode MS is the only multibyte font available, providing support for the
extended character sets of languages that don't use the Latin character set.</li>
</ul>
</p>
</apex:page>
上一页使用以下控制器,该控制器提供了一个简单的“保存到 PDF” 功能。
public with sharing class SaveToPDF {
// Determines whether page is rendered as a PDF or just displayed as HTML
public String renderAs { get; set; }
// Action method to "print" to PDF
public PageReference print() {
renderAs = 'PDF';
return null;
}
}
呈现为 PDF 时的组件行为
了解 Visualforce 如何 组件在转换为 PDF 时的行为对于创建呈现的页面至关重要 井。Visualforce PDF 渲染服务 呈现页面显式提供的静态 HTML 和基本 CSS。通常,不要使用 具有以下特点的组件:
- 依靠 JavaScript 执行操作
- 依赖 Salesforce 风格 床单
- 使用样式表或图形等在页面本身或 静态资源
检查您的 Visualforce 页面 属于这些类别之一,右键单击页面上的任意位置并查看 HTML 源代码。如果 您会看到一个引用 JavaScript 的标记 (.js) 或引用 样式表 (.css),验证生成的 PDF 文件是否显示为 预期。
<script><link>
以 PDF 格式呈现时安全的组件
- <apex:composition>(只要页面包含 PDF 安全组件)
- <apex:dataList>
- <apex:define>
- <apex:facet>
- <apex:include>(只要页面包含 PDF 安全组件)
- <apex:insert>
- <apex:image>
- <apex:outputLabel>
- <apex:outputLink>
- <apex:outputPanel>
- <apex:outputText>
- <apex:page>
- <apex:panelGrid>
- <apex:panelGroup>
- <apex:param>
- <apex:repeat>
- <apex:stylesheet>(只要 URL 不是 直接引用 Salesforce 风格 床单)
- <apex:variable>
以 PDF 格式呈现时要谨慎使用的组件
- <apex:attribute>
- <apex:column>
- <apex:component>
- <apex:componentBody>
- <apex:dataTable>
以 PDF 格式呈现时使用不安全的组件
- <apex:actionFunction>
- <apex:actionPoller>
- <apex:actionRegion>
- <apex:actionStatus>
- <apex:actionSupport>
- <apex:commandButton>
- <apex:commandLink>
- <apex:detail>
- <apex:enhancedList>
- <apex:flash>
- <apex:form>
- <apex:iframe>
- <apex:includeScript>
- <apex:inputCheckbox>
- <apex:inputField>
- <apex:inputFile>
- <apex:inputHidden>
- <apex:inputSecret>
- <apex:inputText>
- <apex:inputTextarea>
- <apex:listViews>
- <apex:message>
- <apex:messages>
- <apex:outputField>
- <apex:pageBlock>
- <apex:pageBlockButtons>
- <apex:pageBlockSection>
- <apex:pageBlockSectionItem>
- <apex:pageBlockTable>
- <apex:pageMessage>
- <apex:pageMessages>
- <apex:panelBar>
- <apex:panelBarItem>
- <apex:relatedList>
- <apex:scontrol>
- <apex:sectionHeader>
- <apex:selectCheckboxes>
- <apex:selectList>
- <apex:selectOption>
- <apex:selectOptions>
- <apex:selectRadio>
- <apex:tab>
- <apex:tabPanel>
- <apex:toolbar>
- <apex:toolbarGroup>