Differences Between: [Versions 310 and 400] [Versions 311 and 400] [Versions 39 and 400] [Versions 400 and 402] [Versions 400 and 403]
1 <?php 2 3 namespace PhpOffice\PhpSpreadsheet\Writer; 4 5 use PhpOffice\PhpSpreadsheet\Calculation\Calculation; 6 use PhpOffice\PhpSpreadsheet\Spreadsheet; 7 8 class Csv extends BaseWriter 9 { 10 /** 11 * PhpSpreadsheet object. 12 * 13 * @var Spreadsheet 14 */ 15 private $spreadsheet; 16 17 /** 18 * Delimiter. 19 * 20 * @var string 21 */ 22 private $delimiter = ','; 23 24 /** 25 * Enclosure. 26 * 27 * @var string 28 */ 29 private $enclosure = '"'; 30 31 /** 32 * Line ending. 33 * 34 * @var string 35 */ 36 private $lineEnding = PHP_EOL; 37 38 /** 39 * Sheet index to write. 40 * 41 * @var int 42 */ 43 private $sheetIndex = 0; 44 45 /** 46 * Whether to write a BOM (for UTF8). 47 * 48 * @var bool 49 */ 50 private $useBOM = false; 51 52 /** 53 * Whether to write a Separator line as the first line of the file 54 * sep=x. 55 * 56 * @var bool 57 */ 58 private $includeSeparatorLine = false; 59 60 /** 61 * Whether to write a fully Excel compatible CSV file. 62 * 63 * @var bool 64 */ 65 private $excelCompatibility = false; 66 67 /** 68 * Output encoding. 69 * 70 * @var string 71 */ 72 private $outputEncoding = ''; 73 74 /** 75 * Create a new CSV. 76 * 77 * @param Spreadsheet $spreadsheet Spreadsheet object 78 */ 79 public function __construct(Spreadsheet $spreadsheet) 80 { 81 $this->spreadsheet = $spreadsheet; 82 } 83 84 /** 85 * Save PhpSpreadsheet to file. 86 * 87 * @param resource|string $filename 88 */ 89 public function save($filename, int $flags = 0): void 90 { 91 $this->processFlags($flags); 92 93 // Fetch sheet 94 $sheet = $this->spreadsheet->getSheet($this->sheetIndex); 95 96 $saveDebugLog = Calculation::getInstance($this->spreadsheet)->getDebugLog()->getWriteDebugLog(); 97 Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog(false); 98 $saveArrayReturnType = Calculation::getArrayReturnType(); 99 Calculation::setArrayReturnType(Calculation::RETURN_ARRAY_AS_VALUE); 100 101 // Open file 102 $this->openFileHandle($filename); 103 104 if ($this->excelCompatibility) { 105 $this->setUseBOM(true); // Enforce UTF-8 BOM Header 106 $this->setIncludeSeparatorLine(true); // Set separator line 107 $this->setEnclosure('"'); // Set enclosure to " 108 $this->setDelimiter(';'); // Set delimiter to a semi-colon 109 $this->setLineEnding("\r\n"); 110 } 111 112 if ($this->useBOM) { 113 // Write the UTF-8 BOM code if required 114 fwrite($this->fileHandle, "\xEF\xBB\xBF"); 115 } 116 117 if ($this->includeSeparatorLine) { 118 // Write the separator line if required 119 fwrite($this->fileHandle, 'sep=' . $this->getDelimiter() . $this->lineEnding); 120 } 121 122 // Identify the range that we need to extract from the worksheet 123 $maxCol = $sheet->getHighestDataColumn(); 124 $maxRow = $sheet->getHighestDataRow(); 125 126 // Write rows to file 127 for ($row = 1; $row <= $maxRow; ++$row) { 128 // Convert the row to an array... 129 $cellsArray = $sheet->rangeToArray('A' . $row . ':' . $maxCol . $row, '', $this->preCalculateFormulas); 130 // ... and write to the file 131 $this->writeLine($this->fileHandle, $cellsArray[0]); 132 } 133 134 $this->maybeCloseFileHandle(); 135 Calculation::setArrayReturnType($saveArrayReturnType); 136 Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog); 137 } 138 139 /** 140 * Get delimiter. 141 * 142 * @return string 143 */ 144 public function getDelimiter() 145 { 146 return $this->delimiter; 147 } 148 149 /** 150 * Set delimiter. 151 * 152 * @param string $delimiter Delimiter, defaults to ',' 153 * 154 * @return $this 155 */ 156 public function setDelimiter($delimiter) 157 { 158 $this->delimiter = $delimiter; 159 160 return $this; 161 } 162 163 /** 164 * Get enclosure. 165 * 166 * @return string 167 */ 168 public function getEnclosure() 169 { 170 return $this->enclosure; 171 } 172 173 /** 174 * Set enclosure. 175 * 176 * @param string $enclosure Enclosure, defaults to " 177 * 178 * @return $this 179 */ 180 public function setEnclosure($enclosure = '"') 181 { 182 $this->enclosure = $enclosure; 183 184 return $this; 185 } 186 187 /** 188 * Get line ending. 189 * 190 * @return string 191 */ 192 public function getLineEnding() 193 { 194 return $this->lineEnding; 195 } 196 197 /** 198 * Set line ending. 199 * 200 * @param string $lineEnding Line ending, defaults to OS line ending (PHP_EOL) 201 * 202 * @return $this 203 */ 204 public function setLineEnding($lineEnding) 205 { 206 $this->lineEnding = $lineEnding; 207 208 return $this; 209 } 210 211 /** 212 * Get whether BOM should be used. 213 * 214 * @return bool 215 */ 216 public function getUseBOM() 217 { 218 return $this->useBOM; 219 } 220 221 /** 222 * Set whether BOM should be used. 223 * 224 * @param bool $useBOM Use UTF-8 byte-order mark? Defaults to false 225 * 226 * @return $this 227 */ 228 public function setUseBOM($useBOM) 229 { 230 $this->useBOM = $useBOM; 231 232 return $this; 233 } 234 235 /** 236 * Get whether a separator line should be included. 237 * 238 * @return bool 239 */ 240 public function getIncludeSeparatorLine() 241 { 242 return $this->includeSeparatorLine; 243 } 244 245 /** 246 * Set whether a separator line should be included as the first line of the file. 247 * 248 * @param bool $includeSeparatorLine Use separator line? Defaults to false 249 * 250 * @return $this 251 */ 252 public function setIncludeSeparatorLine($includeSeparatorLine) 253 { 254 $this->includeSeparatorLine = $includeSeparatorLine; 255 256 return $this; 257 } 258 259 /** 260 * Get whether the file should be saved with full Excel Compatibility. 261 * 262 * @return bool 263 */ 264 public function getExcelCompatibility() 265 { 266 return $this->excelCompatibility; 267 } 268 269 /** 270 * Set whether the file should be saved with full Excel Compatibility. 271 * 272 * @param bool $excelCompatibility Set the file to be written as a fully Excel compatible csv file 273 * Note that this overrides other settings such as useBOM, enclosure and delimiter 274 * 275 * @return $this 276 */ 277 public function setExcelCompatibility($excelCompatibility) 278 { 279 $this->excelCompatibility = $excelCompatibility; 280 281 return $this; 282 } 283 284 /** 285 * Get sheet index. 286 * 287 * @return int 288 */ 289 public function getSheetIndex() 290 { 291 return $this->sheetIndex; 292 } 293 294 /** 295 * Set sheet index. 296 * 297 * @param int $sheetIndex Sheet index 298 * 299 * @return $this 300 */ 301 public function setSheetIndex($sheetIndex) 302 { 303 $this->sheetIndex = $sheetIndex; 304 305 return $this; 306 } 307 308 /** 309 * Get output encoding. 310 * 311 * @return string 312 */ 313 public function getOutputEncoding() 314 { 315 return $this->outputEncoding; 316 } 317 318 /** 319 * Set output encoding. 320 * 321 * @param string $outputEnconding Output encoding 322 * 323 * @return $this 324 */ 325 public function setOutputEncoding($outputEnconding) 326 { 327 $this->outputEncoding = $outputEnconding; 328 329 return $this; 330 } 331 332 /** @var bool */ 333 private $enclosureRequired = true; 334 335 public function setEnclosureRequired(bool $value): self 336 { 337 $this->enclosureRequired = $value; 338 339 return $this; 340 } 341 342 public function getEnclosureRequired(): bool 343 { 344 return $this->enclosureRequired; 345 } 346 347 /** 348 * Convert boolean to TRUE/FALSE; otherwise return element cast to string. 349 * 350 * @param mixed $element 351 */ 352 private static function elementToString($element): string 353 { 354 if (is_bool($element)) { 355 return $element ? 'TRUE' : 'FALSE'; 356 } 357 358 return (string) $element; 359 } 360 361 /** 362 * Write line to CSV file. 363 * 364 * @param resource $fileHandle PHP filehandle 365 * @param array $values Array containing values in a row 366 */ 367 private function writeLine($fileHandle, array $values): void 368 { 369 // No leading delimiter 370 $delimiter = ''; 371 372 // Build the line 373 $line = ''; 374 375 foreach ($values as $element) { 376 $element = self::elementToString($element); 377 // Add delimiter 378 $line .= $delimiter; 379 $delimiter = $this->delimiter; 380 // Escape enclosures 381 $enclosure = $this->enclosure; 382 if ($enclosure) { 383 // If enclosure is not required, use enclosure only if 384 // element contains newline, delimiter, or enclosure. 385 if (!$this->enclosureRequired && strpbrk($element, "$delimiter$enclosure\n") === false) { 386 $enclosure = ''; 387 } else { 388 $element = str_replace($enclosure, $enclosure . $enclosure, $element); 389 } 390 } 391 // Add enclosed string 392 $line .= $enclosure . $element . $enclosure; 393 } 394 395 // Add line ending 396 $line .= $this->lineEnding; 397 398 // Write to file 399 if ($this->outputEncoding != '') { 400 $line = mb_convert_encoding($line, $this->outputEncoding); 401 } 402 fwrite($fileHandle, $line); 403 } 404 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body