利用导出phpspreadsheet库写了导出

38 阅读2分钟
<?php
namespace App\Services\Service\Export;

require './../vendor/autoload.php';

use App\Services\Implement\Export\PhpSpreadsheetInterface;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Writer\Exception;
use function App\getAlphabetLetter;

class PhpSpreadsheetService implements PhpSpreadsheetInterface
{
    public Spreadsheet $spreadsheet;
    public Worksheet $spreadsheetWorksheet;

    public function __construct()
    {
        $this->spreadsheet = new Spreadsheet();
        $this->spreadsheetWorksheet = $this->spreadsheet->getActiveSheet();
    }

    public function setTitle(string $title): self
    {
        $this->spreadsheetWorksheet->setTitle($title);
        return $this;
    }

    public function setHeaders(array $field): self
    {

        foreach (array_values($field) as $k => $v) {
            $columnLetter = getAlphabetLetter($k);
            $this->spreadsheetWorksheet->setCellValue($columnLetter . '1', $v);
        }
        return $this;
    }

    public function fillData(array $data, array $field): self
    {
        $rowData = [];
        foreach ($data as $row) {
            $rowArray = [];
            foreach ($field as $k => $v) {
                $rowArray[] = $row[$k];
            }
            $rowData[] = $rowArray;
        }
        $this->spreadsheetWorksheet->fromArray($rowData, null, 'A2');
        return $this;
    }

    public function setColumnsAsText(array $columnIndexes): self
    {
        foreach ($columnIndexes as $index) {
            $columnLetter = getAlphabetLetter($index + 1);
            $highestRow = $this->spreadsheetWorksheet->getHighestRow();
            for ($row = 2; $row <= $highestRow; $row++) {
                $cell = $this->spreadsheetWorksheet->getCell($columnLetter . $row);
                $cell->setDataType(DataType::TYPE_STRING);
            }
        }
        return $this;
    }

    /**
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     */
    public function applyStyles(array $field, int $dataLength, string $styleType): self
    {
        $lastColumn = getAlphabetLetter(count($field)-1);
        $totalRows = $dataLength + 1;

        $styleArrayHeader = $this->getStyleArray('header', $styleType);
        $styleArrayBody = $this->getStyleArray('body', $styleType);

        $this->spreadsheetWorksheet->getStyle('A1:' . $lastColumn . '1')->applyFromArray($styleArrayHeader);
        $this->spreadsheetWorksheet->getStyle('A1:' . $lastColumn . $totalRows)->applyFromArray($styleArrayBody);
        return $this;
    }

    public function autoSizeColumns(): self
    {
        foreach (range('A', $this->spreadsheetWorksheet->getHighestDataColumn()) as $columnID) {
            $this->spreadsheetWorksheet->getColumnDimension($columnID)->setAutoSize(true);
        }
        return $this;
    }

    /**
     * @throws Exception
     */
    public function saveToFile(string $title, $fileType): void
    {
        // Determine the correct MIME type for the file type
        $mimeType = '';
        if ($fileType === 'Xlsx') {
            $mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
        } elseif ($fileType === 'Xls') {
            $mimeType = 'application/vnd.ms-excel';
        } elseif ($fileType === 'Csv') {
            $mimeType = 'text/csv';
        }

        // Set the headers to force download
        header('Content-Type: ' . $mimeType);
        header('Content-Disposition: attachment;filename="' . $title . '"');
        header('Cache-Control: max-age=0');

        // Create the writer and save the file to php://output
        $writer = IOFactory::createWriter($this->spreadsheet, $fileType);
        ob_clean(); // Clear the output buffer
        $writer->save('php://output');
        exit();
    }

    /**
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws Exception
     */
    public function export(string $title, array $fieldMap, array $data, $fileType, string $styleType = 'default'): void
    {
        $headers = array_values($fieldMap);
        $this->setTitle($title)
            ->setHeaders($headers)
            ->fillData($data, $fieldMap)
            ->applyStyles($headers, count($data), $styleType)
            ->autoSizeColumns()
            ->saveToFile($title, $fileType);
    }

