View/SpreadsheetView.php
public function table($data = [], $width = [], $align = [], $header = []) {
		$language = new Language();
		$locale = $language->getCurrentUIlang(true);
		if (empty($locale)) {
			$locale = 'en';
		}
		\PhpOffice\PhpSpreadsheet\Settings::setLocale($locale);

		$styleTableHeader = $this->_getStyleTableHeader();
		$styleTableSubheader = $this->_getStyleTableSubheader();
		$styleTableRow = $this->_getStyleTableRow();
		$sheetIndex = 0;
		if (empty($data)) {
			$sheet = $this->Spreadsheet->getSheet($sheetIndex);
			$sheet->setTitle(__d('view_extension', 'No data to display'));
			$sheet->setCellValue('B2', __d('view_extension', 'No data to display'));
			$sheet->getColumnDimension('B')->setAutoSize(true);
			$sheet->getStyle('B2')->applyFromArray($styleTableHeader);

			return;
		}

		// Render data
		foreach ($data as $group => $info) {
			if (empty($info)) {
				continue;
			}

			// Sheet - Group
			if ($sheetIndex > 0) {
				$this->Spreadsheet->createSheet();
			}
			$sheet = $this->Spreadsheet->getSheet($sheetIndex);
			$sheetTitle = mb_strimwidth(strip_tags($group), 0, 31, '...', 'UTF-8');
			if (empty($sheetTitle)) {
				$sheetTitle = 'Sheet_' . ($sheetIndex + 1);
			}
			$sheet->setTitle($sheetTitle);

			// Header
			$iRow = 2;
			$azLiters = range('A', 'Z');
			$azLitersCount = count($azLiters);
			$columnCache = [];
			foreach ($header as $i => $headerItem) {
				if ($i > ($azLitersCount - 1)) {
					$part = floor($i / $azLitersCount);
					$liter = $azLiters[$part - 1] . $azLiters[$i - ($part * $azLitersCount)];
				} else {
					$liter = $azLiters[$i + 1];
				}
				$sheet->setCellValue($liter . $iRow, $headerItem);
				$sheet->getColumnDimension($liter)->setWidth($width[$i]);
				$columnCache[] = $liter;
			}
			$sheet->getStyle('B' . $iRow . ':' . $liter . $iRow)->applyFromArray($styleTableHeader);
			$iRow++;
			foreach ($info as $subGroup => $row) {
				if (is_int($subGroup)) {
					foreach ($row as $i => $field) {
						$sheet->setCellValue($columnCache[$i] . $iRow, strip_tags(preg_replace('#<br\s*/?>#i', "\n", $field)));
						switch ($align[$i]) {
							case 'R':
								$alignStyle = Alignment::HORIZONTAL_RIGHT;
								break;
							case 'C':
								$alignStyle = Alignment::HORIZONTAL_CENTER;
								break;
							case 'L':
							default:
								$alignStyle = Alignment::HORIZONTAL_LEFT;
						}
						$sheet->getStyle($columnCache[$i] . $iRow)->getAlignment()->setHorizontal($alignStyle);
						$sheet->getStyle('B' . $iRow . ':' . $liter . $iRow)->applyFromArray($styleTableRow);
					}
				} else {
					if (!empty($subGroup)) {
						$sheet->setCellValue('B' . $iRow, $subGroup);
						$sheet->mergeCells('B' . $iRow . ':' . $liter . $iRow);
						$sheet->getStyle('B' . $iRow . ':' . $liter . $iRow)->applyFromArray($styleTableSubheader);
						$iRow++;
					}
					foreach ($row as $rowItem) {
						foreach ($rowItem as $i => $field) {
							$sheet->setCellValue($columnCache[$i] . $iRow, strip_tags(preg_replace('#<br\s*/?>#i', "\r\n", $field)));
							switch ($align[$i]) {
								case 'R':
									$alignStyle = Alignment::HORIZONTAL_RIGHT;
									break;
								case 'C':
									$alignStyle = Alignment::HORIZONTAL_CENTER;
									break;
								case 'L':
								default:
									$alignStyle = Alignment::HORIZONTAL_LEFT;
							}
							$sheet->getStyle($columnCache[$i] . $iRow)->getAlignment()->setHorizontal($alignStyle);
							$sheet->getStyle('B' . $iRow . ':' . $liter . $iRow)->applyFromArray($styleTableRow);
						}
						$iRow++;
					}
				}
				$iRow++;
			}

			// Set AutoFilter
			$this->Spreadsheet->getActiveSheet()->setAutoFilter('B2:' . $liter . --$iRow);
			$sheetIndex++;
		}

		$this->Spreadsheet->setActiveSheetIndex(0);
	}
