Merge b54e21779913f3b1873d72b08097737b3bd2ec9b into 84596668410bea89d21aa9867b91e1550e359329

This commit is contained in:
kjkooistra-youwe 2022-05-26 15:55:26 +02:00 committed by GitHub
commit 876573579e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 394 additions and 2 deletions

View File

@ -50,6 +50,23 @@ $writer->setShouldCreateNewSheetsAutomatically(true); // default value
$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
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:

View File

@ -3,6 +3,7 @@
namespace Box\Spout\Writer\Common\Entity;
use Box\Spout\Writer\Common\Manager\SheetManager;
use Box\Spout\Writer\XLSX\Entity\SheetView;
/**
* Class Sheet
@ -27,6 +28,9 @@ class Sheet
/** @var SheetManager Sheet manager */
private $sheetManager;
/** @var SheetView */
private $sheetView;
/**
* @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
@ -108,4 +112,31 @@ class Sheet
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;
}
}

View File

@ -23,6 +23,9 @@ class Worksheet
/** @var int Index of the last written row */
private $lastWrittenRowIndex;
/** @var bool */
private $hasStarted = false;
/**
* Worksheet constructor.
*
@ -110,4 +113,20 @@ class Worksheet
// sheet index is zero-based, while ID is 1-based
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;
}
}

View File

@ -131,8 +131,6 @@ abstract class WorkbookManagerAbstract implements WorkbookManagerInterface
$worksheetFilePath = $this->getWorksheetFilePath($sheet);
$worksheet = $this->entityFactory->createWorksheet($worksheetFilePath, $sheet);
$this->worksheetManager->startSheet($worksheet);
$worksheets[] = $worksheet;
$this->workbook->setWorksheets($worksheets);
@ -223,8 +221,15 @@ abstract class WorkbookManagerAbstract implements WorkbookManagerInterface
if ($hasReachedMaxRows) {
// ... continue writing in a new sheet if option set
if ($this->optionsManager->getOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY)) {
$previousSheet = $currentWorksheet->getExternalSheet();
$currentWorksheet = $this->addNewSheetAndMakeItCurrent();
// Use the same sheet view if set
$sheet = $currentWorksheet->getExternalSheet();
if ($previousSheet->hasSheetView()) {
$sheet->setSheetView($previousSheet->getSheetView());
}
$this->addRowToWorksheet($currentWorksheet, $row);
} else {
// otherwise, do nothing as the data won't be written anyways

View 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);
}
}

View File

@ -17,6 +17,7 @@ use Box\Spout\Writer\Common\Manager\RegisteredStyle;
use Box\Spout\Writer\Common\Manager\RowManager;
use Box\Spout\Writer\Common\Manager\Style\StyleMerger;
use Box\Spout\Writer\Common\Manager\WorksheetManagerInterface;
use Box\Spout\Writer\XLSX\Entity\SheetView;
use Box\Spout\Writer\XLSX\Manager\Style\StyleManager;
/**
@ -101,13 +102,34 @@ EOD;
*/
public function startSheet(Worksheet $worksheet)
{
// Only start once
if ($worksheet->hasStarted()) {
return;
}
$sheetFilePointer = \fopen($worksheet->getFilePath(), 'w');
$this->throwIfSheetFilePointerIsNotAvailable($sheetFilePointer);
$worksheet->setFilePointer($sheetFilePointer);
\fwrite($sheetFilePointer, self::SHEET_XML_FILE_HEADER);
$this->addSheetViews($sheetFilePointer, $worksheet);
\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)
{
// Start the sheet when the first row is added
$this->startSheet($worksheet);
if (!$this->rowManager->isEmpty($row)) {
$this->addNonEmptyRow($worksheet, $row);
}