MENU
Abo
某SIer勤務。
ITエンジニアです。
日々の学びをつらつらと書いています。
保有資格:
Salesforce認定アドミニストレーター  
Salesforce認定Platformデベロッパー
Salesforce認定上級Platformデベロッパー
カテゴリー
アーカイブ

【Aura】 lightning:datatableにCSVエクスポート機能を追加

今回はlightning:datatableを用いた関連リストにCSVエクスポートボタンを追加し、CSV出力機能を追加しました。

また、本記事記載のソールコードにはCSV出力機能の他に以下の機能が盛り込まれています。

  • 新規取引先レコード作成
  • 取引先レコード編集(行アクション)
  • 取引先レコード削除(行アクション)
  • 新規取引先レコード作成権限チェック
  • 取引先削除権限チェック
  • ページネーション
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" controller="ContactListController01">
    
    <aura:attribute name="title" type="String"/>
    <aura:attribute name="data" type="Object"/>
    <aura:attribute name="columns" type="List"/>
    <aura:attribute name="recId" type="String"/>
    <aura:attribute name="labelMap" type="Map" default="{}"/>
    <aura:attribute name="rowNumber" type="Integer" default="0"/>
    
    <aura:attribute name="pageSize" type="Integer" default="10"/>
    <aura:attribute name="currentPageNumber" type="Integer" default="1"/>
    <aura:attribute name="totalPages" type="Integer" default="0"/>
    
    <aura:attribute name="showNewButton" type="Boolean" default="false"/>
    <aura:attribute name="showDatatable" type="Boolean" default="false"/>
    <aura:attribute name="showConfirmDialog" type="Boolean" default="false"/>
 
    <aura:handler name="init" action="{!c.init}" value="{!this}"/>
        
    <!--Contact List-->
    <article class="slds-card slds-theme_shade">
        <div class="slds-card__header slds-grid">
            <header class="slds-media slds-media_center slds-has-flexi-truncate">
                <div class="slds-media__figure">
                    <span class="slds-icon_container slds=icon-standard-contact" title="contact">
                        <lightning:icon iconName="standard:contact" alternativeText="Contact" title="Contact" size="small"/>            
                    </span>
                    <span class="slds-assistive-text">contact</span>            
                </div>
                <div class="slds-media__body">
                    <h2 class="slds-card__header-title cardTitle">
                        <span class="slds-card__header-link slds-truncate" style="margin-top:4px;">{!v.title}</span>                  
                    </h2>             
                </div> 
                <aura:if isTrue="{!v.showNewButton}">
                    <lightning:button label="New" onclick="{!c.handleNew}"/>
                </aura:if>
                <aura:if isTrue="{!v.showDatatable}">
                    <lightning:button label="CSV" onclick="{!c.handleCsv}"/>
                </aura:if>   
            </header>       
        </div>
        <aura:if isTrue="{!v.showDatatable}">
            <div style="border: 1px solid #D8D8D8;">
                <lightning:datatable aura:id="ContactList"
                                     columns="{!v.columns}"
                                     data="{!v.data}"
                                     keyField="Id"
                                     showRowNumberColumn="true"
                                     rowNumberOffset="{!v.rowNumber}"
                                     onrowaction="{!c.handleRowAction}"
                                     />     
            </div>        

            <!--Pagenatin-->
            <center>
                <br/>
                <lightning:button class="slds-m-bottom_medium"
                                  label="First"
                                  iconName="utility:left"
                                  iconPosition="left"
                                  onclick="{! c.onFirst }"
                                  disabled="{! v.currentPageNumber == 1 }" />
                <lightning:button class="slds-m-bottom_medium"
                                  label="Previous"
                                  iconName="utility:chevronleft"
                                  iconPosition="left"
                                  onclick="{! c.onPrev }"
                                  disabled="{! v.currentPageNumber == 1 }" />
                <span class="slds-m-horizontal_x-small">
                    Page {! v.currentPageNumber } of {! v.totalPages}
                </span>
                <lightning:button class="slds-m-bottom_medium"
                                  label="Next"
                                  iconName="utility:chevronright"
                                  iconPosition="right"
                                  onclick="{! c.onNext }"
                                  disabled="{! v.currentPageNumber == v.totalPages  }" />
                <lightning:button class="slds-m-bottom_medium"
                                  label="Last"
                                  iconName="utility:right"
                                  iconPosition="right"
                                  onclick="{! c.onLast }"        
                                  disabled="{! v.currentPageNumber == v.totalPages }" />
            </center>
        </aura:if>
    </article>
    
    <!-- Delete modal -->
    <aura:if isTrue="{!v.showConfirmDialog}">
        <div role="dialog" class="slds-modal slds-fade-in-open">
            <div class="slds-modal__container">
                <header class="slds-modal__header">
                    <h1 class="slds-text-heading--medium">Delete Contact</h1>
                </header>
                <div class="slds-modal__content slds-p-around--medium">
                    <center><b>Are you sure you want to delete this Contact?</b></center>
                </div>
                <footer class="slds-modal__footer">
                    <lightning:button name="No" label="Cancel" onclick="{!c.handleConfirmDialogNo}"/>
                    <lightning:button name="Yes" label="Delete" onclick="{!c.handleConfirmDialogYes}"/>
                </footer>
            </div>
        </div>
        <div class="slds-backdrop slds-backdrop--open"/>
    </aura:if>
