PDFファイルの生成とプレビュー表示

ここでは、ユーザによる手書きの署名の結果をPDFファイルとして生成し、そのPDFファイルをプレビュー表示する方法を説明します。なお、ここで説明する内容はサンプルパッケージでインストールすることもできます。

前提

PDFファイルの生成とプレビュー表示の組み込みは手書きパッドの組み込みで実装した処理に対して追加と修正を行います。

制限

RayPreviewコンポーネントは「RayKit」アプリでのみ動作します。Salesforceモバイルアプリやブラウザでは動作しません。

1. 署名をPDFにするコントローラを作成する

署名の結果をPDFにするためのコントローラを作成します。次の手順ではPC(Mac)のブラウザを使用します。

  1. Salesforce Classicの場合、「設定 > ビルド > 開発 > Apexクラス」を開く。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > プラットフォームツール > カスタムコード > Apexクラス」を開く。
  2. 「新規」ボタンをクリックし、「Apex Class」に次のコードを貼り付け、「保存」をクリックする。
public with sharing class SurgeryAgreementPDFPageController {
 public string defaultPatientName = '私';
    public string getDefaultPatientName(){
        return this.defaultPatientName;
    }
    
    public string defaultAgreementText = 'は術前、担当医師より手術に関して十分な説明をうけ了解いたしました。よって貴院における手術の実施に同意いたします。なお手術中、他の疾患が発見された場合や不測の事態が生じた場合には、それに応じた適切な処置をとられることに同意いたします。';
    public string getDefaultAgreementText(){
        return this.defaultPatientName + this.defaultAgreementText;
        
    }
    
    public string defaultAgreementTitle = '手術同意書';
    public string getDefaultAgreementTitle(){
        return this.defaultAgreementTitle;
    }
    public string defaultAgreementDate = Datetime.now().format('yyyy年MM月dd日');
    public string getDefaultAgreementDate(){
        return this.defaultAgreementDate;
    }
    
    public string defaultSignatureTitle = '署名欄';
    public string getDefaultSignatureTitle(){
        return defaultSignatureTitle;
    }
    public string defaultDoctorTitle =  '院長 殿';
    public string getDefaultDoctorTitle(){
        return defaultDoctorTitle;
    }
   
    public Surgery_Agreement__c currentAgreement{get{
        PageReference currentPage = apexpages.currentPage();
        Map<string, string> parameters = currentPage.getParameters();
        string currentAgreementId = parameters.get('agreementId');
        
        return this.getAgreementById(currentAgreementId);
    }}
    
    public Surgery_Agreement__c getAgreementById(string agreementId){
        if (String.isEmpty(agreementId)){return null;}
        if (!Schema.Surgery_Agreement__c.getSObjectType().getDescribe().isAccessible()){return null;}
        
        Surgery_Agreement__c agreement = [select AgreementText__c, SignatureId__c  from Surgery_Agreement__c where Id=:agreementId limit 1];
        return agreement;
    }
    
    public string currentAgreementSignatureId;
    public string getCurrentAgreementSignatureId(){
        if (this.currentAgreement != null){
            return this.currentAgreement.signatureId__c;
        }else{
            return '';
        }
    }
}

2. プレビューでPDFを表示を表示する

次に、Visualforceページを作成して、PDFにした手書き署名の結果をプレビュー表示します。次の手順ではPC(Mac)のブラウザを使用します。

  1. Salesforce Classicの場合、「設定 > 開発 > Visualforceページ」をクリックする。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > カスタムコード > Visualforceページ」をクリックする。
  2. 「新規」ボタンをクリックする。
  3. 「表示ラベル」と「名前」に「Surgery_Agreement_PDF」と記入する。
  4. 「Lightning Experience、Lightning コミュニティ、およびモバイルアプリケーションで利用可能」をオンにする。
  5. 「Visualforce Markup」に次の内容を入力し、「保存」をクリックする。
