2020-05-23 14:04:23 +08:00
|
|
|
<?php
|
2020-05-25 19:47:54 +08:00
|
|
|
namespace catcher\library\excel;
|
|
|
|
|
|
|
|
use catcher\CatchUpload;
|
2020-05-25 22:50:51 +08:00
|
|
|
use catcher\exceptions\FailedException;
|
2020-09-08 14:10:27 +08:00
|
|
|
use catcher\Utils;
|
2020-05-25 19:47:54 +08:00
|
|
|
use PhpOffice\PhpSpreadsheet\Exception;
|
|
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
|
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
|
|
|
use think\file\UploadedFile;
|
2020-09-08 14:10:27 +08:00
|
|
|
use think\helper\Str;
|
2020-05-25 19:47:54 +08:00
|
|
|
|
|
|
|
class Excel
|
|
|
|
{
|
|
|
|
use MacroExcel;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var ExcelContract $excel
|
|
|
|
*/
|
|
|
|
protected $excel;
|
|
|
|
|
|
|
|
protected $sheets;
|
|
|
|
|
|
|
|
protected $spreadsheet = null;
|
|
|
|
|
2020-09-08 14:10:27 +08:00
|
|
|
protected $extension = 'xlsx';
|
|
|
|
|
2020-05-25 19:47:54 +08:00
|
|
|
/**
|
|
|
|
* save
|
|
|
|
*
|
|
|
|
* @time 2020年05月25日
|
|
|
|
* @param ExcelContract $excel
|
|
|
|
* @param $path
|
2020-09-08 14:10:27 +08:00
|
|
|
* @param string $disk
|
|
|
|
* @return mixed
|
2020-05-25 19:47:54 +08:00
|
|
|
* @throws Exception
|
|
|
|
*/
|
2020-09-08 14:10:27 +08:00
|
|
|
public function save(ExcelContract $excel, $path, $disk = 'local')
|
2020-05-25 19:47:54 +08:00
|
|
|
{
|
|
|
|
$this->excel = $excel;
|
|
|
|
|
2020-05-25 19:55:25 +08:00
|
|
|
$this->init();
|
|
|
|
|
2020-09-08 14:10:27 +08:00
|
|
|
!is_dir($path) && mkdir($path, 0777, true);
|
|
|
|
|
|
|
|
$file = $path . date('YmdHis').Str::random(6) . '.' .$this->extension;
|
|
|
|
Factory::make($this->extension)
|
2020-05-25 22:50:51 +08:00
|
|
|
->setSpreadsheet($this->spreadsheet)
|
2020-09-08 14:10:27 +08:00
|
|
|
->save($file);
|
2020-05-25 22:50:51 +08:00
|
|
|
|
2020-09-08 14:10:27 +08:00
|
|
|
if (!file_exists($file)) {
|
|
|
|
throw new FailedException($file . ' generate failed');
|
2020-05-25 22:50:51 +08:00
|
|
|
}
|
|
|
|
|
2020-09-08 14:10:27 +08:00
|
|
|
if ($disk) {
|
|
|
|
$file = $this->upload($disk, $file);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ['url' => $file];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set extension
|
|
|
|
*
|
|
|
|
* @time 2020年09月08日
|
|
|
|
* @param $extension
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setExtension($extension)
|
|
|
|
{
|
|
|
|
$this->extension = $extension;
|
2020-05-25 19:55:25 +08:00
|
|
|
|
2020-09-08 14:10:27 +08:00
|
|
|
return $this;
|
2020-05-25 19:55:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* init excel
|
|
|
|
*
|
|
|
|
* @time 2020年05月25日
|
|
|
|
* @throws Exception
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
protected function init()
|
|
|
|
{
|
2020-05-26 22:55:02 +08:00
|
|
|
$this->setMemoryLimit();
|
2020-05-25 19:47:54 +08:00
|
|
|
// register worksheet for current excel
|
|
|
|
$this->registerWorksheet();
|
2020-05-25 19:55:25 +08:00
|
|
|
// before save excel
|
|
|
|
$this->before();
|
2020-05-25 19:47:54 +08:00
|
|
|
// set excel title
|
|
|
|
$this->setTitle();
|
|
|
|
// set excel headers
|
|
|
|
$this->setExcelHeaders();
|
|
|
|
// set cell width
|
|
|
|
$this->setSheetWidth();
|
|
|
|
// set worksheets
|
|
|
|
$this->setWorksheets();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 设置 sheets
|
|
|
|
*
|
|
|
|
* @time 2020年05月25日
|
|
|
|
* @throws Exception
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
protected function setWorksheets()
|
|
|
|
{
|
|
|
|
$keys= $this->getKeys();
|
|
|
|
|
|
|
|
$isArray = $this->arrayConfirm();
|
|
|
|
|
|
|
|
$worksheet = $this->getWorksheet();
|
|
|
|
|
|
|
|
if (empty($keys)) {
|
|
|
|
if ($isArray) {
|
|
|
|
foreach ($this->excel->sheets() as $sheet) {
|
|
|
|
$worksheet->fromArray($sheet, null, $this->start . $this->row);
|
|
|
|
$this->incRow();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach ($this->excel->sheets() as $sheet) {
|
|
|
|
$worksheet->fromArray($sheet->toArray(), null, $this->start . $this->row);
|
|
|
|
$this->incRow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ($isArray) {
|
|
|
|
foreach ($this->excel->sheets() as $sheet) {
|
|
|
|
$worksheet->fromArray($this->getValuesByKeys($sheet, $keys), null, $this->start . $this->row);
|
|
|
|
$this->incRow();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach ($this->excel->sheets() as $sheet) {
|
|
|
|
$worksheet->fromArray($this->getValuesByKeys($sheet->toArray(), $keys), null, $this->start . $this->row);
|
|
|
|
$this->incRow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 判断 sheet 是否是 array 类型
|
|
|
|
*
|
|
|
|
* @time 2020年05月25日
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
protected function arrayConfirm()
|
|
|
|
{
|
|
|
|
$sheets = $this->excel->sheets();
|
|
|
|
|
|
|
|
$array = true;
|
|
|
|
|
|
|
|
foreach ($sheets as $sheet) {
|
|
|
|
$array = is_array($sheet);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $array;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 获取 item 特定 key 的值
|
|
|
|
*
|
|
|
|
* @time 2020年05月25日
|
|
|
|
* @param array $item
|
|
|
|
* @param array $keys
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
protected function getValuesByKeys(array $item, array $keys)
|
|
|
|
{
|
|
|
|
$array = [];
|
|
|
|
|
|
|
|
foreach ($keys as $key) {
|
|
|
|
$array[] = $item[$key];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $array;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 设置 Excel 头部
|
|
|
|
*
|
|
|
|
* @time 2020年05月23日
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
protected function setExcelHeaders()
|
|
|
|
{
|
|
|
|
$worksheet = $this->getWorksheet();
|
|
|
|
|
|
|
|
// get columns
|
|
|
|
$columns = $this->getSheetColumns();
|
|
|
|
|
|
|
|
// get start row
|
|
|
|
$startRow = $this->getStartRow();
|
|
|
|
|
|
|
|
foreach ($this->excel->headers() as $k => $header) {
|
|
|
|
$worksheet->getCell($columns[$k] . $startRow)->setValue($header);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->incRow();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get spreadsheet
|
|
|
|
*
|
|
|
|
* @time 2020年05月25日
|
|
|
|
* @return Spreadsheet
|
|
|
|
*/
|
|
|
|
protected function getSpreadsheet()
|
|
|
|
{
|
|
|
|
if (!$this->spreadsheet) {
|
|
|
|
$this->spreadsheet = new Spreadsheet();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->spreadsheet;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 获取 active sheet
|
|
|
|
*
|
|
|
|
* @time 2020年05月25日
|
|
|
|
* @throws Exception
|
|
|
|
* @return Worksheet
|
|
|
|
*/
|
|
|
|
protected function getWorksheet()
|
|
|
|
{
|
|
|
|
return $this->getSpreadsheet()->getActiveSheet();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* upload
|
|
|
|
*
|
|
|
|
* @time 2020年05月25日
|
|
|
|
* @param $disk
|
|
|
|
* @param $path
|
|
|
|
* @return string
|
|
|
|
* @throws \Exception
|
|
|
|
*/
|
|
|
|
protected function upload($disk, $path)
|
|
|
|
{
|
2020-09-08 14:10:27 +08:00
|
|
|
if ($disk == 'local') {
|
|
|
|
return $this->local($path);
|
|
|
|
}
|
2020-05-25 19:47:54 +08:00
|
|
|
$upload = new CatchUpload;
|
|
|
|
|
|
|
|
return ($disk ? $upload->setDriver($disk) : $upload)->upload($this->uploadedFile($path));
|
|
|
|
}
|
|
|
|
|
2020-09-08 14:10:27 +08:00
|
|
|
/**
|
|
|
|
* 返回本地下载地址
|
|
|
|
*
|
|
|
|
* @param $path
|
|
|
|
* @time 2020年09月08日
|
|
|
|
* @return mixed
|
|
|
|
*/
|
|
|
|
protected function local($path)
|
|
|
|
{
|
|
|
|
return \config('filesystem.disks.local')['domain'] . '/' .
|
|
|
|
|
|
|
|
str_replace('\\', '/', str_replace(Utils::publicPath(), '', $path));
|
|
|
|
}
|
2020-05-25 19:47:54 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* get uploaded file
|
|
|
|
*
|
|
|
|
* @time 2020年05月25日
|
|
|
|
* @param $file
|
|
|
|
* @return UploadedFile
|
|
|
|
*/
|
|
|
|
protected function uploadedFile($file)
|
|
|
|
{
|
|
|
|
return new UploadedFile($file, pathinfo($file, PATHINFO_BASENAME));
|
|
|
|
}
|
|
|
|
}
|