</aura:component>
({
    /** init **/
    init : function(component, event, helper) {
        helper.init(component, event, helper);
    },
    
    /** CSV output **/
    handleCsv : function(component, event, helper) {
        let url = '/apex/ContactCsvExport?id='+component.get("v.recordId");
        window.open(url, '_blank');
    },

    /** create new Contact **/
    handleNew : function(component, event, helper) {
        helper.handleNew(component, event, helper);
    },
    
    /** row action **/
    handleRowAction : function(component, event, helper) {
        helper.handleRowAction(component, event, helper);
    },
   
    /** delete ConfirmDialog "yes" **/
    handleConfirmDialogYes : function(component, event, helper) {
        helper.handleConfirmDialogYes(component, event, helper);
    },
    
    /** delete ConfirmDialog "no" **/
    handleConfirmDialogNo : function(component, event, helper) {
        helper.handleConfirmDialogNo(component, event, helper);
    },
    
    /** onFirst **/
    onFirst : function(component, event, helper) {
        component.set("v.currentPageNumber", 1);
        component.set("v.rowNumber", 0);
        helper.init(component, helper);
    },
 
    /** onPrev **/
    onPrev : function(component, event, helper) {
        component.set("v.currentPageNumber", component.get("v.currentPageNumber")-1);
        component.set("v.rowNumber", component.get("v.rowNumber")-component.get("v.pageSize"));
        helper.init(component, helper);
    },
        
    /** onNext **/
    onNext : function(component, event, helper) {
        component.set("v.currentPageNumber", component.get("v.currentPageNumber")+1);
        component.set("v.rowNumber", component.get("v.rowNumber")+component.get("v.pageSize"));
        helper.init(component, helper);
    },
    
    /** onLast **/
    onLast : function(component, event, helper) {
        component.set("v.currentPageNumber", component.get("v.totalPages"));
        component.set("v.rowNumber", (component.get("v.totalPages")-1)*component.get("v.pageSize"));
        helper.init(component, helper);
    }
 
 
})
({
    /** init **/
	init : function(component, event, helper) {

        // get Contact label
        var getContactLabelAction = component.get("c.getContactLabel");
        getContactLabelAction.setCallback(this, function(response){
            var state = response.getState();
            if(state === "SUCCESS"){
                var result = response.getReturnValue();
                // set Contact label
                component.set("v.labelMap", result);
                // row action
                var actions = [
                    {label: 'Edit', name: 'edit'},
                    {label: 'Delete', name: 'delete'}
                ]
                // set columns
                component.set("v.columns", [
                    {label: component.get("v.labelMap")['Name'], fieldName: 'LinkName', type: 'url', typeAttributes: {label: {fieldName: 'Name'}, tooltip: {fieldName: 'Name'}}, initialWidth: 150},              
                    {label: component.get("v.labelMap")['Title'], fieldName: 'Title', type: 'text', initialWidth: 150},
                    {label: component.get("v.labelMap")['Email'], fieldName: 'Email', type: 'email', initialWidth: 150},
                    {label: component.get("v.labelMap")['Phone'], fieldName: 'Phone', type: 'phone', initialWidth: 150},
                    {label: component.get("v.labelMap")['Department'], fieldName: 'Department', type: 'text', initialWidth: 150},
                    {label: component.get("v.labelMap")['Age__c'], fieldName: 'Age__c', type: 'text', initialWidth: 150},
                    {label: component.get("v.labelMap")['Birthdate'], fieldName: 'Birthdate', type: 'date', initialWidth: 150},
                    {label: component.get("v.labelMap")['IsActive__c'], fieldName: 'IsActive__c', type: 'boolean'},
                    {type: 'action', typeAttributes: { rowActions: actions }}  
                ]);
            }
        });
        $A.enqueueAction(getContactLabelAction);
        
        // get Contact
        var getContactAction = component.get("c.getContact");
        // record size per page
        var pageSize = component.get("v.pageSize").toString();
        // current page number
        var currentPageNumber = component.get("v.currentPageNumber").toString();
        // set params
        getContactAction.setParams({
            "recordId" : component.get("v.recordId"),
            "pageSize" : pageSize,
            "currentPageNumber" : currentPageNumber
        });
        getContactAction.setCallback(this, function(response){
            var state = response.getState();
            if(state === "SUCCESS"){
                var result = response.getReturnValue();
                // set link 
                result.forEach(function(record){
                    record.LinkName = '/' + record.Id;
                });
                component.set("v.data", result);
            }
        });
        $A.enqueueAction(getContactAction);
        
        // set object name
        component.set("v.title", "Contact")
        // count Contact records
        var countContactAction = component.get("c.countContact");
        // set params
        countContactAction.setParams({
            "recordId" : component.get("v.recordId")
        });
        countContactAction.setCallback(this, function(response){
            var state = response.getState();
            if(state === "SUCCESS"){
                var result = response.getReturnValue();
                if(result > 0){
                    // show datatable
                    component.set("v.showDatatable", true);
                }
                // show record number next to tilte
                component.set("v.title", component.get("v.title").concat(" (", result, ")"));
                // set total page size
                component.set("v.totalPages", Math.ceil(result/component.get("v.pageSize")));
            }
        });
        $A.enqueueAction(countContactAction);
        
        // permission check to create new Contact
        var isCreatableAction = component.get("c.isCreatable");
        isCreatableAction.setCallback(this, function(response){
            var state = response.getState();
            if(state === "SUCCESS"){
                var result = response.getReturnValue();
                // show NEW button
                component.set("v.showNewButton", result);
            }
        });
        $A.enqueueAction(isCreatableAction);
	},
    
    /** create new Contact **/
    handleNew : function(component, event, helper){
        var createRecord = $A.get("e.force:createRecord");
        createRecord.setParams({
            "entityApiName" : "Contact",
            "defaultFieldValues" : {'AccountId' : component.get("v.recordId")}
        })
        createRecord.fire();
    },
    
    /** row action **/
    handleRowAction : function(component, event, helper){
        var action = event.getParam('action');
        var row = event.getParam('row');
        var recId = row.Id;
        component.set("v.recId", recId);
        
        switch(action.name){
            case 'edit':                
                var editRecordEvent = $A.get("e.force:editRecord");
                editRecordEvent.setParams({
                    "recordId" : recId
                });
                //call edit
                editRecordEvent.fire();
                break;
            case 'delete':
                // show delete dialog
                component.set("v.showConfirmDialog", true);
                break;
        }
    }, 
    
    /** delete ConfirmDialog "yes" **/
    handleConfirmDialogYes : function(component, event, helper){
        // hide dailog
        component.set("v.showConfirmDialog", false);
        //get recordId
        var recId = component.get("v.recId");
        //delete Contact
        var action = component.get("c.deleteContact");
        // set params
        action.setParams({
            "recordId" : recId
        });
        action.setCallback(this, function(response){
            var state = response.getState();
            if(state === "SUCCESS"){
                if(response.getReturnValue() === null){
                    this.showToast({
                        "title": "Delete",
                        "type": "success",
                        "message":"Delete Success"});
                    //削除した後のリロード
                    this.reloadDataTable();
                }else{
                    //delete fail
                    this.showToast({
                        "title": "Error",
                        "type" : "error",
                        "message" : response.getReturnValue()
                    });
                }               
            }
        });
        $A.enqueueAction(action);
    },
    
    /** delete ConfirmDialog "no" **/
    handleConfirmDialogNo : function(component, event, helper){
        // hide dailog
        component.set("v.showConfirmDialog", false);
    },
    
    /** show message **/
    showToast:function(params){
        var toastEvent = $A.get("e.force:showToast");
    	if(toastEvent){
    		toastEvent.setParams(params);
    		toastEvent.fire();
    	} else{
    		alert(params.message);
    	}
    },
    
    /** reload **/
    reloadDataTable : function(){
        var refreshEvent = $A.get("e.force:refreshView");
        if(refreshEvent){
            refreshEvent.fire();
        }
    }
})
public class ContactList01Controller {

