<?php
namespace PhpOffice\PhpSpreadsheet\Writer;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
class Csv extends BaseWriter
{
/**
* PhpSpreadsheet object.
*
* @var Spreadsheet
*/
private $spreadsheet;
/**
* Delimiter.
*
* @var string
*/
private $delimiter = ',';
/**
* Enclosure.
*
* @var string
*/
private $enclosure = '"';
/**
* Line ending.
*
* @var string
*/
private $lineEnding = PHP_EOL;
/**
* Sheet index to write.
*
* @var int
*/
private $sheetIndex = 0;
/**
< * Whether to write a BOM (for UTF8).
> * Whether to write a UTF8 BOM.
*
* @var bool
*/
private $useBOM = false;
/**
* Whether to write a Separator line as the first line of the file
* sep=x.
*
* @var bool
*/
private $includeSeparatorLine = false;
/**
* Whether to write a fully Excel compatible CSV file.
*
* @var bool
*/
private $excelCompatibility = false;
/**
< * Create a new CSV.
> * Output encoding.
*
< * @param Spreadsheet $spreadsheet Spreadsheet object
> * @var string
> */
> private $outputEncoding = '';
>
> /**
> * Create a new CSV.
*/
public function __construct(Spreadsheet $spreadsheet)
{
$this->spreadsheet = $spreadsheet;
}
/**
* Save PhpSpreadsheet to file.
*
< * @param resource|string $pFilename
> * @param resource|string $filename
*/
< public function save($pFilename): void
> public function save($filename, int $flags = 0): void
{
> $this->processFlags($flags);
// Fetch sheet
>
$sheet = $this->spreadsheet->getSheet($this->sheetIndex);
$saveDebugLog = Calculation::getInstance($this->spreadsheet)->getDebugLog()->getWriteDebugLog();
Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog(false);
$saveArrayReturnType = Calculation::getArrayReturnType();
Calculation::setArrayReturnType(Calculation::RETURN_ARRAY_AS_VALUE);
// Open file
< $this->openFileHandle($pFilename);
> $this->openFileHandle($filename);
if ($this->excelCompatibility) {
$this->setUseBOM(true); // Enforce UTF-8 BOM Header
$this->setIncludeSeparatorLine(true); // Set separator line
$this->setEnclosure('"'); // Set enclosure to "
$this->setDelimiter(';'); // Set delimiter to a semi-colon
$this->setLineEnding("\r\n");
}
if ($this->useBOM) {
// Write the UTF-8 BOM code if required
fwrite($this->fileHandle, "\xEF\xBB\xBF");
}
if ($this->includeSeparatorLine) {
// Write the separator line if required
fwrite($this->fileHandle, 'sep=' . $this->getDelimiter() . $this->lineEnding);
}
// Identify the range that we need to extract from the worksheet
$maxCol = $sheet->getHighestDataColumn();
$maxRow = $sheet->getHighestDataRow();
// Write rows to file
for ($row = 1; $row <= $maxRow; ++$row) {
// Convert the row to an array...
$cellsArray = $sheet->rangeToArray('A' . $row . ':' . $maxCol . $row, '', $this->preCalculateFormulas);
// ... and write to the file
$this->writeLine($this->fileHandle, $cellsArray[0]);
}
$this->maybeCloseFileHandle();
Calculation::setArrayReturnType($saveArrayReturnType);
Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
}
< /**
< * Get delimiter.
< *
< * @return string
< */
< public function getDelimiter()
> public function getDelimiter(): string
{
return $this->delimiter;
}
< /**
< * Set delimiter.
< *
< * @param string $pValue Delimiter, defaults to ','
< *
< * @return $this
< */
< public function setDelimiter($pValue)
> public function setDelimiter(string $delimiter): self
{
< $this->delimiter = $pValue;
> $this->delimiter = $delimiter;
return $this;
}
< /**
< * Get enclosure.
< *
< * @return string
< */
< public function getEnclosure()
> public function getEnclosure(): string
{
return $this->enclosure;
}
< /**
< * Set enclosure.
< *
< * @param string $pValue Enclosure, defaults to "
< *
< * @return $this
< */
< public function setEnclosure($pValue = '"')
> public function setEnclosure(string $enclosure = '"'): self
{
< $this->enclosure = $pValue;
> $this->enclosure = $enclosure;
return $this;
}
< /**
< * Get line ending.
< *
< * @return string
< */
< public function getLineEnding()
> public function getLineEnding(): string
{
return $this->lineEnding;
}
< /**
< * Set line ending.
< *
< * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL)
< *
< * @return $this
< */
< public function setLineEnding($pValue)
> public function setLineEnding(string $lineEnding): self
{
< $this->lineEnding = $pValue;
> $this->lineEnding = $lineEnding;
return $this;
}
/**
* Get whether BOM should be used.
< *
< * @return bool
*/
< public function getUseBOM()
> public function getUseBOM(): bool
{
return $this->useBOM;
}
/**
< * Set whether BOM should be used.
< *
< * @param bool $pValue Use UTF-8 byte-order mark? Defaults to false
< *
< * @return $this
> * Set whether BOM should be used, typically when non-ASCII characters are used.
*/
< public function setUseBOM($pValue)
> public function setUseBOM(bool $useBOM): self
{
< $this->useBOM = $pValue;
> $this->useBOM = $useBOM;
return $this;
}
/**
* Get whether a separator line should be included.
< *
< * @return bool
*/
< public function getIncludeSeparatorLine()
> public function getIncludeSeparatorLine(): bool
{
return $this->includeSeparatorLine;
}
/**
* Set whether a separator line should be included as the first line of the file.
< *
< * @param bool $pValue Use separator line? Defaults to false
< *
< * @return $this
*/
< public function setIncludeSeparatorLine($pValue)
> public function setIncludeSeparatorLine(bool $includeSeparatorLine): self
{
< $this->includeSeparatorLine = $pValue;
> $this->includeSeparatorLine = $includeSeparatorLine;
return $this;
}
/**
* Get whether the file should be saved with full Excel Compatibility.
< *
< * @return bool
*/
< public function getExcelCompatibility()
> public function getExcelCompatibility(): bool
{
return $this->excelCompatibility;
}
/**
* Set whether the file should be saved with full Excel Compatibility.
*
< * @param bool $pValue Set the file to be written as a fully Excel compatible csv file
> * @param bool $excelCompatibility Set the file to be written as a fully Excel compatible csv file
* Note that this overrides other settings such as useBOM, enclosure and delimiter
< *
< * @return $this
*/
< public function setExcelCompatibility($pValue)
> public function setExcelCompatibility(bool $excelCompatibility): self
{
< $this->excelCompatibility = $pValue;
> $this->excelCompatibility = $excelCompatibility;
return $this;
}
< /**
< * Get sheet index.
< *
< * @return int
< */
< public function getSheetIndex()
> public function getSheetIndex(): int
{
return $this->sheetIndex;
}
< /**
< * Set sheet index.
< *
< * @param int $pValue Sheet index
< *
< * @return $this
< */
< public function setSheetIndex($pValue)
> public function setSheetIndex(int $sheetIndex): self
{
< $this->sheetIndex = $pValue;
> $this->sheetIndex = $sheetIndex;
return $this;
}
> public function getOutputEncoding(): string
private $enclosureRequired = true;
> {
> return $this->outputEncoding;
public function setEnclosureRequired(bool $value): self
> }
{
>
$this->enclosureRequired = $value;
> public function setOutputEncoding(string $outputEnconding): self
> {
return $this;
> $this->outputEncoding = $outputEnconding;
}
>
> return $this;
public function getEnclosureRequired(): bool
> }
{
>
return $this->enclosureRequired;
> /** @var bool */
}
/**
> * Convert boolean to TRUE/FALSE; otherwise return element cast to string.
* Write line to CSV file.
> *
*
> * @param mixed $element
* @param resource $pFileHandle PHP filehandle
> */
* @param array $pValues Array containing values in a row
> private static function elementToString($element): string
*/
> {
private function writeLine($pFileHandle, array $pValues): void
> if (is_bool($element)) {
{
> return $element ? 'TRUE' : 'FALSE';
// No leading delimiter
> }
$delimiter = '';
>
> return (string) $element;
// Build the line
> }
$line = '';
>
> /**
< * @param resource $pFileHandle PHP filehandle
< * @param array $pValues Array containing values in a row
> * @param resource $fileHandle PHP filehandle
> * @param array $values Array containing values in a row
< private function writeLine($pFileHandle, array $pValues): void
> private function writeLine($fileHandle, array $values): void
< foreach ($pValues as $element) {
> foreach ($values as $element) {
> $element = self::elementToString($element);
// Escape enclosures
$enclosure = $this->enclosure;
if ($enclosure) {
// If enclosure is not required, use enclosure only if
// element contains newline, delimiter, or enclosure.
if (!$this->enclosureRequired && strpbrk($element, "$delimiter$enclosure\n") === false) {
$enclosure = '';
} else {
$element = str_replace($enclosure, $enclosure . $enclosure, $element);
}
}
// Add enclosed string
$line .= $enclosure . $element . $enclosure;
}
// Add line ending
$line .= $this->lineEnding;
// Write to file
< fwrite($pFileHandle, $line);
> if ($this->outputEncoding != '') {
> $line = mb_convert_encoding($line, $this->outputEncoding);
> }
> fwrite($fileHandle, /** @scrutinizer ignore-type */ $line);
}
}