spreadsheet = new Spreadsheet(); $this->excel = $this->spreadsheet->getActiveSheet(); $this->projectName = $this->getProjectName(); $this->path = $_SERVER['DOCUMENT_ROOT'] . '/' . $this->getProjectExcelPath() . '/' . $path; $this->projectExcelPath = $path; $this->data = $data; $this->title = $title; $this->getUrl(); if ($this->checkWindows()) { if (!is_dir($this->path)) { mkdir($this->path, 0777, true); chmod($this->path, 0777); } } } /** * 获取项目多字段地址 */ private function getProjectExcelPath(): string { $url = $_SERVER['REQUEST_URI']; $parts = explode('/', $url); $keys = array_keys($parts); $key = array_filter($parts, function ($value) { return false !== strpos($value, 'index.php'); }); $keySa = array_keys($key); $key = count($keys) - ($keySa[0] - 1); return implode('/', array_slice($parts, 1, $keys[count($keys) - $key])); } /** * 设置自动行高. * * @return void */ private function setAutoHeight() { for ($i = 0; $i < count($this->data); $i++) { $this->excel->getRowDimension($i + 2)->setRowHeight($this->height); } } /** * 获取域名地址 * * @return void */ private function getUrl() { $host = $_SERVER['HTTP_HOST']; $scriptName = $_SERVER['SCRIPT_NAME']; $this->defaultDomain = isset($_SERVER['HTTPS']) && 'on' === $_SERVER['HTTPS'] ? 'https://' : 'http://' . $host . substr($scriptName, 0, strrpos($scriptName, '/') + 1); } /** * 设置自动行宽. * * @return void */ private function setAutoWidth() { foreach ($this->title ?? [] as $key => $value) { $this->excel->getColumnDimension($this->ziMu[$key])->setAutoSize(true); // 全局自动宽度 $columnDimension = $this->excel->getColumnDimension($this->ziMu[$key]); $maxWidth = 50; // 自定义最大宽度 if ($columnDimension->getWidth() > $maxWidth) { $columnDimension->setWidth($maxWidth); } } } /** * 获取项目名称. * * @return false|string */ private function getProjectName() { $route = $_SERVER['REQUEST_URI']; $pattern = '/\/(\w+)\/index\.php/'; preg_match($pattern, $route, $matches); if (isset($matches[1])) { return $matches[1]; } return false; } /** * 验证是否Windows系统 */ private function checkWindows(): bool { $os = PHP_OS; if ('WIN' === strtoupper(substr($os, 0, 3))) { return true; } return false; } /** * 设置表格名称. * * @return $this */ public function setExcelName(string $excelName = ''): Excel { $this->excelName = $excelName; return $this; } /** * 设置格子颜色. * * @param int $height //表头高度 * @param string $color //表头颜色 * @param bool $isBold //表头是否加粗 * * @return $this * * @throws \think\Exception */ public function setHeaderColor(int $height = 20, string $color = 'FFFF00', bool $isBold = true): Excel { $this->excel->getStyle($this->getRange(1))->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setRGB($color); $this->excel->getStyle($this->getRange(1))->getFont()->setBold($isBold); $this->excel->getRowDimension(1)->setRowHeight($height); return $this; } /** * 设置是否导出地址 */ public function setIsExportPath(bool $isExportPath): Excel { $this->isExportPath = $isExportPath; return $this; } /** * 设置是否开启本地. * * @param string $localhostPath 本地域名地址 如果域名下一级目录不能直接直接对应项目名称 请传入域名下的相对路径 */ public function setLocalhostPath(string $localhostPath): Excel { $this->defaultDomain = $localhostPath; return $this; } /** * 设置边框. * * @throws \PhpOffice\PhpSpreadsheet\Exception */ public function borderThin(): Excel { $this->excel->getStyle($this->getRange())->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN); return $this; } /** * 设置自动换行. * * @return $this */ public function setAutoWrapText(bool $wrap = true): Excel { $this->setWrapText = $wrap; return $this; } /** * 设置全局居中. * * @return void * * @throws \think\Exception */ private function setCenter() { $this->excel->getStyle($this->getRange())->applyFromArray([ 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER, // 水平居中 'vertical' => Alignment::VERTICAL_CENTER, // 垂直居中 ], ]); } /** * 保存并导出. * * @return $this */ public function save(): Excel { $this->setCenter(); $this->setWrap(); $this->setCellValue(); $this->setAutoWidth(); $this->setAutoHeight(); $this->exportData(); $writer = new Xlsx($this->spreadsheet); if (empty($this->excelName)) { $this->excelName = date('YmdHis'); } $writer->save($this->path . '/' . $this->excelName . '.xlsx'); if ($this->isExportPath) { $this->exportPath = $this->defaultDomain . '/' . $this->projectExcelPath . '/' . $this->excelName . '.xlsx'; } else { header('Location: ' . $this->defaultDomain . '/' . $this->projectExcelPath . '/' . $this->excelName . '.xlsx'); } return $this; } /** * 创建图片. * * @throws \PhpOffice\PhpSpreadsheet\Exception */ private function setImage(string $url = '', string $ceil = '') { $src = imagecreatefromstring(file_get_contents($url)); list($src_w, $src_h) = getimagesize($url); $img = imagecreatetruecolor($src_w, $src_h); imagecopymerge($img, $src, 0, 0, 0, 0, $src_w, $src_h, 100); $drawing = new MemoryDrawing(); $drawing->setName($url); $drawing->setDescription($url); $drawing->setCoordinates($ceil); $drawing->setImageResource($img); $drawing->setHeight(80); $drawing->setOffsetX(10); $drawing->setOffsetY(10); $drawing->setRenderingFunction(MemoryDrawing::RENDERING_JPEG); $drawing->setMimeType(MemoryDrawing::MIMETYPE_DEFAULT); if (!empty($this->ceilImageStyle)) { $ceilText = substr($ceil, 0, 1); if (!empty($this->ceilImageStyle[$ceilText])) { $drawing->setHeight($this->ceilImageStyle[$ceilText]['height']); $drawing->setWidth($this->ceilImageStyle[$ceilText]['width']); $drawing->setOffsetX($this->ceilImageStyle[$ceilText]['OffsetX']); $drawing->setOffsetY($this->ceilImageStyle[$ceilText]['OffsetY']); } } $drawing->setWorksheet($this->spreadsheet->getActiveSheet()); } /** * 设置格子是否导出为图片. * * @return $this */ public function setExportCeilImage(array $images = []): Excel { $this->images = $images; if (count($images) != count($images, 1)) { foreach ($images ?? [] as $v) { $this->ceilImage[] = key($images); next($images); } $this->ceilImageStyle = $images; } else { $this->ceilImage = $images; } return $this; } /** * 设置导出数据. */ private function exportData() { $index = 2; $keyName = $this->getArrayKey(); for ($i = 0; $i < count($this->data); $i++) { for ($j = 0; $j < count($this->title); $j++) { if (in_array($this->ziMu[$j], $this->ceilImage)) { if (!empty($this->data[$i][$keyName[$j]])) { $this->excel->getColumnDimension($this->ziMu[$j])->setWidth($this->images[$this->ziMu[$j]]['width']); // 设置图片宽度 $this->excel->getRowDimension($i + 2)->setRowHeight($this->images[$this->ziMu[$j]]['height']); $this->setImage($this->data[$i][$keyName[$j]], $this->ziMu[$j] . $index); } } else { $this->excel->setCellValue($this->ziMu[$j] . $index, $this->data[$i][$keyName[$j]]); } } $index++; } } /** * 获取数组指针. */ private function getArrayKey(): array { $result = []; if (empty($this->data)) { throw new \think\Exception('传入表数据为空', 40004); } for ($i = 0, $len = count($this->data[0]); $i < $len; $i++) { $result[] = key($this->data[0]); next($this->data[0]); } return $result; } /** * 设置自动换行. */ private function setWrap() { if ($this->setWrapText) { $this->excel->getStyle($this->getRange())->getAlignment()->setWrapText(true); } } /** * 获取数据范围值 * * @return string * * @throws \think\Exception */ private function getRange($type = 0) { if (empty($this->title) || empty($this->data)) { throw new \think\Exception('初始化请传入数据', 40006); } if (0 == $type) { return 'A1:' . $this->ziMu[count($this->title) - 1] . (count($this->data) + 1); } return 'A1:' . $this->ziMu[count($this->title) - 1] . '1'; } /** * 设置表头. * * @return void * * @throws \think\Exception */ private function setCellValue() { if (empty($this->title)) { throw new \think\Exception('传入表头为空', 40005); } foreach ($this->title as $key => $value) { $this->excel->setCellValue($this->ziMu[$key] . '1', $this->title[$key]); } } /** * 获取Xlsx表格数据. * * @return array|false * * @throws \PhpOffice\PhpSpreadsheet\Exception * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception */ public static function getXlsxData($file, array $cell = []) { if (!$file) { return false; } $reader = IOFactory::createReader('Xlsx'); $reader->setReadDataOnly(true); $spreadsheet = $reader->load($file); $worksheet = $spreadsheet->getActiveSheet(); $arr = []; $i = 0; $field = $cell; $max = count($field); foreach ($worksheet->getRowIterator() as $row) { $k = 0; $cellIterator = $row->getCellIterator(); $cellIterator->setIterateOnlyExistingCells(false); foreach ($cellIterator as $cell) { if ($k == $max) { break; } $arr[$i][$field[$k]] = $cell->getCalculatedValue(); $k++; } $i++; } return $arr; } }