EOD; /** @var \Box\Spout\Writer\Common\Sheet The "external" sheet */ protected $externalSheet; /** @var string Path to the XML file that will contain the sheet data */ protected $worksheetFilePath; /** @var \Box\Spout\Writer\XLSX\Helper\SharedStringsHelper Helper to write shared strings */ protected $sharedStringsHelper; /** @var bool Whether inline or shared strings should be used */ protected $shouldUseInlineStrings; /** @var \Box\Spout\Common\Escaper\XLSX Strings escaper */ protected $stringsEscaper; /** @var Resource Pointer to the sheet data file (e.g. xl/worksheets/sheet1.xml) */ protected $sheetFilePointer; /** @var int Index of the last written row */ protected $lastWrittenRowIndex = 0; /** * @param \Box\Spout\Writer\Common\Sheet $externalSheet The associated "external" sheet * @param string $worksheetFilesFolder Temporary folder where the files to create the XLSX will be stored * @param \Box\Spout\Writer\XLSX\Helper\SharedStringsHelper $sharedStringsHelper Helper for shared strings * @param bool $shouldUseInlineStrings Whether inline or shared strings should be used * @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing */ public function __construct($externalSheet, $worksheetFilesFolder, $sharedStringsHelper, $shouldUseInlineStrings) { $this->externalSheet = $externalSheet; $this->sharedStringsHelper = $sharedStringsHelper; $this->shouldUseInlineStrings = $shouldUseInlineStrings; /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ $this->stringsEscaper = new \Box\Spout\Common\Escaper\XLSX(); $this->worksheetFilePath = $worksheetFilesFolder . '/' . strtolower($this->externalSheet->getName()) . '.xml'; $this->startSheet(); } /** * Prepares the worksheet to accept data * * @return void * @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing */ protected function startSheet() { $this->sheetFilePointer = fopen($this->worksheetFilePath, 'w'); $this->throwIfSheetFilePointerIsNotAvailable(); fwrite($this->sheetFilePointer, self::SHEET_XML_FILE_HEADER); fwrite($this->sheetFilePointer, ''); } /** * Checks if the book has been created. Throws an exception if not created yet. * * @return void * @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing */ protected function throwIfSheetFilePointerIsNotAvailable() { if (!$this->sheetFilePointer) { throw new IOException('Unable to open sheet for writing.'); } } /** * @return \Box\Spout\Writer\Common\Sheet The "external" sheet */ public function getExternalSheet() { return $this->externalSheet; } /** * @return int The index of the last written row */ public function getLastWrittenRowIndex() { return $this->lastWrittenRowIndex; } /** * @return int The ID of the worksheet */ public function getId() { // sheet index is zero-based, while ID is 1-based return $this->externalSheet->getIndex() + 1; } /** * Adds data to the worksheet. * * @param array $dataRow Array containing data to be written. Cannot be empty. * Example $dataRow = ['data1', 1234, null, '', 'data5']; * @param \Box\Spout\Writer\Style\Style $style Style to be applied to the row. NULL means use default style. * @return void * @throws \Box\Spout\Common\Exception\IOException If the data cannot be written * @throws \Box\Spout\Common\Exception\InvalidArgumentException If a cell value's type is not supported */ public function addRow($dataRow, $style) { $cellNumber = 0; $rowIndex = $this->lastWrittenRowIndex + 1; $numCells = count($dataRow); $rowXML = ''; foreach($dataRow as $cellValue) { $columnIndex = CellHelper::getCellIndexFromColumnIndex($cellNumber); $cellXML = 'getId() . '"'; if (CellHelper::isNonEmptyString($cellValue)) { // CFDB EDIT BEGIN: Special case added to handle HYPERLINK functions // this IF wrapping exiting code in ELSE $matches = array(); if (preg_match('/=HYPERLINK\("(.*)","(.*)"\)/', $cellValue, $matches)) { // Create a Formula $url = $this->stringsEscaper->escape($matches[1]); $text = $this->stringsEscaper->escape($matches[2]); $formula = sprintf('HYPERLINK("%s","%s")', $url, $text); $cellXML = sprintf( '%s%s', $columnIndex, $rowIndex, $formula, $text); } else { // CFDB EDIT END if ($this->shouldUseInlineStrings) { $cellXML .= ' t="inlineStr">' . $this->stringsEscaper->escape($cellValue) . ''; } else { $sharedStringId = $this->sharedStringsHelper->writeString($cellValue); $cellXML .= ' t="s">' . $sharedStringId . ''; } } // CFDB EDIT this line } else if (CellHelper::isBoolean($cellValue)) { $cellXML .= ' t="b">' . $cellValue . ''; } else if (CellHelper::isNumeric($cellValue)) { $cellXML .= '>' . $cellValue . ''; } else if (empty($cellValue)) { // don't write empty cells (not appending to $cellXML is the right behavior!) $cellXML = ''; } else { throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . gettype($cellValue)); } $rowXML .= $cellXML; $cellNumber++; } $rowXML .= ''; $wasWriteSuccessful = fwrite($this->sheetFilePointer, $rowXML); if ($wasWriteSuccessful === false) { throw new IOException("Unable to write data in {$this->worksheetFilePath}"); } // only update the count if the write worked $this->lastWrittenRowIndex++; } /** * Closes the worksheet * * @return void */ public function close() { fwrite($this->sheetFilePointer, ''); fwrite($this->sheetFilePointer, ''); fclose($this->sheetFilePointer); } }