PDFファイルの生成

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

前提

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

1. 手書きをPDFにするコントローラーを作成する

手書きの結果をPDFにするためのコントローラーを作成します。

  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として出力するためにrenderAs=“pdf”を指定したVisualforceページを作成します。

  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/>
            </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. 動作を確認する

次の手順ではSalesforceモバイルアプリケーション使用します。

  1. Salesforceモバイルアプリケーションを起動し、Salesforceにログインする。
  2. メニューから「同意書(VF)」をタップする。
  3. 「署名する」をタップする。
  4. 「同意書」画面で、手書きを試す。
  5. 「OK」ボタンをクリックする。
  6. 画面に保存された手書き画像が表示され、「PDFとして保存」ボタンが表示される。
  7. 「PDFとして保存」ボタンをクリックする。
  8. 「PDFの名前」および「PDFのID」が表示される。
  9. 「ファイル」を開き、ファイルの一覧から作成したPDFを選択してPDFドキュメントを確認する。

このページでのPDFに手書き結果を埋め込む方法は、実際にはRayPenの機能とは関係がなく、Salesforceでの開発の1例であることに注意してください。

Copyright © 2024 MESCIUS inc. All rights reserved.