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?