<apex:page controller="SurgeryAgreementPDFPageController" showHeader="false" 
           sidebar="false"
           renderAs="pdf"
           standardStylesheets="false"
           docType="html-5.0"
           applyHtmlTag="false"
           applyBodyTag="false">
    <html lang="en">
        <head>
            <title>Surgery Agreement</title>
            <style>
                body{
                width: 7in;
                margin: 0;
                padding: 0;
                }
                .agreement-title{
                font-size: 20pt;
                font-weight: 900;
                text-align: center;
                font-family:"Arial Unicode MS";
                margin: 0;
                padding: 0;
                }
                .doctor-title{
                font-size: 20pt;
                text-align: right;
                font-family:"Arial Unicode MS";
                }
                
                .agreement-text{
                font-size: 16 pt;
                overflow-wrap: break-word;
                word-break: break-all;
                font-family:"Arial Unicode MS";
                display: inline-block;
                text-align: left;
                }
                
                
                
                .signature-pad-container{
                max-width: 200px;
                max-height: 100px;
                width: 200px;
                height: 100px;
                border: 1px solid black;
                background-color: white;
                text-align: center;
                font-family:"Arial Unicode MS";
                }
                
                .signature-button{
                width: 200px;
                height: 100px;
                background: white;
                border: none;
                margin: 0;
                font-family:"Arial Unicode MS";
                }
                
                .signature-image{
                width: 200px;
                height: 100px;
                font-family:"Arial Unicode MS";
                }
                
                .agreement-date{
                font-size: 16 pt;
                font-family:"Arial Unicode MS";
                text-align: left;
                }
                
                .agreement-body{
                text-align: center;
                padding: 0 90pt;
                }
                
                .signature-title{
                text-align: right;
                }
                .signature-pad-container{
                margin: 0 auto;
                margin-right: 0;
                }
                
                
            </style>
        </head>
        <body >
            <h1 class="agreement-title">
                {!defaultAgreementTitle}
            </h1>
            
            <div class="agreement-body">
                <div class="doctor-title">
                    {!defaultDoctorTitle}
                </div>
                <div class="agreement-text">
                    <p>
                        &nbsp; &nbsp;私は術前、担当医師より手術に関して十分な説明をうけ
                    </p>
                    <p>
                        了解いたしました。よって貴院における手術の実施に同意い
                    </p>
                    <p>
                        たします。なお手術中、他の疾患が発見された場合や不測の
                    </p>
                    <p>
                        事態が生じた場合には、それに応じた適切な処置をとられる
                    </p>
                    <p>
                        ことに同意いたします。
                    </p>
                    <div class="agreement-date">
                        {!defaultAgreementDate}
                    </div>
                    
                    <div class="signature-title">
                        {!defaultSignatureTitle}
                        
                    </div>
                    <div class="signature-pad-container">
                        <gcrp:RayPen placeholder="ここに手書き画像" 
                                          styleClass="signature-button"
                                          signatureImageStyleClass="signature-image"
                                          currentSignatureId="{!currentAgreementSignatureId}"
                                          />
                    </div>
                </div>
                
                
                
            </div>
            
            
        </body>
    </html>
</apex:page>

3. 署名を保存するコントローラにPDF保存処理を追加する

署名を保存するコントローラ(SurgeryAgreementPageController)にPDFドキュメントを保存する処理を追加します。

  1. Salesforce Classicの場合、「設定 > ビルド > 開発 > Apexクラス」を開く。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > プラットフォームツール > カスタムコード > Apexクラス」を開く。
  2. 「SurgeryAgreementPageController」の編集をクリックし、編集画面を開く。
  3. 「Apex Class」を次の内容に変更し、「保存」をクリックする。
