ここでは、ユーザーによる手書きの結果をPDFファイルとして生成する方法を説明します。なお、ここで説明する内容はサンプルパッケージでインストールすることもできます。
PDFファイルの生成の組み込みは手書きパッドの組み込みで実装した処理に対して追加と修正を行います。
手書きの結果をPDFにするためのコントローラーを作成します。
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 '';
}
}
}
次に、PDFとして出力するためにrenderAs=“pdf”を指定したVisualforceページを作成します。
<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>
私は術前、担当医師より手術に関して十分な説明をうけ
</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>
手書きを保存するコントローラー(SurgeryAgreementPageController)にPDFを保存する処理を追加します。
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;}
}
Visualforceページ(Surgery_Agreement)にPDFの操作パネルを追加します。
<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>
次の手順ではSalesforceモバイルアプリケーション使用します。
このページでのPDFに手書き結果を埋め込む方法は、実際にはRayPenの機能とは関係がなく、Salesforceでの開発の1例であることに注意してください。