%PDF- %PDF-
Direktori : /home/vacivi36/intranet.vacivitta.com.br/protected/humhub/components/export/ |
Current File : /home/vacivi36/intranet.vacivitta.com.br/protected/humhub/components/export/SpreadsheetExport.php |
<?php /** * @link https://www.humhub.org/ * @copyright Copyright (c) 2018 HumHub GmbH & Co. KG * @license https://www.humhub.com/licences */ namespace humhub\components\export; use PhpOffice\PhpSpreadsheet\Spreadsheet; use Yii; use yii\base\Component; use yii\base\InvalidConfigException; use yii\data\ActiveDataProvider; use yii\data\BaseDataProvider; use yii\di\Instance; use yii\i18n\Formatter; /** * SpreadsheetExport allows export of data into PhpSpreadsheet * It supports exporting of the [[\yii\data\DataProviderInterface]] and [[\yii\db\QueryInterface]] instances. * * This class was originally developed by Paul Klimov <klimov.paul@gmail.com> and his * project csv-grid (https://github.com/yii2tech/csv-grid). * * Example: * * ```php * use humhub\components\export\SpreadsheetExport; * use yii\data\ArrayDataProvider; * * $exporter = new SpreadsheetExport([ * 'dataProvider' => new ArrayDataProvider([ * 'allModels' => [ * [ * 'name' => 'some name', * 'price' => '9879', * ], * [ * 'name' => 'name 2', * 'price' => '79', * ], * ], * ]), * 'columns' => [ * [ * 'attribute' => 'name', * ], * [ * 'attribute' => 'price', * 'format' => 'decimal', * ], * ], * ]); * $exporter->export()->saveAs('/path/to/file.csv'); * ``` */ class SpreadsheetExport extends Component { /** * @var \yii\data\DataProviderInterface the data provider for the view. * This property can be omitted in case [[query]] is set. */ public $dataProvider; /** * @var \yii\db\QueryInterface the data source query. * Note: this field will be ignored in case [[dataProvider]] is set. */ public $query; /** * @var array|Column[] */ public $columns = []; /** * @var boolean whether to show the header section of the sheet. */ public $showHeader = true; /** * @var boolean whether to show the footer section of the sheet. */ public $showFooter = false; /** * @var boolean enable autosize for xlsx/xls export. */ public $autoSize = true; /** * @var string the HTML display when the content of a cell is empty. * This property is used to render cells that have no defined content, * e.g. empty footer or filter cells. * * Note that this is not used by the [[DataColumn]] if a data item is `null`. In that case * the [[nullDisplay]] property will be used to indicate an empty data value. */ public $emptyCell = ''; /** * @var string the text to be displayed when formatting a `null` data value. */ public $nullDisplay = ''; /** * @var array configuration for [[ExportResult]] instance created in process result. * * For example: * * ```php * [ * 'forceArchive' => true * ] * ``` * * @see ExportResult */ public $resultConfig = []; /** * @var array|Formatter the formatter used to format model attribute values into displayable texts. * This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]] * instance. If this property is not set, the "formatter" application component will be used. */ private $formatter; /** * @var int */ private $row = 1; /** * Initializes the grid. * This method will initialize required property values and instantiate [[columns]] objects. */ public function init() { parent::init(); if ($this->dataProvider === null && $this->query !== null) { $this->dataProvider = new ActiveDataProvider([ 'query' => $this->query ]); } if ($this->dataProvider instanceof BaseDataProvider) { $this->dataProvider->setPagination(false); } } /** * @return Formatter formatter instance * @throws \yii\base\InvalidConfigException */ public function getFormatter() { if (!is_object($this->formatter)) { if ($this->formatter === null) { $this->formatter = Yii::$app->getFormatter(); } else { $this->formatter = Instance::ensure($this->formatter, Formatter::className()); } } return $this->formatter; } /** * @param array|Formatter $formatter */ public function setFormatter($formatter) { $this->formatter = $formatter; } /** * Creates column objects and initializes them. * @param array $model list of single row model * @throws \yii\base\InvalidConfigException */ protected function initColumns($model) { if (empty($this->columns)) { $this->guessColumns($model); } foreach ($this->columns as $i => $column) { if (is_string($column)) { $column = $this->createDataColumn($column); } else { $column = Yii::createObject(array_merge([ 'class' => DataColumn::className(), 'grid' => $this, ], $column)); } if (!$column->visible) { unset($this->columns[$i]); continue; } $this->columns[$i] = $column; } } /** * This function tries to guess the columns to show from the given data * if [[columns]] are not explicitly specified. * @param array $model list of model */ protected function guessColumns($model) { if (is_array($model) || is_object($model)) { foreach ($model as $name => $value) { $this->columns[] = (string)$name; } } } /** * Creates a [[DataColumn]] object based on a string in the format of "attribute:format:label". * @param string $text the column specification string * @return DataColumn the column instance * @throws InvalidConfigException if the column specification is invalid */ protected function createDataColumn($text) { if (!preg_match('/^([^:]+)(:(\w*))?(:(.*))?$/', $text, $matches)) { throw new InvalidConfigException( 'The column must be specified in the format of "attribute", ' . '"attribute:format" or "attribute:format:label"' ); } /** @var DataColumn $column */ $column = Yii::createObject([ 'class' => DataColumn::className(), 'grid' => $this, 'attribute' => $matches[1], 'format' => isset($matches[3]) ? $matches[3] : 'text', 'label' => isset($matches[5]) ? $matches[5] : null, ]); return $column; } /** * Performs data export. * @return ExportResult export result. * @throws \yii\base\InvalidConfigException * @throws \PhpOffice\PhpSpreadsheet\Exception */ public function export() { /** @var ExportResult $result */ $result = Yii::createObject(array_merge([ 'class' => ExportResult::className(), ], $this->resultConfig)); $spreadsheet = $result->newSpreadsheet(); $models = $this->dataProvider->getModels(); $keys = $this->dataProvider->getKeys(); $this->initColumns(reset($models)); if ($this->showHeader) { $this->composeHeaderRow($spreadsheet); } foreach ($models as $index => $model) { $key = isset($keys[$index]) ? $keys[$index] : $index; $this->composeBodyRow($spreadsheet, $model, $key, $index); } if ($this->showFooter) { $this->composeFooterRow($spreadsheet); } if ($this->autoSize) { $this->applyAutoSize($spreadsheet); } $this->gc(); return $result; } /** * Composes header row contents. * @param Spreadsheet $spreadsheet * @throws \PhpOffice\PhpSpreadsheet\Exception */ protected function composeHeaderRow($spreadsheet) { $worksheet = $spreadsheet->getActiveSheet(); $row = $this->nextRow(); foreach ($this->columns as $columnIndex => $column) { $worksheet->setCellValueByColumnAndRow( $columnIndex + 1, $row, $column->renderHeaderCellContent() ); } } /** * Composes header row contents. * @param Spreadsheet $spreadsheet * @throws \PhpOffice\PhpSpreadsheet\Exception */ protected function composeFooterRow($spreadsheet) { $worksheet = $spreadsheet->getActiveSheet(); $row = $this->nextRow(); foreach ($this->columns as $columnIndex => $column) { $worksheet->setCellValueByColumnAndRow( $columnIndex + 1, $row, $column->renderFooterCellContent() ); } } /** * Composes body row contents. * @param Spreadsheet $spreadsheet * @param mixed $model the data model * @param mixed $key the key associated with the data model * @param int $index zero-based index of data model among the models array returned by [[GridView::dataProvider]]. * @throws \PhpOffice\PhpSpreadsheet\Exception */ protected function composeBodyRow($spreadsheet, $model, $key, $index) { $worksheet = $spreadsheet->getActiveSheet(); $row = $this->nextRow(); foreach ($this->columns as $columnIndex => $column) { $cell = $worksheet->getCellByColumnAndRow($columnIndex + 1, $row); $value = $column->renderDataCellContent($model, $key, $index); if ($column->dataType !== null) { $cell->setValueExplicit($value, $column->dataType); } else { $cell->setValue($value); } if ($column->styles !== []) { $cell->getStyle()->applyFromArray($column->styles); } } } /** * Enable AutoSize for Export * @param Spreadsheet $spreadsheet * @throws \PhpOffice\PhpSpreadsheet\Exception */ protected function applyAutoSize($spreadsheet) { $worksheet = $spreadsheet->getActiveSheet(); foreach ($this->columns as $columnIndex => $column) { $worksheet->getColumnDimensionByColumn($columnIndex + 1)->setAutoSize(true); } } /** * @return int */ protected function nextRow() { return $this->row++; } /** * Performs PHP memory garbage collection. */ protected function gc() { if (!gc_enabled()) { gc_enable(); } gc_collect_cycles(); } }