Changeset View
Standalone View
src/infrastructure/export/PhabricatorExcelExportFormat.php
- This file was added.
| <?php | |||||
| final class PhabricatorExcelExportFormat | |||||
| extends PhabricatorExportFormat { | |||||
| const EXPORTKEY = 'excel'; | |||||
| private $workbook; | |||||
| private $sheet; | |||||
| private $rowCursor; | |||||
| public function getExportFormatName() { | |||||
| return pht('Excel (.xlsx)'); | |||||
| } | |||||
| public function isExportFormatEnabled() { | |||||
| return true; | |||||
| } | |||||
| public function getFileExtension() { | |||||
| return 'xlsx'; | |||||
| } | |||||
| public function getMIMEContentType() { | |||||
| return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; | |||||
| } | |||||
| /** | |||||
| * @phutil-external-symbol class PHPExcel_Cell_DataType | |||||
| */ | |||||
| public function addHeaders(array $fields) { | |||||
amckinley: This is off-topic, but what does this annotation do? | |||||
Not Done Inline ActionsWhen you use a symbol that doesn't exist, arc lint warns you that you used Excarpteen and probably misspelled the class, forgot to update a library map, etc. This annotation tells lint "don't worry, I know what I'm doing". epriestley: When you use a symbol that doesn't exist, `arc lint` warns you that you used `Excarpteen` and… | |||||
| $sheet = $this->getSheet(); | |||||
| $header_format = array( | |||||
| 'font' => array( | |||||
| 'bold' => true, | |||||
| ), | |||||
| ); | |||||
| $row = 1; | |||||
| $col = 0; | |||||
| foreach ($fields as $field) { | |||||
| $cell_value = $field->getLabel(); | |||||
| $cell_name = $this->getCellName($col, $row); | |||||
| $cell = $sheet->setCellValue( | |||||
| $cell_name, | |||||
| $cell_value, | |||||
| $return_cell = true); | |||||
| $sheet->getStyle($cell_name)->applyFromArray($header_format); | |||||
| $cell->setDataType(PHPExcel_Cell_DataType::TYPE_STRING); | |||||
| $width = $field->getCharacterWidth(); | |||||
| if ($width !== null) { | |||||
Not Done Inline ActionsExcel doesn't do something sensible by default, like "set column width to the maximum width present in the data"? amckinley: Excel doesn't do something sensible by default, like "set column width to the maximum width… | |||||
Not Done Inline ActionsWithout setting widths ourselves, the sheet opens up with every column about one inch wide. This might be a PHPExcel issue (maybe it writes some explicit default?). I don't recall if I ever tried to dig into it. epriestley: Without setting widths ourselves, the sheet opens up with every column about one inch wide. | |||||
| $col_name = $this->getCellName($col); | |||||
| $sheet->getColumnDimension($col_name) | |||||
| ->setWidth($width); | |||||
| } | |||||
| $col++; | |||||
| } | |||||
| } | |||||
| public function addObject($object, array $fields, array $map) { | |||||
| $sheet = $this->getSheet(); | |||||
| $col = 0; | |||||
| foreach ($fields as $key => $field) { | |||||
| $cell_value = $map[$key]; | |||||
| $cell_value = $field->getPHPExcelValue($cell_value); | |||||
| $cell_name = $this->getCellName($col, $this->rowCursor); | |||||
| $cell = $sheet->setCellValue( | |||||
| $cell_name, | |||||
| $cell_value, | |||||
| $return_cell = true); | |||||
| $style = $sheet->getStyle($cell_name); | |||||
| $field->formatPHPExcelCell($cell, $style); | |||||
| $col++; | |||||
| } | |||||
| $this->rowCursor++; | |||||
| } | |||||
| /** | |||||
| * @phutil-external-symbol class PHPExcel_IOFactory | |||||
| */ | |||||
| public function newFileData() { | |||||
| $workbook = $this->getWorkbook(); | |||||
| $writer = PHPExcel_IOFactory::createWriter($workbook, 'Excel2007'); | |||||
| ob_start(); | |||||
| $writer->save('php://output'); | |||||
| $data = ob_get_clean(); | |||||
| return $data; | |||||
| } | |||||
| private function getWorkbook() { | |||||
| if (!$this->workbook) { | |||||
| $this->workbook = $this->newWorkbook(); | |||||
| } | |||||
| return $this->workbook; | |||||
| } | |||||
| /** | |||||
| * @phutil-external-symbol class PHPExcel | |||||
| */ | |||||
| private function newWorkbook() { | |||||
| include_once 'PHPExcel.php'; | |||||
| return new PHPExcel(); | |||||
| } | |||||
| private function getSheet() { | |||||
| if (!$this->sheet) { | |||||
| $workbook = $this->getWorkbook(); | |||||
| $sheet = $workbook->setActiveSheetIndex(0); | |||||
| $sheet->setTitle($this->getTitle()); | |||||
| $this->sheet = $sheet; | |||||
| // The row cursor starts on the second row, after the header row. | |||||
| $this->rowCursor = 2; | |||||
| } | |||||
Not Done Inline ActionsAre we guaranteed to always have a header? I guess since the base class provides id and PHID, even janky extensions should have at least those fields available. amckinley: Are we guaranteed to always have a header? I guess since the base class provides `id` and… | |||||
Not Done Inline ActionsYeah, we're always guaranteed to have at least one field (since SearchEngine won't export if we don't) and every field has a label and can generate a header, so we should always have a header. epriestley: Yeah, we're always guaranteed to have at least one field (since SearchEngine won't export if we… | |||||
| return $this->sheet; | |||||
| } | |||||
| private function getCellName($col, $row = null) { | |||||
| $col_name = chr(ord('A') + $col); | |||||
| if ($row === null) { | |||||
| return $col_name; | |||||
| } | |||||
| return $col_name.$row; | |||||
| } | |||||
| } | |||||
This is off-topic, but what does this annotation do?