Visualforce-邮件模板(4)控制器

Visualforce电子邮件模板可以利用自定义控制器呈现高度自定义的内容为此,请在使用该自定义控制器的Visualforce电子邮件模板中包含自定义组件。
例如,假设您想在电子邮件模板中显示以单词“Smith”开头的所有客户的列表。为此,首先编写一个使用SOSL调用的自定义控制器,以返回以“Smith”开头的客户列表:

public class findSmithAccounts {
private final List<Account> accounts;
public findSmithAccounts() {
accounts = [select Name from Account where Name LIKE ‘Smith_%’];
}
public List<Account> getSmithAccounts() {
return accounts;
}
}

接下来,创建一个名为smithAccounts的自定义组件,该组件使用此控制器:

<apex:component controller=”findSmithAccounts” access=”global”>
<apex:dataTable value=”{!SmithAccounts}” var=”s_account”>
<apex:column>
<apex:facet name=”header”>Account Name</apex:facet>
{!s_account.Name}
</apex:column>
</apex:dataTable>
</apex:component>

提示:请记住,Visualforce电子邮件模板中使用的所有自定义组件必须具有全局访问级别。
最后,创建一个包含smithAccounts组件的Visualforce电子邮件模板:

<messaging:emailTemplate subject=”Embedding Apex Code” recipientType=”Contact”
relatedToType=”Opportunity”>
<messaging:htmlEmailBody>
<p>As you requested, here’s a list of all our Smith accounts:</p>
<c:smithAccounts/>
<p>Hope this helps with the {!relatedToType}.</p>
</messaging:htmlEmailBody>
</messaging:emailTemplate>

请注意,尽管emailTemplate组件需要relatedToType属性,但它对此示例没有任何影响。它具有“机会”的价值只是为了表明它可以采用与自定义组件中使用的对象不同的对象值。

注意:

如果您的电子邮件模板使用标准控制器,则强制共享设置。如果用户对象的组织范围默认设置为“私人”,并且您需要访问Visualforce电子邮件模板中的用户信息(如姓名和电子邮件地址),则可以使用带有不共享关键字的自定义组件或自定义控制器。
有关共享用户对象的信息,请参阅Salesforce联机帮助中的用户共享概述。

Visualforce-邮件模板(3)附件

您可以将附件添加到Visualforce电子邮件模板。每个附件必须封装在一个<messaging:attachment>组件中。 <messaging:attachment>中的代码可以是HTML和Visualforce标签的组合。
前面的示例显示了如何通过遍历一些数据并将其显示给电子邮件收件人来创建Visualforce电子邮件模板。此示例显示如何修改该标记以将数据显示为附件:

<messaging:emailTemplate recipientType=”Contact”
relatedToType=”Account”
subject=”Case report for Account: {!relatedTo.name}”
replyTo=”support@acme.com”>
<messaging:htmlEmailBody>
<html>
<body>
<p>Dear {!recipient.name},</p>
<p>Attached is a list of cases related to {!relatedTo.name}.</p>
<center>
<apex:outputLink value=”http://www.salesforce.com”>
For more detailed information login to Salesforce.com
</apex:outputLink>
</center>
</body>
</html>
</messaging:htmlEmailBody>
<messaging:attachment>
<apex:repeat var=”cx” value=”{!relatedTo.Cases}”>
Case Number: {!cx.CaseNumber}
Origin: {!cx.Origin}
Creator Email: {!cx.Contact.email}
Case Number: {!cx.Status}
</apex:repeat>
</messaging:attachment>
</messaging:emailTemplate>

这个标记在电子邮件中作为附加的数据文件呈现,没有任何格式。您可以使用以下选项之一以更易读的格式显示数据:

更改文件名

<messaging:attachment>标记具有一个名为filename的属性,用于定义附加文件的名称。定义一个容易识别的名字是一个好习惯,但这不是必需的。如果不确定,Salesforce会为您生成一个名称。
没有扩展名的文件名默认为文本文件。您可以将附件呈现为CSV格式:

<messaging:attachment filename=”cases.csv”>
<apex:repeat var=”cx” value=”{!relatedTo.Cases}”>
{!cx.CaseNumber}
{!cx.Origin}
{!cx.Contact.email}
{!cx.Status}
</apex:repeat>
</messaging:attachment>

您也可以将数据呈现为HTML文件:

