getActiveSheet(); $this->fillHeading($export, $sheet); $this->fillData($export, $sheet); $this->setAutoSize($export, $sheet); $closure = $export->getStyleSetting(); if ($closure) { $closure($export, $sheet); } $writer = new Xlsx($spreadsheet); $writer->save($filePath); } private function fillHeading(Export $export, Worksheet $sheet) { $rowIndex = 0; $firstCellKey = null; $lastCellKey = null; foreach ($export->headings() as $columnIndex => $name) { $cellKey = $this->getCellKey($rowIndex, $columnIndex); $sheet->setCellValue($cellKey, $name); if ($columnIndex == 0) { $firstCellKey = $cellKey; } $lastCellKey = $cellKey; } $this->setHeadingStyle($sheet, $firstCellKey . ':' . $lastCellKey); } private function fillData(Export $export, Worksheet $sheet, $rowIndex = 1) { $mode = $export->getMode(); if ($mode == Export::MODE_QUERY) { $rowIndex = $this->fillFromQuery($export, $sheet, $rowIndex); } elseif ($mode == Export::MODE_ARRAY) { $rowIndex = $this->fillFromArray($export, $sheet, $rowIndex); } elseif ($mode == Export::MODE_COLLECTION) { $rowIndex = $this->fillFromCollection($export, $sheet, $rowIndex); } $summary = $export->withSummary ? $export->summary() : null; if (!empty($summary)) { $rowIndex = $this->fillItems($export, $sheet, [$summary], $rowIndex); } } private function setHeadingStyle(Worksheet $sheet, $cellRange) { $sharedStyle = new Style(); $sharedStyle->applyFromArray( [ 'fill' => [ 'fillType' => Fill::FILL_SOLID, 'color' => ['argb' => 'd9d9d9'], ], 'borders' => [ 'allBorders' => ['borderStyle' => Border::BORDER_THIN], ], 'font' => [ 'name' => '黑体', 'bold' => true, 'size' => 12 ] ] ); $sheet->duplicateStyle($sharedStyle, $cellRange); } private function fillFromQuery(Export $export, Worksheet $sheet, $rowIndex) { $query = $export->query(); if (is_null($query)) { throw new BusinessException('query 方法未实现'); } $page = 1; $limit = 1000; $chunkCompareValue = null; $isFirstRound = true; do { $tmpQuery = clone $query; $offset = ($page-1) * $limit; $items = null; if ($export->chunkCompareEnable) { $options = $export->chunkCompareOptions; if (!$isFirstRound) { $tmpQuery->where($options['key'], $options['symbol'], $chunkCompareValue); } $items = $tmpQuery->limit($limit)->get(); $lastItem = $items->last(); $chunkCompareValue = $lastItem ? $lastItem->{$options['key']} : null; } else { $items = $tmpQuery->offset($offset)->limit($limit)->get(); } $items = $export->rangeQueryItems($items); $rowIndex = $this->fillItems($export, $sheet, $items, $rowIndex); $isFirstRound = false; $count = count($items); $page ++; } while ($count == $limit); return $rowIndex; } private function fillFromArray(Export $export, Worksheet $sheet, $rowIndex) { return $this->fillItems($export, $sheet, $export->array(), $rowIndex); } private function fillFromCollection(Export $export, Worksheet $sheet, $rowIndex) { return $this->fillItems($export, $sheet, $export->collection(), $rowIndex); } private function fillItems(Export $export, Worksheet $sheet, $items, $rowIndex) { foreach ($items as $item) { foreach ($export->map($item) as $columnIndex => $value) { $cellKey = $this->getCellKey($rowIndex, $columnIndex); $sheet->setCellValue($cellKey, $value); } $rowIndex += 1; } return $rowIndex; } private function concatCellKey($rowKey, $columnKey) { return $columnKey . $rowKey; } private function getCellKey($rowIndex, $columnIndex) { return $this->concatCellKey($rowIndex + 1, Excel::getColumnKey($columnIndex)); } private function setAutoSize(Export $export, Worksheet $sheet) { foreach ($export->headings() as $columnIndex => $name) { $columnKey = Excel::getColumnKey($columnIndex); $sheet->getColumnDimension($columnKey)->setAutoSize(true); } } }