public with sharing class SurgeryAgreementPageController {
    
    public Id savedPDFFileID;
    public string defaultAgreementText = '私は術前、担当医師より手術に関して十分な説明をうけ了解いたしました。よって貴院における手術の実施に同意いたします。なお手術中、他の疾患が発見された場合や不測の事態が生じた場合には、それに応じた適切な処置をとられることに同意いたします。';
    public string getDefaultAgreementText(){
        return this.defaultAgreementText;
        
    }
    
    public string defaultAgreementTitle = '手術同意書';
    public string getDefaultAgreementTitle(){
        return this.defaultAgreementTitle;
    }
    public string defaultAgreementDate = Datetime.now().format('yyyy年MM月dd日');
    public string getDefaultAgreementDate(){
        return this.defaultAgreementDate;
    }
    
    public string defaultSignatureTitle = '署名欄';
    public string getDefaultSignatureTitle(){
        return defaultSignatureTitle;
    }
    public string defaultDoctorTitle =  '院長 殿';
    public string getDefaultDoctorTitle(){
        return defaultDoctorTitle;
    }
    
   
    public Surgery_Agreement__c currentAgreement{get{
        if (!Surgery_Agreement__c.sObjectType.getDescribe().isAccessible()){return null;}

        PageReference currentPage = apexpages.currentPage();
        Map<string, string> parameters = currentPage.getParameters();
        string currentAgreementId = parameters.get('agreementId');
        
        return this.getAgreementById(currentAgreementId);
    }}
    
    public string currentAgreementSignatureId;
    public string getCurrentAgreementSignatureId(){

        if (!Schema.sObjectType.Surgery_Agreement__c.fields.signatureId__c.isAccessible()){return '';}
        if (this.currentAgreement != null){
            return this.currentAgreement.signatureId__c;
        }else{
            return '';
        }
    }
    
    public Surgery_Agreement__c savedAgreement;
    
    
    public Surgery_Agreement__c signAgreement(string agreementId, string signatureId){
        if (!Surgery_Agreement__c.sObjectType.getDescribe().isAccessible()){return null;}

        if (!Surgery_Agreement__c.sObjectType.getDescribe().isUpdateable()){return null;}

        Surgery_Agreement__c agreement = getAgreementById(agreementId);
        if (agreement == null){
            return null;
        }
        agreement.signatureId__c = signatureId;
        agreement.Patient_Signature__c = signatureId;
        
        update agreement;
        
        return agreement;
    }
    
    public Surgery_Agreement__c getAgreementById(string agreementId){
        if (!Surgery_Agreement__c.sObjectType.getDescribe().isAccessible()){return null;}
        
        if (String.isEmpty(agreementId)){
            return null;
        }
        
        Surgery_Agreement__c agreement = [select AgreementText__c, SignatureId__c  from Surgery_Agreement__c where Id=:agreementId limit 1];
        return agreement;
    }
    
    
    public PageReference onPatientSignatureComplete(){
        if (!Surgery_Agreement__c.sObjectType.getDescribe().isCreateable()){return null;}

        Surgery_Agreement__c agreement  = new Surgery_Agreement__c();
        agreement.Date__c = this.defaultAgreementDate;
        agreement.DoctorTitle__c = this.defaultDoctorTitle;
        agreement.SignatureTitle__c = this.defaultSignatureTitle;
        agreement.AgreementText__c = this.defaultAgreementText;
        
        insert agreement;
        
        string agreementPDFVersionUrl = '/apex/Surgery_Agreement_PDF?agreementId=' + agreement.Id;
        agreement.PDFPageUrl__c  = agreementPDFVersionUrl;
        update agreement;
        
        this.signAgreement(agreement.Id, patientSignatureId);
        this.savedAgreement = agreement;

        return null;
    }

    public void savePDFToDocuments(){
        if (this.savedAgreement == null){
            return;
        }
        
        string pdfUrl = this.savedAgreement.PDFPageUrl__c;
        PageReference pr = new PageReference(pdfUrl);
        
        Blob b = pr.getContent();

       saveBlobAsContentDocument(b);
    }

    public void saveBlobAsContentDocument(Blob b){
         string fileName = 'Surgery Agreement ' + this.savedAgreement.Id + '.pdf';
        ContentVersion cv = new ContentVersion();
        cv.ContentLocation = 'S';
        cv.VersionData = b;
        cv.Title = fileName;
        cv.PathOnClient=fileName;        
        insert cv;
        
        
        
        cv = [select ContentDocumentId from ContentVersion where Id=:cv.Id limit 1];
        this.savedPDFFileName = fileName;   
        this.savedPDFFileID = cv.ContentDocumentId;
    }


    public string savedPDFFileName = '';
    public boolean getIsSavedPDFFileNameExists(){
      return !string.isBlank(savedPDFFileName);
    }
    
    public string getSavedPDFFileName(){
      return this.savedPDFFileName;
    }
    
    public string getSavedPDFFileID(){
      return string.valueOf(this.savedPDFFileID);
    }
    
    
    public string getShowPDFURL(){
      if(this.savedAgreement == null){
        return '';
      }
      
      string pdfUrl = this.savedAgreement.PDFPageUrl__c;
      return '/apex/PdfViewer?pdf-url=' + EncodingUtil.urlEncode(pdfUrl, 'UTF-8');
    }
    
    

    public Boolean getCurrentSignatureExists(){
      return this.savedAgreement != null;
    }
    public string patientSignatureId{get;set;}
}

