hyperf-view/builder/Office/Excel/PhpOffice.php

180 lines
6.7 KiB
PHP

<?php
declare(strict_types=1);
/**
* MineAdmin is committed to providing solutions for quickly building web applications
* Please view the LICENSE file that was distributed with this source code,
* For the full copyright and license information.
* Thank you very much for using MineAdmin.
*
* @Author X.Mo<root@imoi.cn>
* @Link https://gitee.com/xmo/MineAdmin
*/
namespace Builder\Office\Excel;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Color;
use Builder\Exception\MineException;
use Builder\Office\ExcelPropertyInterface;
use Builder\Office\BaseExcel;
class PhpOffice extends BaseExcel implements ExcelPropertyInterface
{
/**
* 导入
* @param \Builder\BaseModel $model
* @param \Closure|null $closure
* @return bool
* @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function import(\Builder\BaseModel $model, ?\Closure $closure = null): bool
{
$request = container()->get(\Builder\BaseRequest::class);
$data = [];
if ($request->hasFile('file')) {
$file = $request->file('file');
$tempFileName = 'import_'.time().'.'.$file->getExtension();
$tempFilePath = BASE_PATH . '/runtime/'. $tempFileName;
file_put_contents($tempFilePath, $file->getStream()->getContents());
$reader = IOFactory::createReader(IOFactory::identify($tempFilePath));
$reader->setReadDataOnly(true);
$sheet = $reader->load($tempFilePath);
$endCell = isset($this->property) ? chr(count($this->property) + 65) : null;
try {
foreach ($sheet->getActiveSheet()->getRowIterator(2) as $row) {
$temp = [];
foreach ($row->getCellIterator('A', $endCell) as $index => $item) {
$propertyIndex = ord($index) - 65;
if (isset($this->property[$propertyIndex])) {
$temp[$this->property[$propertyIndex]['name']] = $item->getFormattedValue();
}
}
if (! empty($temp)) {
$data[] = $temp;
}
}
unlink($tempFilePath);
} catch (\Throwable $e) {
unlink($tempFilePath);
throw new MineException($e->getMessage());
}
} else {
return false;
}
if ($closure instanceof \Closure) {
return $closure($model, $data);
}
foreach ($data as $datum) {
$model::create($datum);
}
return true;
}
/**
* 导出
* @param string $filename
* @param array|\Closure $closure
* @return \Psr\Http\Message\ResponseInterface
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function export(string $filename, array|\Closure $closure): \Psr\Http\Message\ResponseInterface
{
$spread = new Spreadsheet();
$sheet = $spread->getActiveSheet();
$filename .= '.xlsx';
is_array($closure) ? $data = &$closure : $data = $closure();
// 表头
$titleStart = 'A';
foreach ($this->property as $item) {
$headerColumn = $titleStart . '1';
$sheet->setCellValue($headerColumn, $item['value']);
$style = $sheet->getStyle($headerColumn)->getFont()->setBold(true);
$columnDimension = $sheet->getColumnDimension($titleStart);
empty($item['width']) ? $columnDimension->setAutoSize(true) : $columnDimension->setWidth((float) $item['width']);
empty($item['align']) || $sheet->getStyle($headerColumn)->getAlignment()->setHorizontal($item['align']);
empty($item['headColor']) || $style->setColor(new Color(str_replace('#', '', $item['headColor'])));
if (!empty($item['headBgColor'])) {
$sheet->getStyle($headerColumn)->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
->getStartColor()->setARGB(str_replace('#', '', $item['headBgColor']));
}
$titleStart++;
}
$generate = $this->yieldExcelData($data);
// 表体
try {
$row = 2;
while ($generate->valid()) {
$column = 'A';
foreach ($generate->current() as $name => $value) {
$columnRow = $column . $row;
$annotation = '';
foreach ($this->property as $item) {
if ($item['name'] == $name) {
$annotation = $item;
break;
}
}
if (!empty($annotation['dictName'])) {
$sheet->setCellValue($columnRow, $annotation['dictName'][$value]);
} else if (!empty($annotation['dictData'])) {
$sheet->setCellValue($columnRow, $annotation['dictData'][$value]);
} else {
$sheet->setCellValue($columnRow, $value . "\t");
}
if (! empty($item['color'])) {
$sheet->getStyle($columnRow)->getFont()
->setColor(new Color(str_replace('#', '', $annotation['color'])));
}
if (! empty($item['bgColor'])) {
$sheet->getStyle($columnRow)->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
->getStartColor()->setARGB(str_replace('#', '', $annotation['bgColor']));
}
$column++;
}
$generate->next();
$row++;
}
} catch (\RuntimeException $e) {}
$writer = IOFactory::createWriter($spread, 'Xlsx');
ob_start();
$writer->save('php://output');
$res = $this->downloadExcel($filename, ob_get_contents());
ob_end_clean();
$spread->disconnectWorksheets();
return $res;
}
protected function yieldExcelData(array &$data): \Generator
{
foreach ($data as $dat) {
$yield = [];
foreach ($this->property as $item) {
$yield[ $item['name'] ] = $dat[$item['name']] ?? '';
}
yield $yield;
}
}
}