匯出匯入的功能是平時開發比較常見的功能了,Laravel Maatwebsite-Excel更新了3.x,這次就自己封裝一個簡單的通用版並記錄一下遇到的問題。
PHP:
^7.3.4
Laravel:
^5.7
composer require maatwebsite/excel
建立檔案
然後在composer.json新增
然後執行:
composer dump-autoload
export.php內
<?php
namespace App\Http\Libraries\ExcelUtil;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Events\AfterSheet;
class export implements FromCollection,WithHeadings, WithEvents
{
protected $data;
protected $headings;
protected $sheetName; //設定sheet頁名稱
protected $columnWidth = [];//設定列寬 key:列 value:寬
protected $rowHeight = []; //設定行高 key:行 value:高
protected $mergeCells = []; //合併單元格 key:第一個單元格 value:第二個單元格
protected $font = []; //設定字型 key:A1:K8 value:11
protected $bold = []; //設定粗體 key:A1:K8 value:true
protected $background = []; //設定背景顏色 key:A1:K8 value:#F0F0F0F
protected $vertical = []; //設定定位 key:A1:K8 value:center
protected $horizontal = []; //設定水平定位 key:A1:K8 value:center
protected $wrapText = []; //設定是否自動換行 key:A1:K8 value:bool
//設定頁面屬性時如果無效 更改excel格式嘗試即可
//建構函式傳值
public function __construct($data, $headings)
{
$this->data = $data;
$this->headings = $headings;
$this->createData();
}
public function headings(): array
{
return $this->headings;
}
//陣列轉集合
public function collection()
{
return new Collection($this->data);
}
//業務程式碼
public function createData()
{
$this->data = collect($this->data)->toArray();
}
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
//設定sheet頁名稱
$event->getSheet()->getDelegate()->setTitle($this->sheetName);
//設定自動換行
foreach ($this->wrapText as $column => $bool) {
$event->sheet->getDelegate()
->getStyle($column)
->getAlignment()
->setWrapText(true);
}
//設定列寬
foreach ($this->columnWidth as $column => $width) {
$event->sheet->getDelegate()
->getColumnDimension($column)
->setWidth($width);
}
//設定行高,$i為資料行數
foreach ($this->rowHeight as $row => $height) {
$event->sheet->getDelegate()
->getRowDimension($row)
->setRowHeight($height);
}
//設定區域單元格垂直居中
foreach ($this->vertical as $region => $position) {
$event->sheet->getDelegate()
->getStyle($region)
->getAlignment()
->setVertical($position);
}
//設定區域單元格水平定位
foreach ($this->horizontal as $region => $position) {
$event->sheet->getDelegate()
->getStyle($region)
->getAlignment()
->setHorizontal($position);
}
//設定區域單元格字型
foreach ($this->font as $region => $value) {
$event->sheet->getDelegate()
->getStyle($region)
->getFont()
->setSize($value);
}
//設定區域單元格字型粗體
foreach ($this->bold as $region => $bool) {
$event->sheet->getDelegate()
->getStyle($region)
->getFont()
->setBold($bool);
}
//設定區域單元格背景顏色
foreach ($this->background as $region => $item) {
$event->sheet->getDelegate()->getStyle($region)->applyFromArray([
'fill' => [
'fillType' => 'linear', //線性填充,類似漸變
'startColor' => [
'rgb' => $item //初始顏色
],
//結束顏色,如果需要單一背景色,請和初始顏色保持一致
'endColor' => [
'argb' => $item
]
]
]);
}
//合併單元格
foreach ($this->mergeCells as $start => $end) {
$event->sheet->getDelegate()->mergeCells($start.':'.$end);
}
}
];
}
/**
* @return array
* @2020/3/22 10:33
*/
public function setSheetName(string $sheetName)
{
$this->sheetName = trim($sheetName);
}
/**
* @return array
* @2020/3/22 10:33
* [
* A1:K7 => true
* ]
*/
public function setWrapText (array $wrapText)
{
$this->wrapText = array_change_key_case($this->symbol($wrapText),CASE_UPPER);
}
/**
* @return array
* @2020/3/22 10:33
* [
* A1:K7 => center
* ]
*/
public function setVertical (array $vertical)
{
$this->vertical = array_change_key_case($this->symbol($vertical),CASE_UPPER);
}
/**
* @return array
* @2020/3/22 10:33
* [
* A1:K7 => center
* ]
*/
public function setHorizontal (array $horizontal)
{
$this->horizontal = array_change_key_case($this->symbol($horizontal),CASE_UPPER);
}
/**
* @return array
* @2020/3/22 10:33
* [
* 'B' => 40,
* 'C' => 60
* ]
*/
public function setColumnWidth (array $columnwidth)
{
$this->columnWidth = array_change_key_case($columnwidth, CASE_UPPER);
}
/**
* @return array
* @2020/3/22 10:33
* [
* 1 => 40,
* 2 => 60
* ]
*/
public function setRowHeight (array $rowHeight)
{
$this->rowHeight = $rowHeight;
}
/**
* @return array
* @2020/3/22 10:33
* [
* A1:K7 => 12
* ]
*/
public function setFont (array $fount)
{
$this->font = array_change_key_case($fount, CASE_UPPER);
}
/**
* @return array
* @2020/3/22 10:33
* [
* A1:K7 => true
* ]
*/
public function setBold (array $bold)
{
$this->bold = array_change_key_case($bold, CASE_UPPER);
}
/**
* @return array
* @2020/3/22 10:33
* [
* A1:K7 => F0FF0F
* ]
*/
public function setBackground (array $background)
{
$this->background = array_change_key_case($background, CASE_UPPER);
}
public function symbol ($param) {
$record = [];
$count = count($this->data) + 1;//加上表頭
foreach ($param as $key => $value) {
$str = str_replace("*", $count, $key);
$record[$str] = $value;
}
return $record;
}
}
在控制器內呼叫。
use App\Http\Libraries\ExcelUtil\export;
use Maatwebsite\Excel\Facades\Excel;
public function export () {
$data = [];//要匯出的資料
$header = [];//匯出頭 例如:["名稱", "價格", "數量"]
//匯出的頭和匯出的資料的長度要一致
$excel = new export($data, $header);
//從上面的封裝類中可以看到都有哪些屬性可以設定,下面是一些例子,大寫字母是列,字母后面的數字是行,支援*號設定整行或整列。
//例如表頭是["名稱", "價格", "數量"],就有下面的設定
$excel->setColumnWidth(['A' => 40,'B' => 40, 'C' => 40]);//設定單元格寬度
$excel->setRowHeight([1 => 40]);//設定行高
$excel->setFont(['A1:C1' => 12]);//設定字型大小
$excel->setBold(['A1:C1' => true]);//設定字型粗細
$excel->setBackground(['A1:C1' => '808080']);//設定背景色
return Excel::download($excel, '匯出的檔名.xlsx');
}
根據自己的需求可設定行、列、字型、背景顏色等;
樣式在有的excel格式上不起作用,具體不知道為什麼,沒有再去研究了;
數字過大時展示科學計數法問題,我借鑑了一個大佬的方法
開啟預設配置檔案vendor/maatwebsite/excel/src/DefaultValueBinder.php,新增
use PhpOffice\PhpSpreadsheet\Cell\DataType;
函式內部新增:
//超過10位的數字轉文字格式,防止科學計數法
if (strlen($value) > 10) {
$cell->setValueExplicit($value, DataType::TYPE_STRING);
return true;
}
檔案程式碼最終如下:
namespace Maatwebsite\Excel;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder as PhpSpreadsheetDefaultValueBinder;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
class DefaultValueBinder extends PhpSpreadsheetDefaultValueBinder
{
/**
* @param Cell $cell Cell to bind value to
* @param mixed $value Value to bind in cell
*
* @return bool
*/
public function bindValue(Cell $cell, $value)
{
if (is_array($value)) {
$value = \json_encode($value);
}
//超過10位的數字轉文字格式,防止科學計數法
if (strlen($value) > 10) {
$cell->setValueExplicit($value, DataType::TYPE_STRING);
return true;
}
return parent::bindValue($cell, $value);
}
}
如果要把匯出檔案先下載到伺服器上可以使用store方法
import.php內
<?php
namespace App\Http\Libraries\ExcelUtil;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
class import implements ToCollection
{
public $data;
protected $delTitle;
/**
*
* @param $title integer //去掉幾行標題 預設一行
*/
public function __construct($delTitle = 1)
{
$this->delTitle = $delTitle;
}
/**
* @param Collection $rows
* @2020/3/23 9:53
*/
public function collection(Collection $rows)
{
$this->delTitle($rows);
//$rows 是陣列格式
$this->data = $rows;
}
public function delTitle (&$rows) {
$rows = $rows->slice($this->delTitle)->values();
}
}
控制器內呼叫
public function import (Request $request) {
$path = $request->file('file');
$delTitle = 1;//指定頭行數 刪除它
$excel = new import($delTitle);
Excel::import($excel, $path->getRealPath());
dd($excel->data); //這個地方就可以獲取到檔案內的集合了
//在這可以驗證資料 入庫操作
}
程式碼都是貼上就可以使用的,記錄完畢
本作品採用《CC 協議》,轉載必須註明作者和本文連結