[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 3 namespace Box\Spout\Writer\ODS\Internal; 4 5 use Box\Spout\Common\Exception\InvalidArgumentException; 6 use Box\Spout\Common\Exception\IOException; 7 use Box\Spout\Common\Helper\StringHelper; 8 use Box\Spout\Writer\Common\Helper\CellHelper; 9 use Box\Spout\Writer\Common\Internal\WorksheetInterface; 10 11 /** 12 * Class Worksheet 13 * Represents a worksheet within a ODS file. The difference with the Sheet object is 14 * that this class provides an interface to write data 15 * 16 * @package Box\Spout\Writer\ODS\Internal 17 */ 18 class Worksheet implements WorksheetInterface 19 { 20 /** @var \Box\Spout\Writer\Common\Sheet The "external" sheet */ 21 protected $externalSheet; 22 23 /** @var string Path to the XML file that will contain the sheet data */ 24 protected $worksheetFilePath; 25 26 /** @var \Box\Spout\Common\Escaper\ODS Strings escaper */ 27 protected $stringsEscaper; 28 29 /** @var \Box\Spout\Common\Helper\StringHelper To help with string manipulation */ 30 protected $stringHelper; 31 32 /** @var Resource Pointer to the temporary sheet data file (e.g. worksheets-temp/sheet1.xml) */ 33 protected $sheetFilePointer; 34 35 /** @var int Maximum number of columns among all the written rows */ 36 protected $maxNumColumns = 1; 37 38 /** @var int Index of the last written row */ 39 protected $lastWrittenRowIndex = 0; 40 41 /** 42 * @param \Box\Spout\Writer\Common\Sheet $externalSheet The associated "external" sheet 43 * @param string $worksheetFilesFolder Temporary folder where the files to create the XLSX will be stored 44 * @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing 45 */ 46 public function __construct($externalSheet, $worksheetFilesFolder) 47 { 48 $this->externalSheet = $externalSheet; 49 /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ 50 $this->stringsEscaper = new \Box\Spout\Common\Escaper\ODS(); 51 $this->worksheetFilePath = $worksheetFilesFolder . '/sheet' . $externalSheet->getIndex() . '.xml'; 52 53 $this->stringHelper = new StringHelper(); 54 55 $this->startSheet(); 56 } 57 58 /** 59 * Prepares the worksheet to accept data 60 * The XML file does not contain the "<table:table>" node as it contains the sheet's name 61 * which may change during the execution of the program. It will be added at the end. 62 * 63 * @return void 64 * @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing 65 */ 66 protected function startSheet() 67 { 68 $this->sheetFilePointer = fopen($this->worksheetFilePath, 'w'); 69 $this->throwIfSheetFilePointerIsNotAvailable(); 70 } 71 72 /** 73 * Checks if the book has been created. Throws an exception if not created yet. 74 * 75 * @return void 76 * @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing 77 */ 78 protected function throwIfSheetFilePointerIsNotAvailable() 79 { 80 if (!$this->sheetFilePointer) { 81 throw new IOException('Unable to open sheet for writing.'); 82 } 83 } 84 85 /** 86 * @return string Path to the temporary sheet content XML file 87 */ 88 public function getWorksheetFilePath() 89 { 90 return $this->worksheetFilePath; 91 } 92 93 /** 94 * Returns the table XML root node as string. 95 * 96 * @return string <table> node as string 97 */ 98 public function getTableElementStartAsString() 99 { 100 $escapedSheetName = $this->stringsEscaper->escape($this->externalSheet->getName()); 101 $tableStyleName = 'ta' . ($this->externalSheet->getIndex() + 1); 102 103 $tableElement = '<table:table table:style-name="' . $tableStyleName . '" table:name="' . $escapedSheetName . '">'; 104 $tableElement .= '<table:table-column table:default-cell-style-name="ce1" table:style-name="co1" table:number-columns-repeated="' . $this->maxNumColumns . '"/>'; 105 106 return $tableElement; 107 } 108 109 /** 110 * @return \Box\Spout\Writer\Common\Sheet The "external" sheet 111 */ 112 public function getExternalSheet() 113 { 114 return $this->externalSheet; 115 } 116 117 /** 118 * @return int The index of the last written row 119 */ 120 public function getLastWrittenRowIndex() 121 { 122 return $this->lastWrittenRowIndex; 123 } 124 125 /** 126 * Adds data to the worksheet. 127 * 128 * @param array $dataRow Array containing data to be written. Cannot be empty. 129 * Example $dataRow = ['data1', 1234, null, '', 'data5']; 130 * @param \Box\Spout\Writer\Style\Style $style Style to be applied to the row. NULL means use default style. 131 * @return void 132 * @throws \Box\Spout\Common\Exception\IOException If the data cannot be written 133 * @throws \Box\Spout\Common\Exception\InvalidArgumentException If a cell value's type is not supported 134 */ 135 public function addRow($dataRow, $style) 136 { 137 $styleIndex = ($style->getId() + 1); // 1-based 138 $cellsCount = count($dataRow); 139 $this->maxNumColumns = max($this->maxNumColumns, $cellsCount); 140 141 $data = '<table:table-row table:style-name="ro1">'; 142 143 $currentCellIndex = 0; 144 $nextCellIndex = 1; 145 146 for ($i = 0; $i < $cellsCount; $i++) { 147 $currentCellValue = $dataRow[$currentCellIndex]; 148 149 // Using isset here because it is way faster than array_key_exists... 150 if (!isset($dataRow[$nextCellIndex]) || $currentCellValue !== $dataRow[$nextCellIndex]) { 151 $numTimesValueRepeated = ($nextCellIndex - $currentCellIndex); 152 $data .= $this->getCellContent($currentCellValue, $styleIndex, $numTimesValueRepeated); 153 154 $currentCellIndex = $nextCellIndex; 155 } 156 157 $nextCellIndex++; 158 } 159 160 $data .= '</table:table-row>'; 161 162 $wasWriteSuccessful = fwrite($this->sheetFilePointer, $data); 163 if ($wasWriteSuccessful === false) { 164 throw new IOException("Unable to write data in {$this->worksheetFilePath}"); 165 } 166 167 // only update the count if the write worked 168 $this->lastWrittenRowIndex++; 169 } 170 171 /** 172 * Returns the cell XML content, given its value. 173 * 174 * @param mixed $cellValue The value to be written 175 * @param int $styleIndex Index of the used style 176 * @param int $numTimesValueRepeated Number of times the value is consecutively repeated 177 * @return string The cell XML content 178 * @throws \Box\Spout\Common\Exception\InvalidArgumentException If a cell value's type is not supported 179 */ 180 protected function getCellContent($cellValue, $styleIndex, $numTimesValueRepeated) 181 { 182 $data = '<table:table-cell table:style-name="ce' . $styleIndex . '"'; 183 184 if ($numTimesValueRepeated !== 1) { 185 $data .= ' table:number-columns-repeated="' . $numTimesValueRepeated . '"'; 186 } 187 188 if (CellHelper::isNonEmptyString($cellValue)) { 189 $data .= ' office:value-type="string" calcext:value-type="string">'; 190 191 $cellValueLines = explode("\n", $cellValue); 192 foreach ($cellValueLines as $cellValueLine) { 193 $data .= '<text:p>' . $this->stringsEscaper->escape($cellValueLine) . '</text:p>'; 194 } 195 196 $data .= '</table:table-cell>'; 197 } else if (CellHelper::isBoolean($cellValue)) { 198 $data .= ' office:value-type="boolean" calcext:value-type="boolean" office:boolean-value="' . $cellValue . '">'; 199 $data .= '<text:p>' . $cellValue . '</text:p>'; 200 $data .= '</table:table-cell>'; 201 } else if (CellHelper::isNumeric($cellValue)) { 202 $data .= ' office:value-type="float" calcext:value-type="float" office:value="' . $cellValue . '">'; 203 $data .= '<text:p>' . $cellValue . '</text:p>'; 204 $data .= '</table:table-cell>'; 205 } else if (empty($cellValue)) { 206 $data .= '/>'; 207 } else { 208 throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . gettype($cellValue)); 209 } 210 211 return $data; 212 } 213 214 /** 215 * Closes the worksheet 216 * 217 * @return void 218 */ 219 public function close() 220 { 221 fclose($this->sheetFilePointer); 222 } 223 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |