Merge b54e21779913f3b1873d72b08097737b3bd2ec9b into 84596668410bea89d21aa9867b91e1550e359329
This commit is contained in:
commit
876573579e
@ -50,6 +50,23 @@ $writer->setShouldCreateNewSheetsAutomatically(true); // default value
|
|||||||
$writer->setShouldCreateNewSheetsAutomatically(false); // will stop writing new data when limit is reached
|
$writer->setShouldCreateNewSheetsAutomatically(false); // will stop writing new data when limit is reached
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Sheet view (XLSX writer)
|
||||||
|
|
||||||
|
Sheet view settings must be configured before any rows are added to the sheet.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
|
||||||
|
use Box\Spout\Writer\XLSX\Entity\SheetView;
|
||||||
|
|
||||||
|
$sheetView = (new SheetView())
|
||||||
|
->setFreezeRow(2) // First row will be fixed
|
||||||
|
->setFreezeColumn('D') // Columns A to C will be fixed
|
||||||
|
->setZoomScale(150); // And other options
|
||||||
|
|
||||||
|
$writer = WriterEntityFactory::createXLSXWriter();
|
||||||
|
$writer->getCurrentSheet()->setSheetView($sheetView);
|
||||||
|
```
|
||||||
|
|
||||||
### Using a custom temporary folder
|
### Using a custom temporary folder
|
||||||
|
|
||||||
Processing XLSX and ODS files requires temporary files to be created. By default, {{ site.spout_html }} will use the system default temporary folder (as returned by `sys_get_temp_dir()`). It is possible to override this by explicitly setting it on the reader or writer:
|
Processing XLSX and ODS files requires temporary files to be created. By default, {{ site.spout_html }} will use the system default temporary folder (as returned by `sys_get_temp_dir()`). It is possible to override this by explicitly setting it on the reader or writer:
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace Box\Spout\Writer\Common\Entity;
|
namespace Box\Spout\Writer\Common\Entity;
|
||||||
|
|
||||||
use Box\Spout\Writer\Common\Manager\SheetManager;
|
use Box\Spout\Writer\Common\Manager\SheetManager;
|
||||||
|
use Box\Spout\Writer\XLSX\Entity\SheetView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Sheet
|
* Class Sheet
|
||||||
@ -27,6 +28,9 @@ class Sheet
|
|||||||
/** @var SheetManager Sheet manager */
|
/** @var SheetManager Sheet manager */
|
||||||
private $sheetManager;
|
private $sheetManager;
|
||||||
|
|
||||||
|
/** @var SheetView */
|
||||||
|
private $sheetView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
|
* @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
|
||||||
* @param string $associatedWorkbookId ID of the sheet's associated workbook
|
* @param string $associatedWorkbookId ID of the sheet's associated workbook
|
||||||
@ -108,4 +112,31 @@ class Sheet
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return SheetView|null
|
||||||
|
*/
|
||||||
|
public function getSheetView(): ?SheetView
|
||||||
|
{
|
||||||
|
return $this->sheetView;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SheetView $sheetView
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setSheetView(SheetView $sheetView)
|
||||||
|
{
|
||||||
|
$this->sheetView = $sheetView;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasSheetView(): bool
|
||||||
|
{
|
||||||
|
return $this->sheetView instanceof SheetView;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,9 @@ class Worksheet
|
|||||||
/** @var int Index of the last written row */
|
/** @var int Index of the last written row */
|
||||||
private $lastWrittenRowIndex;
|
private $lastWrittenRowIndex;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $hasStarted = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Worksheet constructor.
|
* Worksheet constructor.
|
||||||
*
|
*
|
||||||
@ -110,4 +113,20 @@ class Worksheet
|
|||||||
// sheet index is zero-based, while ID is 1-based
|
// sheet index is zero-based, while ID is 1-based
|
||||||
return $this->externalSheet->getIndex() + 1;
|
return $this->externalSheet->getIndex() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasStarted(): bool
|
||||||
|
{
|
||||||
|
return $this->hasStarted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $hasStarted
|
||||||
|
*/
|
||||||
|
public function setHasStarted(bool $hasStarted = true): void
|
||||||
|
{
|
||||||
|
$this->hasStarted = $hasStarted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,8 +131,6 @@ abstract class WorkbookManagerAbstract implements WorkbookManagerInterface
|
|||||||
$worksheetFilePath = $this->getWorksheetFilePath($sheet);
|
$worksheetFilePath = $this->getWorksheetFilePath($sheet);
|
||||||
$worksheet = $this->entityFactory->createWorksheet($worksheetFilePath, $sheet);
|
$worksheet = $this->entityFactory->createWorksheet($worksheetFilePath, $sheet);
|
||||||
|
|
||||||
$this->worksheetManager->startSheet($worksheet);
|
|
||||||
|
|
||||||
$worksheets[] = $worksheet;
|
$worksheets[] = $worksheet;
|
||||||
$this->workbook->setWorksheets($worksheets);
|
$this->workbook->setWorksheets($worksheets);
|
||||||
|
|
||||||
@ -223,8 +221,15 @@ abstract class WorkbookManagerAbstract implements WorkbookManagerInterface
|
|||||||
if ($hasReachedMaxRows) {
|
if ($hasReachedMaxRows) {
|
||||||
// ... continue writing in a new sheet if option set
|
// ... continue writing in a new sheet if option set
|
||||||
if ($this->optionsManager->getOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY)) {
|
if ($this->optionsManager->getOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY)) {
|
||||||
|
$previousSheet = $currentWorksheet->getExternalSheet();
|
||||||
$currentWorksheet = $this->addNewSheetAndMakeItCurrent();
|
$currentWorksheet = $this->addNewSheetAndMakeItCurrent();
|
||||||
|
|
||||||
|
// Use the same sheet view if set
|
||||||
|
$sheet = $currentWorksheet->getExternalSheet();
|
||||||
|
if ($previousSheet->hasSheetView()) {
|
||||||
|
$sheet->setSheetView($previousSheet->getSheetView());
|
||||||
|
}
|
||||||
|
|
||||||
$this->addRowToWorksheet($currentWorksheet, $row);
|
$this->addRowToWorksheet($currentWorksheet, $row);
|
||||||
} else {
|
} else {
|
||||||
// otherwise, do nothing as the data won't be written anyways
|
// otherwise, do nothing as the data won't be written anyways
|
||||||
|
295
src/Spout/Writer/XLSX/Entity/SheetView.php
Normal file
295
src/Spout/Writer/XLSX/Entity/SheetView.php
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Box\Spout\Writer\XLSX\Entity;
|
||||||
|
|
||||||
|
use Box\Spout\Common\Exception\InvalidArgumentException;
|
||||||
|
use Box\Spout\Reader\XLSX\Helper\CellHelper;
|
||||||
|
|
||||||
|
class SheetView
|
||||||
|
{
|
||||||
|
/** @var bool */
|
||||||
|
protected $showFormulas = false;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $showGridLines = true;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $showRowcolHeaders = true;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $showZeroes = true;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $rightToLeft = false;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $tabSelected = false;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $showOutlineSymbols = true;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $defaultGridColor = true;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
protected $view = 'normal';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
protected $topLeftCell = 'A1';
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
protected $colorId = 64;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
protected $zoomScale = 100;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
protected $zoomScaleNormal = 100;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
protected $zoomScalePageLayoutView = 100;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
protected $workbookViewId = 0;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
protected $freezeRow = 0;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
protected $freezeColumn = 'A';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $showFormulas
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setShowFormulas(bool $showFormulas): self
|
||||||
|
{
|
||||||
|
$this->showFormulas = $showFormulas;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $showGridLines
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setShowGridLines(bool $showGridLines): self
|
||||||
|
{
|
||||||
|
$this->showGridLines = $showGridLines;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $showRowcolHeaders
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setShowRowcolHeaders(bool $showRowcolHeaders): self
|
||||||
|
{
|
||||||
|
$this->showRowcolHeaders = $showRowcolHeaders;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $showZeroes
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setShowZeroes(bool $showZeroes): self
|
||||||
|
{
|
||||||
|
$this->showZeroes = $showZeroes;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $rightToLeft
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setRightToLeft(bool $rightToLeft): self
|
||||||
|
{
|
||||||
|
$this->rightToLeft = $rightToLeft;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $tabSelected
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setTabSelected(bool $tabSelected): self
|
||||||
|
{
|
||||||
|
$this->tabSelected = $tabSelected;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $showOutlineSymbols
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setShowOutlineSymbols(bool $showOutlineSymbols): self
|
||||||
|
{
|
||||||
|
$this->showOutlineSymbols = $showOutlineSymbols;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $defaultGridColor
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setDefaultGridColor(bool $defaultGridColor): self
|
||||||
|
{
|
||||||
|
$this->defaultGridColor = $defaultGridColor;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $view
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setView(string $view): self
|
||||||
|
{
|
||||||
|
$this->view = $view;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $topLeftCell
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setTopLeftCell(string $topLeftCell): self
|
||||||
|
{
|
||||||
|
$this->topLeftCell = $topLeftCell;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $colorId
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setColorId(int $colorId): self
|
||||||
|
{
|
||||||
|
$this->colorId = $colorId;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $zoomScale
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setZoomScale(int $zoomScale): self
|
||||||
|
{
|
||||||
|
$this->zoomScale = $zoomScale;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $zoomScaleNormal
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setZoomScaleNormal(int $zoomScaleNormal): self
|
||||||
|
{
|
||||||
|
$this->zoomScaleNormal = $zoomScaleNormal;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $zoomScalePageLayoutView
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setZoomScalePageLayoutView(int $zoomScalePageLayoutView): self
|
||||||
|
{
|
||||||
|
$this->zoomScalePageLayoutView = $zoomScalePageLayoutView;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $workbookViewId
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setWorkbookViewId(int $workbookViewId): self
|
||||||
|
{
|
||||||
|
$this->workbookViewId = $workbookViewId;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $freezeRow Set to 2 to fix the first row
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setFreezeRow(int $freezeRow): self
|
||||||
|
{
|
||||||
|
if ($freezeRow < 1) {
|
||||||
|
throw new InvalidArgumentException('Freeze row must be a positive integer', 1589543073);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->freezeRow = $freezeRow;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $freezeColumn Set to B to fix the first column
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setFreezeColumn(string $freezeColumn): self
|
||||||
|
{
|
||||||
|
$this->freezeColumn = strtoupper($freezeColumn);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getXml(): string
|
||||||
|
{
|
||||||
|
return '<sheetView' . $this->getSheetViewAttributes() . '>' .
|
||||||
|
$this->getFreezeCellPaneXml() .
|
||||||
|
'</sheetView>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getSheetViewAttributes(): string
|
||||||
|
{
|
||||||
|
// Get class properties
|
||||||
|
$propertyValues = get_object_vars($this);
|
||||||
|
unset($propertyValues['freezeRow'], $propertyValues['freezeColumn']);
|
||||||
|
|
||||||
|
return $this->generateAttributes($propertyValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getFreezeCellPaneXml(): string
|
||||||
|
{
|
||||||
|
if ($this->freezeRow < 2 && $this->freezeColumn === 'A') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$columnIndex = CellHelper::getColumnIndexFromCellIndex($this->freezeColumn . '1');
|
||||||
|
|
||||||
|
return '<pane' . $this->generateAttributes([
|
||||||
|
'xSplit' => $columnIndex,
|
||||||
|
'ySplit' => $this->freezeRow - 1,
|
||||||
|
'topLeftCell' => $this->freezeColumn . $this->freezeRow,
|
||||||
|
'activePane' => 'bottomRight',
|
||||||
|
'state' => 'frozen',
|
||||||
|
]) . '/>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $data with key containing the attribute name and value containing the attribute value
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function generateAttributes(array $data): string
|
||||||
|
{
|
||||||
|
// Create attribute for each key
|
||||||
|
$attributes = array_map(function ($key, $value) {
|
||||||
|
if (is_bool($value)) {
|
||||||
|
$value = $value ? 'true' : 'false';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $key . '="' . $value . '"';
|
||||||
|
}, array_keys($data), $data);
|
||||||
|
|
||||||
|
// Append all attributes
|
||||||
|
return ' ' . implode(' ', $attributes);
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,7 @@ use Box\Spout\Writer\Common\Manager\RegisteredStyle;
|
|||||||
use Box\Spout\Writer\Common\Manager\RowManager;
|
use Box\Spout\Writer\Common\Manager\RowManager;
|
||||||
use Box\Spout\Writer\Common\Manager\Style\StyleMerger;
|
use Box\Spout\Writer\Common\Manager\Style\StyleMerger;
|
||||||
use Box\Spout\Writer\Common\Manager\WorksheetManagerInterface;
|
use Box\Spout\Writer\Common\Manager\WorksheetManagerInterface;
|
||||||
|
use Box\Spout\Writer\XLSX\Entity\SheetView;
|
||||||
use Box\Spout\Writer\XLSX\Manager\Style\StyleManager;
|
use Box\Spout\Writer\XLSX\Manager\Style\StyleManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,13 +102,34 @@ EOD;
|
|||||||
*/
|
*/
|
||||||
public function startSheet(Worksheet $worksheet)
|
public function startSheet(Worksheet $worksheet)
|
||||||
{
|
{
|
||||||
|
// Only start once
|
||||||
|
if ($worksheet->hasStarted()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$sheetFilePointer = \fopen($worksheet->getFilePath(), 'w');
|
$sheetFilePointer = \fopen($worksheet->getFilePath(), 'w');
|
||||||
$this->throwIfSheetFilePointerIsNotAvailable($sheetFilePointer);
|
$this->throwIfSheetFilePointerIsNotAvailable($sheetFilePointer);
|
||||||
|
|
||||||
$worksheet->setFilePointer($sheetFilePointer);
|
$worksheet->setFilePointer($sheetFilePointer);
|
||||||
|
|
||||||
\fwrite($sheetFilePointer, self::SHEET_XML_FILE_HEADER);
|
\fwrite($sheetFilePointer, self::SHEET_XML_FILE_HEADER);
|
||||||
|
$this->addSheetViews($sheetFilePointer, $worksheet);
|
||||||
\fwrite($sheetFilePointer, '<sheetData>');
|
\fwrite($sheetFilePointer, '<sheetData>');
|
||||||
|
|
||||||
|
$worksheet->setHasStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param resource $sheetFilePointer
|
||||||
|
* @param resourceWorksheet $worksheet
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function addSheetViews($sheetFilePointer, Worksheet $worksheet): void
|
||||||
|
{
|
||||||
|
$sheet = $worksheet->getExternalSheet();
|
||||||
|
if ($sheet->hasSheetView()) {
|
||||||
|
\fwrite($sheetFilePointer, '<sheetViews>' . $sheet->getSheetView()->getXml() . '</sheetViews>');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,6 +151,9 @@ EOD;
|
|||||||
*/
|
*/
|
||||||
public function addRow(Worksheet $worksheet, Row $row)
|
public function addRow(Worksheet $worksheet, Row $row)
|
||||||
{
|
{
|
||||||
|
// Start the sheet when the first row is added
|
||||||
|
$this->startSheet($worksheet);
|
||||||
|
|
||||||
if (!$this->rowManager->isEmpty($row)) {
|
if (!$this->rowManager->isEmpty($row)) {
|
||||||
$this->addNonEmptyRow($worksheet, $row);
|
$this->addNonEmptyRow($worksheet, $row);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user