| 1 |
<?php |
| 2 |
|
| 3 |
namespace Box\Spout\Writer\Common\Internal; |
| 4 |
|
| 5 |
use Box\Spout\Writer\Exception\SheetNotFoundException; |
| 6 |
|
| 7 |
/** |
| 8 |
* Class Workbook |
| 9 |
* Represents a workbook within a spreadsheet file. |
| 10 |
* It provides the functions to work with worksheets. |
| 11 |
* |
| 12 |
* @package Box\Spout\Writer\Common |
| 13 |
*/ |
| 14 |
abstract class AbstractWorkbook implements WorkbookInterface |
| 15 |
{ |
| 16 |
/** @var bool Whether new sheets should be automatically created when the max rows limit per sheet is reached */ |
| 17 |
protected $shouldCreateNewSheetsAutomatically; |
| 18 |
|
| 19 |
/** @var string Timestamp based unique ID identifying the workbook */ |
| 20 |
protected $internalId; |
| 21 |
|
| 22 |
/** @var WorksheetInterface[] Array containing the workbook's sheets */ |
| 23 |
protected $worksheets = []; |
| 24 |
|
| 25 |
/** @var WorksheetInterface The worksheet where data will be written to */ |
| 26 |
protected $currentWorksheet; |
| 27 |
|
| 28 |
/** |
| 29 |
* @param bool $shouldCreateNewSheetsAutomatically |
| 30 |
* @param \Box\Spout\Writer\Style\Style $defaultRowStyle |
| 31 |
* @throws \Box\Spout\Common\Exception\IOException If unable to create at least one of the base folders |
| 32 |
*/ |
| 33 |
public function __construct($shouldCreateNewSheetsAutomatically, $defaultRowStyle) |
| 34 |
{ |
| 35 |
$this->shouldCreateNewSheetsAutomatically = $shouldCreateNewSheetsAutomatically; |
| 36 |
$this->internalId = uniqid(); |
| 37 |
} |
| 38 |
|
| 39 |
/** |
| 40 |
* @return \Box\Spout\Writer\Common\Helper\AbstractStyleHelper The specific style helper |
| 41 |
*/ |
| 42 |
abstract protected function getStyleHelper(); |
| 43 |
|
| 44 |
/** |
| 45 |
* @return int Maximum number of rows/columns a sheet can contain |
| 46 |
*/ |
| 47 |
abstract protected function getMaxRowsPerWorksheet(); |
| 48 |
|
| 49 |
/** |
| 50 |
* Creates a new sheet in the workbook. The current sheet remains unchanged. |
| 51 |
* |
| 52 |
* @return WorksheetInterface The created sheet |
| 53 |
* @throws \Box\Spout\Common\Exception\IOException If unable to open the sheet for writing |
| 54 |
*/ |
| 55 |
abstract public function addNewSheet(); |
| 56 |
|
| 57 |
/** |
| 58 |
* Creates a new sheet in the workbook and make it the current sheet. |
| 59 |
* The writing will resume where it stopped (i.e. data won't be truncated). |
| 60 |
* |
| 61 |
* @return WorksheetInterface The created sheet |
| 62 |
* @throws \Box\Spout\Common\Exception\IOException If unable to open the sheet for writing |
| 63 |
*/ |
| 64 |
public function addNewSheetAndMakeItCurrent() |
| 65 |
{ |
| 66 |
$worksheet = $this->addNewSheet(); |
| 67 |
$this->setCurrentWorksheet($worksheet); |
| 68 |
|
| 69 |
return $worksheet; |
| 70 |
} |
| 71 |
|
| 72 |
/** |
| 73 |
* @return WorksheetInterface[] All the workbook's sheets |
| 74 |
*/ |
| 75 |
public function getWorksheets() |
| 76 |
{ |
| 77 |
return $this->worksheets; |
| 78 |
} |
| 79 |
|
| 80 |
/** |
| 81 |
* Returns the current sheet |
| 82 |
* |
| 83 |
* @return WorksheetInterface The current sheet |
| 84 |
*/ |
| 85 |
public function getCurrentWorksheet() |
| 86 |
{ |
| 87 |
return $this->currentWorksheet; |
| 88 |
} |
| 89 |
|
| 90 |
/** |
| 91 |
* Sets the given sheet as the current one. New data will be written to this sheet. |
| 92 |
* The writing will resume where it stopped (i.e. data won't be truncated). |
| 93 |
* |
| 94 |
* @param \Box\Spout\Writer\Common\Sheet $sheet The "external" sheet to set as current |
| 95 |
* @return void |
| 96 |
* @throws \Box\Spout\Writer\Exception\SheetNotFoundException If the given sheet does not exist in the workbook |
| 97 |
*/ |
| 98 |
public function setCurrentSheet($sheet) |
| 99 |
{ |
| 100 |
$worksheet = $this->getWorksheetFromExternalSheet($sheet); |
| 101 |
if ($worksheet !== null) { |
| 102 |
$this->currentWorksheet = $worksheet; |
| 103 |
} else { |
| 104 |
throw new SheetNotFoundException('The given sheet does not exist in the workbook.'); |
| 105 |
} |
| 106 |
} |
| 107 |
|
| 108 |
/** |
| 109 |
* @param WorksheetInterface $worksheet |
| 110 |
* @return void |
| 111 |
*/ |
| 112 |
protected function setCurrentWorksheet($worksheet) |
| 113 |
{ |
| 114 |
$this->currentWorksheet = $worksheet; |
| 115 |
} |
| 116 |
|
| 117 |
/** |
| 118 |
* Returns the worksheet associated to the given external sheet. |
| 119 |
* |
| 120 |
* @param \Box\Spout\Writer\Common\Sheet $sheet |
| 121 |
* @return WorksheetInterface|null The worksheet associated to the given external sheet or null if not found. |
| 122 |
*/ |
| 123 |
protected function getWorksheetFromExternalSheet($sheet) |
| 124 |
{ |
| 125 |
$worksheetFound = null; |
| 126 |
|
| 127 |
foreach ($this->worksheets as $worksheet) { |
| 128 |
if ($worksheet->getExternalSheet() === $sheet) { |
| 129 |
$worksheetFound = $worksheet; |
| 130 |
break; |
| 131 |
} |
| 132 |
} |
| 133 |
|
| 134 |
return $worksheetFound; |
| 135 |
} |
| 136 |
|
| 137 |
/** |
| 138 |
* Adds data to the current sheet. |
| 139 |
* If shouldCreateNewSheetsAutomatically option is set to true, it will handle pagination |
| 140 |
* with the creation of new worksheets if one worksheet has reached its maximum capicity. |
| 141 |
* |
| 142 |
* @param array $dataRow Array containing data to be written. Cannot be empty. |
| 143 |
* Example $dataRow = ['data1', 1234, null, '', 'data5']; |
| 144 |
* @param \Box\Spout\Writer\Style\Style $style Style to be applied to the row. |
| 145 |
* @return void |
| 146 |
* @throws \Box\Spout\Common\Exception\IOException If trying to create a new sheet and unable to open the sheet for writing |
| 147 |
* @throws \Box\Spout\Writer\Exception\WriterException If unable to write data |
| 148 |
*/ |
| 149 |
public function addRowToCurrentWorksheet($dataRow, $style) |
| 150 |
{ |
| 151 |
$currentWorksheet = $this->getCurrentWorksheet(); |
| 152 |
$hasReachedMaxRows = $this->hasCurrentWorkseetReachedMaxRows(); |
| 153 |
$styleHelper = $this->getStyleHelper(); |
| 154 |
|
| 155 |
// if we reached the maximum number of rows for the current sheet... |
| 156 |
if ($hasReachedMaxRows) { |
| 157 |
// ... continue writing in a new sheet if option set |
| 158 |
if ($this->shouldCreateNewSheetsAutomatically) { |
| 159 |
$currentWorksheet = $this->addNewSheetAndMakeItCurrent(); |
| 160 |
|
| 161 |
$updatedStyle = $styleHelper->applyExtraStylesIfNeeded($style, $dataRow); |
| 162 |
$registeredStyle = $styleHelper->registerStyle($updatedStyle); |
| 163 |
$currentWorksheet->addRow($dataRow, $registeredStyle); |
| 164 |
} else { |
| 165 |
// otherwise, do nothing as the data won't be read anyways |
| 166 |
} |
| 167 |
} else { |
| 168 |
$updatedStyle = $styleHelper->applyExtraStylesIfNeeded($style, $dataRow); |
| 169 |
$registeredStyle = $styleHelper->registerStyle($updatedStyle); |
| 170 |
$currentWorksheet->addRow($dataRow, $registeredStyle); |
| 171 |
} |
| 172 |
} |
| 173 |
|
| 174 |
/** |
| 175 |
* @return bool Whether the current worksheet has reached the maximum number of rows per sheet. |
| 176 |
*/ |
| 177 |
protected function hasCurrentWorkseetReachedMaxRows() |
| 178 |
{ |
| 179 |
$currentWorksheet = $this->getCurrentWorksheet(); |
| 180 |
return ($currentWorksheet->getLastWrittenRowIndex() >= $this->getMaxRowsPerWorksheet()); |
| 181 |
} |
| 182 |
|
| 183 |
/** |
| 184 |
* Closes the workbook and all its associated sheets. |
| 185 |
* All the necessary files are written to disk and zipped together to create the ODS file. |
| 186 |
* All the temporary files are then deleted. |
| 187 |
* |
| 188 |
* @param resource $finalFilePointer Pointer to the ODS that will be created |
| 189 |
* @return void |
| 190 |
*/ |
| 191 |
abstract public function close($finalFilePointer); |
| 192 |
} |
| 193 |
|