    // get Contact label
    @AuraEnabled
    public static Map<String, String> getContactLabel(){
        
        Map<String, String> fieldNameMap = new Map<String, String>();
        fieldNameMap.put('Name', Schema.SObjectType.Contact.fields.Name.Label);
        fieldNameMap.put('Title', Schema.SObjectType.Contact.fields.Title.Label);
        fieldNameMap.put('Email', Schema.SObjectType.Contact.fields.Email.Label);
        fieldNameMap.put('Phone', Schema.SObjectType.Contact.fields.Phone.Label);
        fieldNameMap.put('Department', Schema.SObjectType.Contact.fields.Department.Label);
        fieldNameMap.put('Age__c', Schema.SObjectType.Contact.fields.Age__c.Label);
        fieldNameMap.put('Birthdate', Schema.SObjectType.Contact.fields.Birthdate.Label);
        fieldNameMap.put('IsActive__c', Schema.SObjectType.Contact.fields.IsActive__c.Label);
        system.debug(fieldNameMap);
        return fieldNameMap;
    }
    
    // get Contact
    @AuraEnabled
    public static List<Contact> getContact(Id recordId, String pageSize, String currentPageNumber){
        
        Integer recSize = Integer.valueOf(pageSize);
        Integer curPageNumber = Integer.valueOf(currentPageNumber)-1;
        
        return [Select Id, Name, Title, Email, Phone, Department, Age__c, Birthdate, IsActive__c From Contact
                             Where AccountId =: recordId
                             Limit: recSize OffSet: (recSize * curPageNumber)];
        
    }
    