<messaging:attachment filename=”cases.html”>
<html>
<body>
<table border=”0″ >
<tr>
<th>Case Number</th><th>Origin</th>
<th>Creator Email</th><th>Status</th>
</tr>
<apex:repeat var=”cx” value=”{!relatedTo.Cases}”>
<tr>
<td><a href =
“https://na1.salesforce.com/{!cx.id}”>{!cx.CaseNumber}
</a></td>
<td>{!cx.Origin}</td>
<td>{!cx.Contact.email}</td>
<td>{!cx.Status}</td>
</tr>
</apex:repeat>
</table>
</body>
</html>
</messaging:attachment>

尽管您只能为每个<messaging:attachment>组件定义一个文件名,但可以将多个文件附加到电子邮件中。

更改呈现属性

与其他Visualforce页面类似,在<messaging:attachment>组件上将renderAs属性设置为PDF将使该附件呈现为PDF。例如:

<messaging:attachment renderAs=”PDF” filename=”cases.pdf”>
<html>
<body>
<p>You can display your {!relatedTo.name} cases as a PDF:</p>
<table border=”0″ >
<tr>
<th>Case Number</th><th>Origin</th>
<th>Creator Email</th><th>Status</th>
</tr>
<apex:repeat var=”cx” value=”{!relatedTo.Cases}”>
<tr>
<td><a href =
“https://na1.salesforce.com/{!cx.id}”>{!cx.CaseNumber}
</a></td>
<td>{!cx.Origin}</td>
<td>{!cx.Contact.email}</td>
<td>{!cx.Status}</td>
</tr>
</apex:repeat>
</table>
</body>
</html>
</messaging:attachment>

Visualforce PDF呈现服务的限制包括以下内容。

  • PDF是唯一支持的呈现服务。
  • PDF呈现服务呈现PDF版本1.4。
  • 将Visualforce页面呈现为PDF文件适用于为打印设计和优化的页面。
  • 作为PDF文件呈现的Visualforce页面显示在浏览器中,或根据浏览器的设置进行下载。具体行为取决于浏览器,版本和用户设置,并且不受Visualforce的控制。
  • PDF呈现服务在您的页面上呈现标记和数据,但是它可能不会呈现包含在添加到页面的富文本区域内容中的格式。
  • 没有断点的长行文本(如空格或破折号)不能由PDF呈现服务打包。这通常发生在非常长的URL,注册表项等等。当这些行比页面宽时,它们会增加页面内容的宽度,超出PDF页面的边缘。这会导致内容从页面“流”,切断它。
  • 不要使用不易打印格式的标准组件,或输入或按钮等表单元素,或任何需要JavaScript格式的组件。
  • PDF渲染不支持JavaScript呈现的内容。
  • Salesforce应用程序中的页面不支持PDF呈现。
  • 页面上使用的字体必须在Visualforce PDF呈现服务上可用。 Web字体不受支持。
  • 如果PDF文件无法显示所有页面的文本,特别是多字节字符(如日文或重音国际字符),请调整CSS以使用支持它们的字体。 例如:
    <apex:page showHeader=”false” applyBodyTag=”false” renderAs=”pdf”>
    <head>
    <style>
    body { font-family: ‘Arial Unicode MS’; }
    </style>
    </head>
    <body>
    これはサンプルページです。<br/>
    This is a sample page: API version 28.0
    </body>
    </apex:page>
    “Arial Unicode MS”是包含多字节字符的扩展字符集所支持的唯一字体。
  • 如果使用内联CSS样式,请将API版本设置为28.0或更高版本。同样设置<apex:page applyBodyTag =“false”>,并在页面中添加静态的,有效的<head>和<body>标签,就像前面的例子。
  • 创建PDF文件时的最大响应大小必须小于15 MB,然后才能呈现为PDF文件。此限制是所有Visualforce请求的标准限制。
  • 生成的PDF文件的最大文件大小为60 MB。
  • 生成的PDF中包含的所有图像的最大总大小为30 MB。
  • PDF呈现不支持以数据:URI方案格式编码的图像。
  • 以PDF形式呈现时,以下组件不支持双字节字体。
    – <apex:pageBlock>
    – <apex:sectionHeader>
    不推荐将这些组件用于以PDF形式呈现的页面。
  • 如果<apex:dataTable>或<apex:pageBlockTable>没有呈现<apex:column>组件,则将该页呈现为PDF失败。 要解决此问题,请将表组件的呈现属性设置为false,如果未呈现其任何子<apex:column>组件。