    private function getStyleArray(string $type, string $styleType): array
    {
        $styles = [
            'default' => [
                'header' => [
                    'font' => [
                        'bold' => true,
                        'size' => 12,
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                    ],
                ],
                'body' => [
                    'borders' => [
                        'allBorders' => [
                            'borderStyle' => Border::BORDER_THIN,
                            'color' => ['argb' => '666666'],
                        ],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                    ],
                ],
            ],
            'alternative' => [
                'header' => [
                    'font' => [
                        'bold' => true,
                        'color' => ['argb' => 'FF0000'],
                        'size' => 14,
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                    ],
                ],
                'body' => [
                    'borders' => [
                        'allBorders' => [
                            'borderStyle' => Border::BORDER_DOTTED,
                            'color' => ['argb' => 'CCCCCC'],
                        ],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_LEFT,
                    ],
                ],
            ],
            'elegant_blue' => [
                'header' => [
                    'font' => [
                        'bold' => true,
                        'color' => ['argb' => 'FFFFFFFF'],
                        'size' => 12,
                    ],
                    'fill' => [
                        'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
                        'startColor' => ['argb' => 'FF4F81BD'],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                    ],
                ],
                'body' => [
                    'borders' => [
                        'allBorders' => [
                            'borderStyle' => Border::BORDER_THIN,
                            'color' => ['argb' => 'FF4F81BD'],
                        ],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                    ],
                ],
            ],
            'modern_green' => [
                'header' => [
                    'font' => [
                        'bold' => true,
                        'color' => ['argb' => 'FFFFFFFF'],
                        'size' => 12,
                    ],
                    'fill' => [
                        'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
                        'startColor' => ['argb' => 'FF00B050'],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                    ],
                ],
                'body' => [
                    'borders' => [
                        'allBorders' => [
                            'borderStyle' => Border::BORDER_THIN,
                            'color' => ['argb' => 'FF00B050'],
                        ],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_LEFT,
                    ],
                ],
            ],
            'classic_gray' => [
                'header' => [
                    'font' => [
                        'bold' => true,
                        'color' => ['argb' => 'FF000000'],
                        'size' => 12,
                    ],
                    'fill' => [
                        'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
                        'startColor' => ['argb' => 'FFD9D9D9'],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                    ],
                ],
                'body' => [
                    'borders' => [
                        'allBorders' => [
                            'borderStyle' => Border::BORDER_THIN,
                            'color' => ['argb' => 'FFB0B0B0'],
                        ],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_LEFT,
                    ],
                ],
            ],
            'professional_purple' => [
                'header' => [
                    'font' => [
                        'bold' => true,
                        'color' => ['argb' => 'FFFFFFFF'],
                        'size' => 12,
                    ],
                    'fill' => [
                        'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
                        'startColor' => ['argb' => 'FF7030A0'],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                    ],
                ],
                'body' => [
                    'borders' => [
                        'allBorders' => [
                            'borderStyle' => Border::BORDER_THIN,
                            'color' => ['argb' => 'FF7030A0'],
                        ],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_LEFT,
                    ],
                ],
            ],
            'sleek_black' => [
                'header' => [
                    'font' => [
                        'bold' => true,
                        'color' => ['argb' => 'FFFFFFFF'],
                        'size' => 12,
                    ],
                    'fill' => [
                        'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
                        'startColor' => ['argb' => 'FF000000'],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                    ],
                ],
                'body' => [
                    'borders' => [
                        'allBorders' => [
                            'borderStyle' => Border::BORDER_THIN,
                            'color' => ['argb' => 'FF000000'],
                        ],
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_LEFT,
                    ],
                ],
            ],
        ];

        return $styles[$styleType][$type];
    }
}