想要实现功能:
在导入该excel时,想要获取数组
$array = [
['xx公司','A部门','a中心'],
['xx公司','A部门','b中心'],
['xx公司','A部门','c中心'],
['xx公司','D部门','d中心'],
];
因为有合并单元格,所以读取excel内容A2:A5 的内容只有A2为XX公司,其余的均为null,所以我们只要获取到excel中合并单元格的范围,就可以将其余的null值赋予单元格的第一位;在phpExcel中获取单元格合并范围的函数为
getMergeCells()
但是在laravel excel中使用该函数获取的均为空数组,究其原因是默认读取excelData 数据设置
setReadDataOnly(true)
导致无法正确的读取excel具体格式,所以只要更改真个属性为false,就可以正确的使用getMergeCells()
但是我没有找到如何更改laravel excel 的这个属性所以只能用这种笨方法,用phpexcel原生方法设置setReadDataOnly(false)然后获取phpexcel原生的getMergeCells(),然后给laravel excel中返回结果赋值:
<?php
namespace App\Imports;
use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\WithCalculatedFormulas;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Events\BeforeImport;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
/**
* 获取合并数据的excel 并将合并的单元格数据赋值:当前合并第一个单元格的数据,调用array(),方法可以获取正确的数据
* Class mergeCellBasicImport
* @package App\Imports
*/
class mergeCellBasicImport implements WithEvents,ToArray, WithStartRow, WithCalculatedFormulas,WithMultipleSheets
{
public $filePath;
public $startRow = 2;
public $mergeCells = [];
public function __construct($startRow = 2, $filePath = '')
{
$this->filePath = $filePath;
}
/**
* 将合并数据进行赋值,调用eg: $import = new mergeCellBasicImport(2,$filePath);$array = $excel->toArray($import,$file);$array = $import->array($array);
* @param array $array
* @return array
* @throws \PhpOffice\PhpSpreadsheet\Exception
*/
public function array(array $array): array
{
if ($this->mergeCells) {
$startRow = $this->startRow;
foreach ($this->mergeCells as $key => $mergeCells) {
if ($mergeCells && is_array($mergeCells)) {
foreach ($mergeCells as $mergeCell) {
[$begin, $end] = Coordinate::getRangeBoundaries($mergeCell);
//要和数组对应行列保持一直 数据对应: $array[$key][$row][$col],所以要进行行数据 - startRow ;列数据 - 1
$beginRow = $begin[1] - $startRow;
$beginCol = Coordinate::columnIndexFromString($begin[0]) - 1;
$endRow = $end[1] - $startRow;
$endCol = Coordinate::columnIndexFromString($end[0]) - 1;
$value = $array[$key][$beginRow][$beginCol];
for ($intCol = $beginCol; $intCol <= $endCol; $intCol++) {
for ($intRow = $beginRow; $intRow <= $endRow; $intRow++) {
$array[$key][$intRow][$intCol] = $value;
}
}
}
}
}
}
return $array;
}
public function registerEvents(): array
{
return [
BeforeImport::class => function (BeforeImport $event) {
//因为我无法设置laravel-excel中的setReadDataOnly 为false,所以在原生iof中设置setReadDataOnly 为false,获取合并数据
$iofReader = $event->reader->getPhpSpreadsheetReader();
$iofReader->setReadDataOnly(false);
$iofLoad = $iofReader->load($event->getConcernable()->filePath);
$mergeCells = [];
foreach ($iofLoad->getAllSheets() as $key => $item) {
$mergeCells[$key] = $item->getMergeCells();
}
$event->getConcernable()->mergeCells = $mergeCells;
},
];
}
public function sheets(): array
{
return [
0 => new self()
];
}
public function startRow(): int
{
return $this->startRow;
}
}
调用的方法是:
$import = new mergeCellBasicImport(2,$request->file('file')->getRealPath());
$sheets =$excel->toArray($import, $request->file('file'));
$sheet = $import->array($sheets)[0];
利用toArray的方式获取对应数组,再利用array()方法进行将数据变成想要的格式,dd打印结果如下:
array:4 [
0 => array:3 [
0 => "XX公司"
1 => "A部门"
2 => "a中心"
]
1 => array:3 [
0 => "XX公司"
1 => "A部门"
2 => "b中心"
]
2 => array:3 [
0 => "XX公司"
1 => "A部门"
2 => "c中心"
]
3 => array:3 [
0 => "XX公司"
1 => "D部门"
2 => "d中心"
]
]