PHP導出Excel數據導出,前端進度條實現方式

效果如上,結合layer組件以及ajax分頁實現,具體代碼如下

前端代碼

<a href="javascript:;" onclick="exportData()">用戶數據導出</a>
// 執行事件
function exportData() {
    var loading = layer.load(1, {
        shade: [0.4,'#000']
    }); // 彈出loading層
    var formData = $(".layui-form").serialize(); // 獲取搜索表單數據
    $.post("{:url('download')}",formData,function (res) {
        layer.close(loading);
        if(res.code == 1){
            doConfirm(res.data.total); // 彈出下載確認
        }else{
            layer.msg('沒有可導出數據~');
        }
    })
}
/**
* 返回可執行數據後分頁處理
* num 數據總數
**/
function doConfirm(num) {
    if(num == 0){
        layer.msg('沒有可導出數據');
        return ;
    }
    layer.confirm('共有'+num+'個用戶數據需要導出,導出時間可能會較長,確認執行嗎?',function () {
        layer.closeAll();
        layer.open({
            type: 1, title: false, area: ['560px', '135px'], anim: 2, shadeClose: false, end: function () {
                doAjax = false;
            }, content: '' +
                '<div class="padding-30 padding-bottom-0" style="width:500px" data-export-load>' +
                '   <div class="layui-elip nowrap" data-message-title>數據導出進度</div>' +
                '   <div class="margin-top-15 layui-progress layui-progress-big" lay-showPercent="yes"><div class="layui-progress-bar transition" lay-percent="10.00%"></div></div>' +
                '   <div class="margin-top-15" data-load-tips>正在導出,請等待,請勿關閉窗口,否則導出失敗~~</div>' +
                '</div>'
        });
        var pageNum = 1;
        (function loadprocess(page,that) {
            that = this,this.$box = $("[data-export-load]");
            this.$area = that.$box.find('textarea'), this.$title = that.$box.find('[data-message-title]');
            this.$percent = that.$box.find('.layui-progress div');
            this.setState = function (status, message) {
                if (status === 1) { // 已完成
                    that.$title.html('<b class="color-text">' + message + '</b>').addClass('text-center');
                    that.$percent.addClass('layui-bg-blue').removeClass('layui-bg-green layui-bg-red');
                } else if (status === 2) {
                    if (message.indexOf('>>>') > -1) {
                        that.$title.html('<b class="color-blue">' + message + '</b>').addClass('text-center');
                    } else {
                        that.$title.html('<b class="color-blue">正在處理:</b>' + message).removeClass('text-center');
                    }
                    that.$percent.addClass('layui-bg-blue').removeClass('layui-bg-green layui-bg-red');
                } else if (status === 3) { // 已完成
                    that.$title.html('<b class="color-green">' + message + '</b>').addClass('text-center');
                    that.$percent.addClass('layui-bg-green').removeClass('layui-bg-blue layui-bg-red');
                }
            };
            var formData = $(".layui-form").serialize() + "&page="+pageNum; // 表單數據加 當前分頁數
            $.post("{:url('downpage')}",formData,function (res) {
                that.setState(parseInt(res.code), res.message); // 返回數據
                that.$percent.attr('lay-percent', (parseFloat(res.data.progress || '0.00').toFixed(2)) + '%'), layui.element.render(); // 更新進度條
                if(res.code == 1){ // 進行中
                    pageNum = res.data.page;
                    setTimeout(function () {
                        loadprocess(pageNum); // 循環執行
                    },2000);
                }else if(res.code == 3){ // 已完成
                    var downLink = "<a href='"+res.data.downurl+"' target='_blank'>《~點我下載~》</a>";
                    $("[data-load-tips]").html('導出完成,請點擊下載保存至本地;'+downLink);
                }

            })
        })(num);
    });
}

後端代碼,以Thinkphp爲例

1、安裝phpspreadsheet

composer require phpoffice/phpspreadsheet

2、邏輯代碼,實現分頁處理以及返回執行進度

<?php
namespace app\index\controller;

use lib\Dir;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

class Index {
    
    /**
     * 返回當前需導出數據總數
     * @return json
    **/
    public function download(){
        if(!$this->request->isAjax()){
            return 'error';die;
        }
        $param = $this->request->param();
        $name = input('name','');
        $where[] = ['parent_id', '=','1'];
        $query = $this->app->db->name('member');

        $total = $query->where($where)->count();
        return json(['code'=>1,'data'=>['total'=>$total]]);
    }

    /**
     * 執行數據分頁處理
    */
    public function downpage(){
        $param = $this->request->param();
        // 創建存儲目錄
        $excelPath = $this->app->getRootPath()."public/excel/excel_".$this->user['id'].DIRECTORY_SEPARATOR;
        $zipPath = $this->app->getRootPath()."public/excel/";
        if(!is_dir($excelPath)){
            mkdir($excelPath,0775);
        }
        // 導出用戶
        $page = $param['page'];
        $query = $this->app->db->name('member');

        $total = $query->where($where)->order('create_at desc')->count();
        $limit = 2; // 每次執行2條
        $totalSize = ceil($total / $limit);

        $progress = ceil($page * 100 / $totalSize); // 執行進度

        if($page < $totalSize){
            $list = $query->where($where)->page((int)$page,(int)$limit)->select()->toArray();
            // 執行數據excel數據寫入操作
            $this->exp_userDetail($list,"某某名下會有數據",$excelPath);
            //
            return json(['code'=>1,'data'=>['progress'=>$progress,'page'=>$page+1],'message'=>'>>>正在導出數據中,請勿關閉窗口<<<']);
        }
        if($progress >= 100){
            // 把所有文件生成壓縮包
            $zipName = $this->userData['nickname'].'_'.date('YmdHi').'_報表數據.zip';
            $this->createZip($excelPath, $zipPath.$zipName);
            // 刪除所生成文件夾
            $dir = new \lib\Dir();
            $dir->delAll($excelPath);
            return json(['code'=>3,'data'=>['progress'=>$progress,'page'=>$page,'downurl'=>"/excel/".$zipName],'message'=>'>>>導出完成<<<']);
        }
    }

    /**
     * 生成壓縮包
     * @param $path
     * @param $zipName
     */
    protected function createZip($path,$zipName){
        $zip = new \ZipArchive();
        if($zip->open($zipName,\ZipArchive::CREATE) === true){
            $dir = opendir($path);
            while ($file = readdir($dir)){
                if(is_file($path.$file)){
                    $zip->addFile($path.$file,$file);
                }
            }
            $zip->close();
        }
    }

    /**
     * 數據寫入excel文件
     * @param $list Array 數據集
     * @param $name String 生成文件名
     * @param $path String 文件生成路徑
     */
    protected function exp_userDetail($list,$name,$path){
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $title = ['姓名', '手機號碼'];
        $data = [];
        foreach($list as $vo){
            $data[] = [
                'nickname'=> $vo['nickname'],
                'phone'=> $vo['phone'],
            ];
        }
        foreach ($title as $key => $value) {
            // 單元格內容寫入
            $sheet->setCellValueByColumnAndRow($key + 1, 1, $value);
        }
        $row = 2; // 從第二行開始
        foreach ($data as $item) {
            $column = 1;
            foreach ($item as $value) {
                // 單元格內容寫入
                $sheet->setCellValueByColumnAndRow($column, $row, $value);
                $column++;
            }
            $row++;
        }
        $writer = new Xlsx($spreadsheet);
        // 保存數據
        $writer->save($path.$name.'_詳細報表.xlsx');
    }   
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章