public function table($data = [], $width = [], $align = [], $header = []) {
		$language = new Language();
		$locale = $language->getCurrentUIlang(true);
		if (empty($locale)) {
			$locale = 'en';
		}
		\PhpOffice\PhpSpreadsheet\Settings::setLocale($locale);

		$styleTableHeader = $this->_getStyleTableHeader();
		$styleTableSubheader = $this->_getStyleTableSubheader();
		$styleTableRow = $this->_getStyleTableRow();
		$sheetIndex = 0;
		if (empty($data)) {
			$sheet = $this->Spreadsheet->getSheet($sheetIndex);
			$sheet->setTitle(__d('view_extension', 'No data to display'));
			$sheet->setCellValue('B2', __d('view_extension', 'No data to display'));
			$sheet->getColumnDimension('B')->setAutoSize(true);
			$sheet->getStyle('B2')->applyFromArray($styleTableHeader);

			return;
		}

		// Render data
		foreach ($data as $group => $info) {
			if (empty($info)) {
				continue;
			}

			// Sheet - Group
			if ($sheetIndex > 0) {
				$this->Spreadsheet->createSheet();
			}
			$sheet = $this->Spreadsheet->getSheet($sheetIndex);
			$sheetTitle = mb_strimwidth(strip_tags($group), 0, 31, '...', 'UTF-8');
			if (empty($sheetTitle)) {
				$sheetTitle = 'Sheet_' . ($sheetIndex + 1);
			}
			$sheet->setTitle($sheetTitle);

			// Header
			$iRow = 2;
			$azLiters = range('A', 'Z');
			$azLitersCount = count($azLiters);
			$columnCache = [];
			foreach ($header as $i => $headerItem) {
				if ($i > ($azLitersCount - 1)) {
					$part = floor($i / $azLitersCount);
					$liter = $azLiters[$part - 1] . $azLiters[$i - ($part * $azLitersCount)];
				} else {
					$liter = $azLiters[$i + 1];
				}
				$sheet->setCellValue($liter . $iRow, $headerItem);
				$sheet->getColumnDimension($liter)->setWidth($width[$i]);
				$columnCache[] = $liter;
			}
			$sheet->getStyle('B' . $iRow . ':' . $liter . $iRow)->applyFromArray($styleTableHeader);
			$iRow++;
			foreach ($info as $subGroup => $row) {
				if (is_int($subGroup)) {
					foreach ($row as $i => $field) {
						$sheet->setCellValue($columnCache[$i] . $iRow, strip_tags(preg_replace('#<br\s*/?>#i', "\n", $field)));
						switch ($align[$i]) {
							case 'R':
								$alignStyle = Alignment::HORIZONTAL_RIGHT;
								break;
							case 'C':
								$alignStyle = Alignment::HORIZONTAL_CENTER;
								break;
							case 'L':
							default:
								$alignStyle = Alignment::HORIZONTAL_LEFT;
						}
						$sheet->getStyle($columnCache[$i] . $iRow)->getAlignment()->setHorizontal($alignStyle);
						$sheet->getStyle('B' . $iRow . ':' . $liter . $iRow)->applyFromArray($styleTableRow);
					}
				} else {
					if (!empty($subGroup)) {
						$sheet->setCellValue('B' . $iRow, $subGroup);
						$sheet->mergeCells('B' . $iRow . ':' . $liter . $iRow);
						$sheet->getStyle('B' . $iRow . ':' . $liter . $iRow)->applyFromArray($styleTableSubheader);
						$iRow++;
					}
					foreach ($row as $rowItem) {
						foreach ($rowItem as $i => $field) {
							$sheet->setCellValue($columnCache[$i] . $iRow, strip_tags(preg_replace('#<br\s*/?>#i', "\r\n", $field)));
							switch ($align[$i]) {
								case 'R':
									$alignStyle = Alignment::HORIZONTAL_RIGHT;
									break;
								case 'C':
									$alignStyle = Alignment::HORIZONTAL_CENTER;
									break;
								case 'L':
								default:
									$alignStyle = Alignment::HORIZONTAL_LEFT;
							}
							$sheet->getStyle($columnCache[$i] . $iRow)->getAlignment()->setHorizontal($alignStyle);
							$sheet->getStyle('B' . $iRow . ':' . $liter . $iRow)->applyFromArray($styleTableRow);
						}
						$iRow++;
					}
				}
				$iRow++;
			}

			// Set AutoFilter
			$this->Spreadsheet->getActiveSheet()->setAutoFilter('B2:' . $liter . --$iRow);
			$sheetIndex++;
		}

		$this->Spreadsheet->setActiveSheetIndex(0);
	}
Write a table

@param array $data Array of rows for table.
@param array $width Array of width for table cells.
@param array $align Array of align position for table cells.
@param array $header Array of header for table cells.
@return void