BatchExportService.php 3.8 KB
<?php

namespace App\Services;

use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

/**
 * 批量导出
 * Class BatchExportService
 * @package App\Services
 * @author zbj
 * @date 2023/5/8
 */
class BatchExportService
{

    private $name = '';
    /**
     * @var array
     */
    private $data = [];


    /**
     * @var null | \PhpOffice\PhpSpreadsheet\Spreadsheet;
     */
    private $spreadsheet = null;


    /**
     * 包头与字段映射
     * @var array
     */
    private $head = [];


    public function __construct($name)
    {
        $this->name = $name;
        $this->spreadsheet = new Spreadsheet();
        $this->spreadsheet->setActiveSheetIndex(0);
    }

    /**
     * config hook
     * @param $callback
     * @return $this
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     */
    public function config($callback)
    {
        if(is_callable($callback)) {
            $callback($this->spreadsheet->getActiveSheet(),$this->spreadsheet);
        }
        return $this;
    }

    /**
     * 设置表头
     * @param array $data
     * @return $this
     */
    public function head($map = [])
    {
        $this->head = $map;
        return $this;
    }

    /**
     * @param $data
     * @return $this
     */
    public function data($data)
    {
        $this->data = $data;
        return $this;
    }

    /**
     * @return false|string
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
     * @author zbj
     * @date 2023/5/8
     */
    public function save()
    {
        $file = "export/".date('Y-m-d')."/{$this->name}_" . date('YmdHis') . ".xlsx";
        $filename = public_path('runtime/'.$file);

        if (!is_dir(dirname($filename))) {
            @mkdir(dirname($filename),0755, true);
        }
        $this->render();

        $writer = new Xlsx($this->spreadsheet);
        $writer->save($filename);
        if(file_exists($filename) && filesize($filename)) {
            return $file;
        }
        return false;
    }


    /**
     * 进行数据渲染
     * 遍历所有的单元格处理文件,进行数据处理
     * @return $this
     * @author zbj
     * @date 2023/5/8
     */
    protected function render()
    {

        $map = [];
        $sheet = $this->spreadsheet->getActiveSheet();
        $i = 0;
        foreach ($this->head as $k=>$title) {
            $chr = chr(65+$i);
            $map[$chr] = $k;
            if(is_array($title)) {
                $title = $title[0];
            }
            $sheet->setCellValue($chr . "1", $title);
            $i++;
        }
        foreach ($this->data as $k=>$item) {
            foreach ($map as $chr => $field) {
                if(is_array($this->head[$field]) && is_callable($this->head[$field][1])) { //TODO 进行字段内容的处理
                    $this->head[$field][1]($sheet, $chr . ($k + 2), $item[$field]);
                }
                $sheet->setCellValue($chr . ($k + 2), $this->getDataValue($field, $item));
            }
        }
        return $this;
    }

    /**
     * 读取指定字段的value, 支持"."形式指定多维数组
     * @param $name
     * @param $data
     * @return mixed|null
     * @author zbj
     * @date 2023/5/8
     */
    protected function getDataValue($name, $data)
    {
        if(false === strpos($name, '.')) {
            return $data[$name] ?? null;
        }
        $name    = explode('.', $name);
        $name[0] = strtolower($name[0]);

        // 按.拆分成多维数组进行判断
        foreach ($name as $val) {
            if (isset($data[$val])) {
                $data = $data[$val];
            } else {
                $data = null;
                break;
            }
        }
        return $data;
    }
}