diff --git a/docs/topics/reading-and-writing-to-file.md b/docs/topics/reading-and-writing-to-file.md index df8ed7c2..19928f04 100644 --- a/docs/topics/reading-and-writing-to-file.md +++ b/docs/topics/reading-and-writing-to-file.md @@ -436,7 +436,14 @@ You can read a .csv file using the following code: ```php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv(); -$spreadsheet = $reader->load("sample.csv"); +$spreadsheet = $reader->load('sample.csv'); +``` + +You can also treat a string as if it were the contents of a CSV file as follows: + +```php +$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv(); +$spreadsheet = $reader->loadSpreadsheetFromString($data); ``` #### Setting CSV options diff --git a/src/PhpSpreadsheet/Reader/Csv.php b/src/PhpSpreadsheet/Reader/Csv.php index e894e9a4..b604ceef 100644 --- a/src/PhpSpreadsheet/Reader/Csv.php +++ b/src/PhpSpreadsheet/Reader/Csv.php @@ -265,6 +265,18 @@ class Csv extends BaseReader return $this->loadIntoExisting($filename, $spreadsheet); } + /** + * Loads Spreadsheet from string. + */ + public function loadSpreadsheetFromString(string $contents): Spreadsheet + { + // Create new Spreadsheet + $spreadsheet = new Spreadsheet(); + + // Load into this instance + return $this->loadStringOrFile('data://text/plain,' . urlencode($contents), $spreadsheet, true); + } + private function openFileOrMemory(string $filename): void { // Open file @@ -314,16 +326,43 @@ class Csv extends BaseReader $this->preserveNumericFormatting = $preserveNumericFormatting; } + /** + * Open data uri for reading. + */ + private function openDataUri(string $filename): void + { + $fileHandle = fopen($filename, 'rb'); + if ($fileHandle === false) { + // @codeCoverageIgnoreStart + throw new ReaderException('Could not open file ' . $filename . ' for reading.'); + // @codeCoverageIgnoreEnd + } + + $this->fileHandle = $fileHandle; + } + /** * Loads PhpSpreadsheet from file into PhpSpreadsheet instance. */ public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet): Spreadsheet + { + return $this->loadStringOrFile($filename, $spreadsheet, false); + } + + /** + * Loads PhpSpreadsheet from file into PhpSpreadsheet instance. + */ + private function loadStringOrFile(string $filename, Spreadsheet $spreadsheet, bool $dataUri): Spreadsheet { // Deprecated in Php8.1 $iniset = $this->setAutoDetect('1'); // Open file - $this->openFileOrMemory($filename); + if ($dataUri) { + $this->openDataUri($filename); + } else { + $this->openFileOrMemory($filename); + } $fileHandle = $this->fileHandle; // Skip BOM, if any @@ -395,8 +434,8 @@ class Csv extends BaseReader } elseif (strcasecmp(Calculation::getFALSE(), $rowDatum) === 0 || strcasecmp('false', $rowDatum) === 0) { $rowDatum = false; } - } elseif ($rowDatum === null) { - $rowDatum = ''; + } else { + $rowDatum = $rowDatum ?? ''; } } diff --git a/tests/PhpSpreadsheetTests/Reader/Csv/CsvLoadFromStringTest.php b/tests/PhpSpreadsheetTests/Reader/Csv/CsvLoadFromStringTest.php new file mode 100644 index 00000000..fda1f723 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Csv/CsvLoadFromStringTest.php @@ -0,0 +1,26 @@ +loadSpreadsheetFromString($data); + $sheet = $spreadsheet->getActiveSheet(); + self::AssertSame('2+3', $sheet->getCell('B2')->getValue()); + self::AssertSame('7 , 8', $sheet->getCell('A3')->getValue()); + self::AssertSame("12\n13", $sheet->getCell('B4')->getValue()); + } +}