4. 署名パッドにPDF操作パネルを追加する

署名パッドを表示するVisualforceページ(Surgery_Agreement)にPDFの操作パネルを追加します。

  1. Salesforce Classicの場合、「設定 > 開発 > Visualforceページ」をクリックする。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > カスタムコード > Visualforceページ」をクリックする。
  2. 「Surgery_Agreement」の編集をクリックし、編集画面を開く。
  3. 「Visualforce Markup」を次の内容に変更し、「保存」をクリックする。
<apex:page controller="SurgeryAgreementPageController"  standardStylesheets="false">

    <h1>
        {!defaultAgreementTitle}
    </h1>
    <div>
        {!defaultDoctorTitle}
    </div>
    <div>
        {!defaultAgreementText}
    </div>
    <div>
        {!defaultAgreementDate}
    </div>
    
    <div>
        {!defaultSignatureTitle}

         <div class="signature-pad-container">
            <gcrp:RayPen placeholder="署名する" 
                              styleClass="signature-button"
                              signatureImageStyle="max-width: 200px; max-height: 100px;"
                              currentSignatureId="{!patientSignatureId}"
                              onSignatureComplete="{!onPatientSignatureComplete}"

                              footNote="署名の前に契約書を必ずお読みください"
                              footNoteColor="#cccccc"

                              signatureLineColor="#cccccc"
                              titleText="同意書"
                              titleTextColor="#000000"
                              okButtonText="OK"
                              cancelButtonText="キャンセル"
                              reRender="pdfOperationPanel"
                              />
        </div>
    </div>


    <apex:outputPanel id="pdfOperationPanel" >
        <apex:form rendered="{!currentSignatureExists}">
            <apex:commandButton reRender="pdfOperationPanel"
                action="{!savePDFToDocuments}" 
                value="PDFとして保存"/>

            <apex:outputPanel rendered="{!isSavedPDFFileNameExists}">
                <p>PDFの名前: </p>
                {!savedPDFFileName}
                
                <p>PDFのId:</p>
                {!savedPDFFileID}
                
                <br/>
               <gcrp:RayPreview contentDocumentId="{!savedPDFFileID}" 
                         text="PDFをプレビュー"></gcrp:RayPreview>
            </apex:outputPanel>
        </apex:form>
    </apex:outputPanel>

    <style>
    .signature-pad-container{
        max-width: 200px;
        max-height: 100px;
        width: 200px;
        height: 100px;
        border: 1px solid black;
        background-color: white;
        text-align: center;
    }
    
    .signature-button{
        
        width: 200px !important;
        height: 100px !important;
        background-color: white !important;
        border: none !important;
        -webkit-appearance: none;
        background-image: none !important;
        box-sizing: border-box;
        border-radius: unset !important;
        padding: 0 !important;
        margin: 0 !important;
    }

    .signature-image{
    }
    </style>
</apex:page>

5. 動作を確認する

次の手順ではスマートフォンまたはiPadの「RayKit」アプリを使用します。

  1. 「RayKit」アプリを起動し、Salesforceにログインする。
  2. ナビゲーションメニューから「Surgery Agreement」をタップする。
  3. 「署名する」をタップする。
  4. 「同意書」画面で、手書きを試す。
  5. 「OK」ボタンをクリックする。
  6. Visualforceページに保存された署名が表示され、「PDFとして保存」ボタンが表示される。
  7. 「PDFとして保存」ボタンをクリックする。
  8. 「PDFの名前」、「PDFのID」および「PDFをプレビュー」ボタンが表示される。
  9. 「PDFをプレビュー」ボタンをクリックする。
  10. 署名結果のPDFがプレビュー表示されることを確認する。
Copyright © 2019 GrapeCity inc. All rights reserved.