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

165 lines
5.8 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 Vtiful\Kernel\Format;
use Builder\Office\BaseExcel;
use Builder\Exception\MineException;
use Builder\BaseResponse;
use Builder\Office\ExcelPropertyInterface;
class XlsWriter extends BaseExcel implements ExcelPropertyInterface
{
/**
* 导入数据
* @param \Builder\BaseModel $model
* @param \Closure|null $closure
* @return bool
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
* @throws \Exception
*/
public function import(\Builder\BaseModel $model, ?\Closure $closure = null): bool
{
$request = container()->get(\Builder\BaseRequest::class);
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());
$xlsxObject = new \Vtiful\Kernel\Excel(['path' => BASE_PATH . '/runtime/']);
$data = $xlsxObject->openFile($tempFileName)->openSheet()->getSheetData();
unset($data[0]);
$importData = [];
foreach ($data as $item) {
$tmp = [];
foreach ($item as $key => $value) {
$tmp[$this->property[$key]['name']] = (string) $value;
}
$importData[] = $tmp;
}
if ($closure instanceof \Closure) {
return $closure($model, $importData);
}
try {
foreach ($importData as $item) {
$model::create($item);
}
@unlink($tempFilePath);
} catch (\Exception $e) {
@unlink($tempFilePath);
throw new \Exception($e->getMessage());
}
return true;
} else {
return false;
}
}
/**
* 导出excel
* @param string $filename
* @param array|\Closure $closure
* @return \Psr\Http\Message\ResponseInterface
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
public function export(string $filename, array|\Closure $closure): \Psr\Http\Message\ResponseInterface
{
$filename .= '.xlsx';
is_array($closure) ? $data = &$closure : $data = $closure();
$aligns = [
'left' => Format::FORMAT_ALIGN_LEFT,
'center' => Format::FORMAT_ALIGN_CENTER,
'right' => Format::FORMAT_ALIGN_RIGHT,
];
$columnName = [];
$columnField = [];
foreach ($this->property as $item) {
$columnName[] = $item['value'];
$columnField[] = $item['name'];
}
$tempFileName = 'export_' . time() . '.xlsx';
$xlsxObject = new \Vtiful\Kernel\Excel(['path' => BASE_PATH . '/runtime/']);
$fileObject = $xlsxObject->fileName($tempFileName)->header($columnName);
$columnFormat = new Format($fileObject->getHandle());
$rowFormat = new Format($fileObject->getHandle());
$index = 0;
for ($i = 65; $i < (65 + count($columnField)); $i++) {
$columnNumber = chr($i) . '1';
$fileObject->setColumn(
sprintf('%s:%s', $columnNumber, $columnNumber),
$this->property[$index]['width'] ?? mb_strlen($columnName[$index]) * 5,
$columnFormat->align($this->property[$index]['align'] ? $aligns[$this->property[$index]['align']] : $aligns['left'])
->background($this->property[$index]['bgColor'] ?? Format::COLOR_WHITE)
->border(Format::BORDER_THIN)
->fontColor($this->property[$index]['color'] ?? Format::COLOR_BLACK)
->toResource()
);
$index++;
}
// 表头加样式
$fileObject->setRow(
sprintf('A1:%s1', chr(65 + count($columnField))), 20,
$rowFormat->bold()->align(Format::FORMAT_ALIGN_CENTER, Format::FORMAT_ALIGN_VERTICAL_CENTER)
->background(0x4ac1ff)->fontColor(Format::COLOR_BLACK)
->border(Format::BORDER_THIN)
->toResource()
);
$exportData = [];
foreach ($data as $item) {
$yield = [];
foreach ($this->property as $property) {
foreach ($item as $name => $value) {
if ($property['name'] == $name) {
if (!empty($property['dictName'])) {
$yield[] = $property['dictName'][$value];
} else if (!empty($property['dictData'])) {
$yield[] = $property['dictData'][$value];
} else {
$yield[] = $value;
}
break;
}
}
}
$exportData[] = $yield;
}
$response = container()->get(BaseResponse::class);
$filePath = $fileObject->data($exportData)->output();
$response->download($filePath, $filename);
ob_start();
if ( copy($filePath, 'php://output') === false) {
throw new MineException('导出数据失败', 500);
}
$res = $this->downloadExcel($filename, ob_get_contents());
ob_end_clean();
@unlink($filePath);
return $res;
}
}