Apex からの PDF としての Visualforce ページの表示
1<apex:page title="Account Summary" tabStyle="Account"
2 controller="PdfEmailerController">
3
4 <apex:pageMessages />
5
6 <apex:form >
7 <apex:pageBlock title="Account Summary">
8
9 <p>Select a recently modified account to summarize.</p>
10 <p/>
11
12 <apex:pageBlockSection title="Report Format">
13
14 <!-- Select account menu -->
15 <apex:pageBlockSectionItem>
16 <apex:outputLabel for="selectedAccount" value="Account"/>
17 <apex:selectList id="selectedAccount" value="{! selectedAccount }"
18 size="1">
19 <apex:selectOption /> <!-- blank by default -->
20 <apex:selectOptions value="{! recentAccounts }" />
21 </apex:selectList>
22 </apex:pageBlockSectionItem>
23
24 <!-- Select report format menu -->
25 <apex:pageBlockSectionItem >
26 <apex:outputLabel for="selectedReport" value="Summary Format"/>
27 <apex:selectList id="selectedReport" value="{! selectedReport }"
28 size="1">
29 <apex:selectOptions value="{! reportFormats }" />
30 </apex:selectList>
31 </apex:pageBlockSectionItem>
32
33 <!-- Email recipient input field -->
34 <apex:pageBlockSectionItem >
35 <apex:outputLabel for="recipientEmail" value="Send To"/>
36 <apex:inputText value="{! recipientEmail }" size="40"/>
37 </apex:pageBlockSectionItem>
38
39 </apex:pageBlockSection>
40
41 <apex:pageBlockButtons location="bottom">
42 <apex:commandButton action="{! sendReport }" value="Send Account Summary" />
43 </apex:pageBlockButtons>
44
45 </apex:pageBlock>
46 </apex:form>
47
48</apex:page>このページは、シンプルなユーザインターフェースです。Apex から PDF ファイルを生成する場合、すべてのアクションは Apex コード内にあります。
1public with sharing class PdfEmailerController {
2
3 // Form fields
4 public Id selectedAccount { get; set; } // Account selected on Visualforce page
5 public String selectedReport { get; set; } // Report selected
6 public String recipientEmail { get; set; } // Send to this email
7
8 // Action method for the [Send Account Summary] button
9 public PageReference sendReport() {
10
11 // NOTE: Abbreviated error checking to keep the code sample short
12 // You, of course, would never do this little error checking
13 if(String.isBlank(this.selectedAccount) || String.isBlank(this.recipientEmail)) {
14 ApexPages.addMessage(new
15 ApexPages.Message(ApexPages.Severity.ERROR,
16 'Errors on the form. Please correct and resubmit.'));
17 return null; // early out
18 }
19
20 // Get account name for email message strings
21 Account account = [SELECT Name
22 FROM Account
23 WHERE Id = :this.selectedAccount
24 LIMIT 1];
25 if(null == account) {
26 // Got a bogus ID from the form submission
27 ApexPages.addMessage(new
28 ApexPages.Message(ApexPages.Severity.ERROR,
29 'Invalid account. Please correct and resubmit.'));
30 return null; // early out
31 }
32
33 // Create email
34 Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
35 message.setToAddresses(new String[]{ this.recipientEmail });
36 message.setSubject('Account summary for ' + account.Name);
37 message.setHtmlBody('Here\'s a summary for the ' + account.Name + ' account.');
38
39 // Create PDF
40 PageReference reportPage =
41 (PageReference)this.reportPagesIndex.get(this.selectedReport);
42 reportPage.getParameters().put('id', this.selectedAccount);
43 Blob reportPdf;
44 try {
45 reportPdf = reportPage.getContentAsPDF();
46 }
47 catch (Exception e) {
48 reportPdf = Blob.valueOf(e.getMessage());
49 }
50
51 // Attach PDF to email and send
52 Messaging.EmailFileAttachment attachment = new Messaging.EmailFileAttachment();
53 attachment.setContentType('application/pdf');
54 attachment.setFileName('AccountSummary-' + account.Name + '.pdf');
55 attachment.setInline(false);
56 attachment.setBody(reportPdf);
57 message.setFileAttachments(new Messaging.EmailFileAttachment[]{ attachment });
58 Messaging.sendEmail(new Messaging.SingleEmailMessage[]{ message });
59
60 ApexPages.addMessage(new
61 ApexPages.Message(ApexPages.Severity.INFO,
62 'Email sent with PDF attachment to ' + this.recipientEmail));
63
64 return null; // Stay on same page, even on success
65 }
66
67
68 /***** Form Helpers *****/
69
70 // Ten recently-touched accounts, for the Account selection menu
71 public List<SelectOption> recentAccounts {
72 get {
73 if(null == recentAccounts){
74 recentAccounts = new List<SelectOption>();
75 for(Account acct : [SELECT Id,Name,LastModifiedDate
76 FROM Account
77 ORDER BY LastModifiedDate DESC
78 LIMIT 10]) {
79 recentAccounts.add(new SelectOption(acct.Id, acct.Name));
80 }
81 }
82 return recentAccounts;
83 }
84 set;
85 }
86
87 // List of available reports, for the Summary Format selection menu
88 public List<SelectOption> reportFormats {
89 get {
90 if(null == reportFormats) {
91 reportFormats = new List<SelectOption>();
92 for(Map <String,Object> report : reports) {
93 reportFormats.add(new SelectOption(
94 (String)report.get('name'), (String)report.get('label')));
95 }
96 }
97 return reportFormats;
98 }
99 set;
100 }
101
102
103 /***** Private Helpers *****/
104
105 // List of report templates to make available
106 // These are just Visualforce pages you might print to PDF
107 private Map<String,PageReference> reportPagesIndex;
108 private List<Map<String,Object>> reports {
109 get {
110 if(null == reports) {
111 reports = new List<Map<String,Object>>();
112 // Add one report to the list of reports
113 Map<String,Object> simpleReport = new Map<String,Object>();
114 simpleReport.put('name', 'simple');
115 simpleReport.put('label', 'Simple');
116 simpleReport.put('page', Page.ReportAccountSimple);
117 reports.add(simpleReport);
118
119 // Add your own, more complete list of PDF templates here
120
121 // Index the page names for the reports
122 this.reportPagesIndex = new Map<String,PageReference>();
123 for(Map<String,Object> report : reports) {
124 this.reportPagesIndex.put(
125 (String)report.get('name'), (PageReference)report.get('page'));
126 }
127 }
128 return reports;
129 }
130 set;
131 }
132}- 先頭にある 3 つの公開プロパティは、フォームの 3 つの入力要素により送信された値を取得します。
- sendReport() アクションメソッドは、[取引先の概要を送信] ボタンをクリックしたときに起動されます。
- 2 つの公開ヘルパープロパティは、選択リストの 2 つの入力要素に使用する値を提供します。
- 末尾にある非公開ヘルパーは、使用可能な PDF レポート形式のリストをカプセ���化します。Visualforce ページを作成してから、そのエントリをこのセクションに追加することにより、独自のレポートを追加できます。
- フォーム項目に意味のある値があることを確認するため、基本的なエラーチェックが実行されます。
- 次に、選択された取引先の値を使用して、その取引先の名前が検索されます。取引先名は、メールメッセージに追加されるテキストで使用されます。また、この検索では、実際の取引先が選択されたことを確認するため、フォームの値がさらに検証されます。
- Messaging.SingleEmailMessage クラスを使用して、メールメッセージの宛先、件名、本文の値を設定してメールメッセージが作成されます。
- 選択されたレポート形式に対してコードで PageReference が作成され、ページ要求パラメータが設定されます。パラメータは指定された「ID」で、その値は選択された取引先の ID に設定されます。この PageReference は、指定された取引先のコンテキストでこのページにアクセスするための特定の要求を表します。getContentAsPdf() がコールされると、参照された Visualforce ページから指定の取引先にアクセスでき、その取引先の詳細を使用してページが表示されます。
- 最後に、PDF データが添付ファイルに追加され、前に作成したメールメッセージに添付ファイルが追加されます。そして、メッセージが送信されます。
PageReference.getContentAsPdf() を使用する場合、メソッドコールの戻り値の型は「大きなバイナリオブジェクト」を表す Blob です。Apex では、Blob データ型は型指定のないバイナリデータを表します。バイナリデータが PDF ファイルになる「application/pdf」コンテンツタイプで reportPdf 変数を Messaging.EmailFileAttachment に追加する場合にのみ、このようになります。
さらに、getContentAsPdf() へのコールは try/catch ブロックにラップされます。コールに失敗すると、catch により、期待される PDF データが例外メッセージテキストの Blob バージョンで置き換えられます。
PDF データとしての Visualforce ページの表示は、さまざまな理由により、意味的には外部サービスへのコールアウトとして処理されます。その理由の 1 つとして、外部サービスが失敗するのとまったく同じように表示サービスが失敗する可能性があることが挙げられます。たとえば、使用できない外部リソースをページで参照する場合があります。別の例としては、ページに含まれるデータが多すぎたり、表示時間が制限を超えたりする場合です。これは通常、画像フォームの場合に起こります。この理由により、Visualforce ページを Apex で PDF データとして表示する場合は、getContentAsPdf() 表示コールを常に try/catch ブロックにラップしてください。
1<apex:page showHeader="false" standardStylesheets="false"
2 standardController="Account">
3
4 <!--
5 This page must be called with an Account ID in the request, e.g.:
6 https://<salesforceInstance>/apex/ReportAccountSimple?id=001D000000JRBet
7 -->
8
9 <h1>Account Summary for {! Account.Name }</h1>
10
11 <table>
12 <tr><th>Phone</th> <td><apex:outputText value="{! Account.Phone }"/></td></tr>
13 <tr><th>Fax</th> <td><apex:outputText value="{! Account.Fax }"/></td></tr>
14 <tr><th>Website</th><td><apex:outputText value="{! Account.Website }"/></td></tr>
15 </table>
16
17 <p><apex:outputText value="{! Account.Description }"/></p>
18
19</apex:page>