    // count Contact record
    @AuraEnabled
    public static Integer countContact(Id recordId){

        return [Select Count() From Contact Where AccountId =: recordId];
    }
    
    // permission check to create new Contact
    @AuraEnabled
    public static Boolean isCreatable(){
        return Schema.SObjectType.Contact.isCreateable();
    }
    
    // delete Contact
    @AuraEnabled
    public static String deleteContact(String recordId){
        
        try{
            // permission check to delete Contact
            if(Schema.SObjectType.Contact.isDeletable() == false){
                return 'No permission to delete this record.';
            }
            List<Contact> conList = [Select Id From Contact Where Id =: recordId];
            delete conList;
            return null;
        }catch(Exception e){
            return e.getMessage();
        }      
    }
}
<apex:page controller="ContactCsvExportController" action="{!export}" sidebar="false" showHeader="false" contentType="text/csv;charset=Shift-JIS#{!fileName}" readOnly="true" title="Csv Export">
    <apex:repeat value="{!headers}" var="item">
        <apex:outputText value="{!item}"/>
    </apex:repeat>
    
    <apex:repeat value="{!bodies}" var="items">
        <apex:repeat value="{!items}" var="item">
            <apex:outputText value="{!item}"/>
        </apex:repeat>
    </apex:repeat>
