<?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;
}
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;
}
public function saveToFile(string $title, $fileType): void
{
$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';
}
header('Content-Type: ' . $mimeType);
header('Content-Disposition: attachment;filename="' . $title . '"');
header('Cache-Control: max-age=0');
$writer = IOFactory::createWriter($this->spreadsheet, $fileType);
ob_clean();
$writer->save('php://output');
exit();
}
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];
}
}