title = $title; $this->book = new Spreadsheet(); $this->book->getProperties() ->setCreator($creator) ->setTitle($title) ->setSubject($subject) ->setDescription('Created ' . date('r')); } /** * @return string */ public function getTitle() { return $this->title; } /** * Add a sheet and select it as active. * Returns sheet index. * * @param $label - sheet label * @return int - new sheet number, 0-based */ public function addSheet($label) { if ($this->activeSheetNum == -1) { // PhpOffice workbook has one sheet by default, // we require user to 'add' it before using it $this->sheetCount = 1; $this->activeSheet = $this->book->setActiveSheetIndex(0); $this->activeSheetNum = 0; } else { $this->sheetCount++; $this->activeSheet = $this->book->addSheet(new Worksheet()); $this->activeSheetNum = $this->sheetCount-1; } $this->activeSheet->setTitle($label); return $this->activeSheetNum; } /** * Select a sheet for cell modifications * * @param int $number - sheet index, 0-based */ public function selectSheet($number) { $this->activeSheet = $this->book->setActiveSheetIndex($number); $this->activeSheetNum = $number; } /** * Set a cell value in the current sheet * * @param int $row - 0-based row * @param int $column - 0-based column * @param mixed $value - value to set */ public function setValue($row, $column, $value) { $this->activeSheet->setCellValueByColumnAndRow($column+1, $row+1, $value); } /** * Set a row of values * * @param int $row - 0-based row * @param int $startcol - first column to fill * @param array $values - array of values to write into the row */ public function setRow($row, $startcol, $values) { $i = 0; foreach ($values as $value) { $this->setValue($row, $startcol + $i, $value); $i++; } } /** * Set a row of values * * @param int $startrow - 0-based start row * @param int $startcol - 0-based start column * @param array $values - array of row vectors ([ [first,row], [second,row], ...] */ public function setGrid($startrow, $startcol, $values) { foreach ($values as $row => $row_values) { $this->setRow($startrow + $row, $startcol, $row_values); } } /** * Make a cell a given style * * @param int $row - 0-based row * @param int $column - 0-based column */ private function setStyle($row, $column, $array) { $coord = Coordinate::stringFromColumnIndex($column+1) . ($row+1); $this->activeSheet->getStyle($coord) ->applyFromArray($array); } /** * Make an area of cells a given style * * @param $startrow - 0-based first row * @param $startcol - 0-based first column * @param $rows - number of rows * @param $cols - number of columns */ private function setStyleArea($startrow, $startcol, $rows, $cols, $array) { $coord = Coordinate::stringFromColumnIndex($startcol+1) . ($startrow+1) . ':' . Coordinate::stringFromColumnIndex($startcol+$cols) . ($startrow+$rows); $this->activeSheet->getStyle($coord) ->applyFromArray($array); } /** * Make a cell bold * * @param int $row - 0-based row * @param int $column - 0-based column */ public function setBold($row, $column) { $this->setStyle($row, $column, ['font' => ['bold' => 'true']]); } /** * Make an area of cells bold * * @param $startrow - 0-based first row * @param $startcol - 0-based first column * @param $rows - number of rows * @param $cols - number of columns */ public function setBoldArea($startrow, $startcol, $rows, $cols) { $this->setStyleArea($startrow, $startcol, $rows, $cols, ['font' => ['bold' => 'true']]); } /** * Make a cell italic * * @param int $row - 0-based row * @param int $column - 0-based column */ public function setItalic($row, $column) { $this->setStyle($row, $column, ['font' => ['italic' => 'true']]); } /** * Make an area of cells italic * * @param $startrow - 0-based first row * @param $startcol - 0-based first column * @param $rows - number of rows * @param $cols - number of columns */ public function setItalicArea($startrow, $startcol, $rows, $cols) { $this->setStyleArea($startrow, $startcol, $rows, $cols, ['font' => ['italic' => 'true']]); } private function convertColor($color) { if ($color[0] == '#') $rgb = substr($color, 1); else { $map = [ 'black' => '000000', 'gray' => '808080', 'silver' => 'C0C0C0', 'white' => 'FFFFFF', 'maroon' => '800000', 'red' => 'FF0000', 'olive' => '808000', 'yellow' => 'FFFF00', 'green' => '008000', 'lime' => '00FF00', 'teal' => '008080', 'aqua' => '00FFFF', 'navy' => '000080', 'blue' => '0000FF', 'purple' => '800080', 'fuchsia' => 'FF00FF', ]; if (isset($map[$color])) { $rgb = $map[$color]; } else { throw new \LogicException("Bad color format $color"); } } return ['rgb' => $rgb]; } /** * Set cell colors * * @param int $row - 0-based row * @param int $column - 0-based column * @param string $text - foreground * @param string $background - background */ public function setColors($row, $column, $text = null, $background = null) { $this->setColorsArea($row, $column, 1, 1, $text, $background); } /** * Set colors of an area of cells * * @param $startrow - 0-based first row * @param $startcol - 0-based first column * @param $rows - number of rows * @param $cols - number of columns * @param string $text - foreground * @param string $background - background */ public function setColorsArea($startrow, $startcol, $rows, $cols, $text = null, $background = null) { $ar = []; if ($text !== null) { $ar['font'] = [ 'color' => $this->convertColor($text), ]; } if ($background !== null) { $ar['fill'] = [ 'fillType' => Fill::FILL_SOLID, 'color' => $this->convertColor($background), ]; } $this->setStyleArea($startrow, $startcol, $rows, $cols, $ar); } /** * Merge cells * * @param $startrow - 0-based first row * @param $startcol - 0-based first column * @param $rows - number of rows * @param $cols - number of columns */ public function mergeCells($startrow, $startcol, $rows, $cols) { $coord = Coordinate::stringFromColumnIndex($startcol+1) . ($startrow+1) . ':' . Coordinate::stringFromColumnIndex($startcol+$cols) . ($startrow+$rows); $this->activeSheet->mergeCells($coord); } /** * Merge row cells * * @param $startrow - 0-based first row * @param $startcol - 0-based first column * @param $rows - number of rows * @param $cols - number of columns */ public function mergeRowCells($startrow, $startcol, $cols) { $this->mergeCells($startrow, $startcol, 1, $cols); } /** * Set a column's width * * @param int $column - 0-based column number * @param int $width - width in pixels */ public function setColumnWidth($column, $width) { $this->activeSheet->getColumnDimensionByColumn($column+1)->setWidth($width); } /** * Prepare writer and resolve mime type for export * * @param string $format - one of : xls, xlsx, csv, ods * @return array (mime, writer) */ private function prepareExport($format = 'xlsx') { switch ($format) { case 'xls': $writerName = 'Xls'; $mimeType = 'application/vnd.ms-excel'; break; case 'xlsx': $writerName = 'Xlsx'; $mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; break; case 'ods': $writerName = 'Ods'; $mimeType = 'application/vnd.oasis.opendocument.spreadsheet'; break; default: case 'csv': $writerName = 'Csv'; $mimeType = 'text/csv'; break; } // Set active sheet index to the first sheet, so Excel opens this as the first sheet $this->book->setActiveSheetIndex(0); $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($this->book, $writerName); return [$mimeType, $writer]; } /** * Export and send to browser as a response for user to download * * @param string $base_filename - filename without suffix * @param string $format - one of : xls, xlsx, csv, ods */ public function exportToBrowser($base_filename, $format = 'xlsx') { list($mimeType, $writer) = $this->prepareExport($format); /** @var IWriter $writer */ $base_filename .= '.' . $format; ob_end_clean(); // Redirect output to a client’s web browser (Xlsx) header("Content-Type: $mimeType; charset=utf-8"); header("Content-Disposition: attachment;filename=\"$base_filename\""); header('Content-Language: ' . Lang::locale()); // Cache headers header('Cache-Control: max-age=0'); // IE9 header('Cache-Control: max-age=1'); // Other IE headers header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified header('Cache-Control: cache, must-revalidate'); // HTTP/1.1 header('Pragma: no-cache'); // HTTP/1.0 $writer->save('php://output'); exit; } /** * Export and send to browser as a response for user to download * * @param string $base_filename - filename without suffix * @param string $format - one of : xls, xlsx, csv, ods * @return string - the mime type */ public function exportToFile($base_filename, $format = 'xlsx', $path='/tmp') { list($mimeType, $writer) = $this->prepareExport($format); /** @var IWriter $writer */ $writer->save($path . DIRECTORY_SEPARATOR . "$base_filename.$format"); return $mimeType; } }