</apex:page>
public class ContactCsvExportController {

    public String fileName {get; set;}
    public List<String> headers {get; set;}
    public List<List<String>> bodies {get; set;}
    
    //CSV Export
    public void export(){
        
        fileName = 'ContactList.csv';
        fileName = EncodingUtil.urlEncode(fileName, 'UTF-8');
        
        // get recordId
        Id recordId = ApexPages.currentPage().getParameters().get('id');
        
        // get Contact 
        List<Contact> conList = [Select Id, Name, Title, Email, Phone, Department, Age__c, Birthdate, IsActive__c From Contact
                                 Where AccountId =: recordId Order by Id];
        
        // get label
        List<String> labelList = new List<String>();
        labelList.add('Id');
        labelList.add(Schema.SObjectType.Contact.fields.Name.label);
        labelList.add(Schema.SObjectType.Contact.fields.Title.label);
        labelList.add(Schema.SObjectType.Contact.fields.Email.label);
        labelList.add(Schema.SObjectType.Contact.fields.Phone.label);
        labelList.add(Schema.SObjectType.Contact.fields.Department.label);
        labelList.add(Schema.SObjectType.Contact.fields.Age__c.label);
        labelList.add(Schema.SObjectType.Contact.fields.Birthdate.label);
        labelList.add(Schema.SObjectType.Contact.fields.IsActive__c.label);

        // CSV header
        headers = new List<String>();
        for(Integer i = 0; i < labelList.size(); i++){
            if(i > 0){
                headers.add(',');
            }
            headers.add('\"' + labelList.get(i) + '\"');        
        }        
        headers.add('\r\n');
        
        // CSV bodies
        bodies = new List<List<String>>();
        for(Contact con : conList){
            List<String> items = new List<String>();
            items.add('\"' + con.Id + '\"');
            items.add(',');
            items.add(con.Name == null ? '' : '\"' + con.Name + '\"');
            items.add(',');
            items.add(con.Title == null ? '' : '\"' + con.Title + '\"');
            items.add(',');
            items.add(con.Email == null ? '' : '\"' + con.Email + '\"');
            items.add(',');
            items.add(con.Phone == null ? '' : '\"' + con.Phone + '\"');
            items.add(',');
            items.add(con.Department == null ? '' : '\"' + con.Department + '\"');
            items.add(',');
            items.add(con.Age__c == null ? '' : '\"' + con.Age__c + '\"');
            items.add(',');
            items.add(con.Birthdate == null ? '' : '\"' +con.Birthdate.format() + '\"');
            items.add(',');
            items.add(con.IsActive__c == null ? '' : '\"' + con.IsActive__c + '\"');
            items.add('\r\n');
            bodies.add(items);
        }
        
    }
}
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

某SIer勤務。
Salesforceエンジニアです。
日々の学びをつらつらと書いています。
Certified Administrator
Certified Platform DeveloperⅠ
Certified Platform DeveloperⅡ
Certified Sales Cloud Consultant

コメント

コメントする

CAPTCHA


目次