添加样式和图像

附件还可以使用样式表来改变数据的呈现方式。 样式以与在Visualforce电子邮件模板中的方式相同的方式与内嵌代码或通过使用自定义组件相关联。
呈现为PDF的附件可以通过$ Resource全局变量引用静态资源。 这使您可以引用PDF正文中的图像或样式表。
例如,以下附件在PDF中包含徽标:

<messaging:attachment renderAs=”PDF” filename=”cases.pdf”>
<html>
<body>
<img src = “{!$Resource.logo}” />

</body>
</html>
</messaging:attachment>

这个附件引用了一个你保存为静态资源的样式表:

<messaging:attachment renderAs=”PDF”>
<html>
<link rel=’stylesheet’ type=’text/css’ href='{!$Resource.EMAILCSS}’ />
<body>

</body>
</html>
</messaging:attachment>

警告:引用远程服务器上的静态资源可能会增加呈现PDF附件所需的时间。 在Apex触发器中创建PDF附件时,不能引用远程资源; 这样做会导致例外。

Visualforce-邮件模板(2)样式

默认情况下,Visualforce电子邮件模板始终使用其他Salesforce组件的标准外观。但是,您可以通过定义自己的样式表来扩展或覆盖这些样式。
与其他Visualforce页面不同,Visualforce电子邮件模板不能使用引用的页面样式或静态资源。尽管CSS似乎在电子邮件模板预览窗格中呈现,但它与您的电子邮件的收件人不同。您必须在<style>标签内使用CSS定义您的样式。
以下示例将电子邮件的字体更改为Courier,将边框添加到表中,并更改表格行的颜色:

<messaging:emailTemplate recipientType=”Contact”
relatedToType=”Account”
subject=”Case report for Account: {!relatedTo.name}”
replyTo=”support@acme.com”>
<messaging:htmlEmailBody>
<html>
<style type=”text/css”>
body {font-family: Courier; size: 12pt;}
table {
border-width: 5px;
border-spacing: 5px;
border-style: dashed;
border-color: #FF0000;
background-color: #FFFFFF;
}
td {
border-width: 1px;
padding: 4px;
border-style: solid;
border-color: #000000;
background-color: #FFEECC;
}
th {
color: #000000;
border-width: 1px ;
padding: 4px ;
border-style: solid ;
border-color: #000000;
background-color: #FFFFF0;
}
</style>
<body>
<p>Dear {!recipient.name},</p>
<table border=”0″ >
<tr>
<th>Case Number</th><th>Origin</th>
<th>Creator Email</th><th>Status</th>
</tr>
<apex:repeat var=”cx” value=”{!relatedTo.Cases}”>
<tr>
<td><a href =
“https://na1.salesforce.com/{!cx.id}”>{!cx.CaseNumber}
</a></td>
<td>{!cx.Origin}</td>
<td>{!cx.Contact.email}</td>
<td>{!cx.Status}</td>
</tr>
</apex:repeat>
</table>
</body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>

在自定义组件中定义Visualforce样式表

虽然您无法在Visualforce电子邮件模板中引用外部样式表,但您可以将样式定义放置在可在其他位置引用的自定义组件中。例如,您可以修改前面的示例以将样式信息放入名为EmailStyle的组件中:

<apex:component access=”global”>
<style type=”text/css”>
body {font-family: Courier; size: 12pt;}
table {
border-width: 5px;
border-spacing: 5px;
border-style: dashed;
border-color: #FF0000;
background-color: #FFFFFF;
}
td {
border-width: 1px;
padding: 4px;
border-style: solid;
border-color: #000000;
background-color: #FFEECC;
}
th {
color: #000000;
border-width: 1px ;
padding: 4px ;
border-style: solid ;
border-color: #000000;
background-color: #FFFFF0;
}
</style>
</apex:component>

然后,在Visualforce电子邮件模板中,您只能引用该组件:

<messaging:htmlEmailBody>
<html>
<c:EmailStyle />
<body>
<p>Dear {!recipient.name},</p>

</body>
</html>
</messaging:htmlEmailBody>

注意:在Visualforce电子邮件模板中使用的任何<apex:component>标记都必须具有全局访问级别。