readFilter = new DefaultReadFilter(); } /** * Set input encoding. * * @param string $pValue Input encoding */ public function setInputEncoding($pValue = 'UTF-8') { $this->inputEncoding = $pValue; return $this; } /** * Get input encoding. * * @return string */ public function getInputEncoding() { return $this->inputEncoding; } /** * Move filepointer past any BOM marker. */ protected function skipBOM() { rewind($this->fileHandle); switch ($this->inputEncoding) { case 'UTF-8': fgets($this->fileHandle, 4) == "\xEF\xBB\xBF" ? fseek($this->fileHandle, 3) : fseek($this->fileHandle, 0); break; case 'UTF-16LE': fgets($this->fileHandle, 3) == "\xFF\xFE" ? fseek($this->fileHandle, 2) : fseek($this->fileHandle, 0); break; case 'UTF-16BE': fgets($this->fileHandle, 3) == "\xFE\xFF" ? fseek($this->fileHandle, 2) : fseek($this->fileHandle, 0); break; case 'UTF-32LE': fgets($this->fileHandle, 5) == "\xFF\xFE\x00\x00" ? fseek($this->fileHandle, 4) : fseek($this->fileHandle, 0); break; case 'UTF-32BE': fgets($this->fileHandle, 5) == "\x00\x00\xFE\xFF" ? fseek($this->fileHandle, 4) : fseek($this->fileHandle, 0); break; default: break; } } /** * Identify any separator that is explicitly set in the file. */ protected function checkSeparator() { $line = fgets($this->fileHandle); if ($line === false) { return; } if ((strlen(trim($line, "\r\n")) == 5) && (stripos($line, 'sep=') === 0)) { $this->delimiter = substr($line, 4, 1); return; } return $this->skipBOM(); } /** * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns). * * @param string $pFilename * * @throws Exception */ public function listWorksheetInfo($pFilename) { // Open file if (!$this->canRead($pFilename)) { throw new Exception($pFilename . ' is an Invalid Spreadsheet file.'); } $this->openFile($pFilename); $fileHandle = $this->fileHandle; // Skip BOM, if any $this->skipBOM(); $this->checkSeparator(); $escapeEnclosures = ['\\' . $this->enclosure, $this->enclosure . $this->enclosure]; $worksheetInfo = []; $worksheetInfo[0]['worksheetName'] = 'Worksheet'; $worksheetInfo[0]['lastColumnLetter'] = 'A'; $worksheetInfo[0]['lastColumnIndex'] = 0; $worksheetInfo[0]['totalRows'] = 0; $worksheetInfo[0]['totalColumns'] = 0; // Loop through each line of the file in turn while (($rowData = fgetcsv($fileHandle, 0, $this->delimiter, $this->enclosure)) !== false) { ++$worksheetInfo[0]['totalRows']; $worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], count($rowData) - 1); } $worksheetInfo[0]['lastColumnLetter'] = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex']); $worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1; // Close file fclose($fileHandle); return $worksheetInfo; } /** * Loads Spreadsheet from file. * * @param string $pFilename * * @throws Exception * * @return \PhpOffice\PhpSpreadsheet\Spreadsheet */ public function load($pFilename) { // Create new Spreadsheet $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); // Load into this instance return $this->loadIntoExisting($pFilename, $spreadsheet); } /** * Loads PhpSpreadsheet from file into PhpSpreadsheet instance. * * @param string $pFilename * @param Spreadsheet $spreadsheet * * @throws Exception * * @return Spreadsheet */ public function loadIntoExisting($pFilename, Spreadsheet $spreadsheet) { $lineEnding = ini_get('auto_detect_line_endings'); ini_set('auto_detect_line_endings', true); // Open file if (!$this->canRead($pFilename)) { throw new Exception($pFilename . ' is an Invalid Spreadsheet file.'); } $this->openFile($pFilename); $fileHandle = $this->fileHandle; // Skip BOM, if any $this->skipBOM(); $this->checkSeparator(); // Create new PhpSpreadsheet object while ($spreadsheet->getSheetCount() <= $this->sheetIndex) { $spreadsheet->createSheet(); } $sheet = $spreadsheet->setActiveSheetIndex($this->sheetIndex); $escapeEnclosures = [ '\\' . $this->enclosure, $this->enclosure . $this->enclosure, ]; // Set our starting row based on whether we're in contiguous mode or not $currentRow = 1; if ($this->contiguous) { $currentRow = ($this->contiguousRow == -1) ? $sheet->getHighestRow() : $this->contiguousRow; } // Loop through each line of the file in turn while (($rowData = fgetcsv($fileHandle, 0, $this->delimiter, $this->enclosure)) !== false) { $columnLetter = 'A'; foreach ($rowData as $rowDatum) { if ($rowDatum != '' && $this->readFilter->readCell($columnLetter, $currentRow)) { // Unescape enclosures $rowDatum = str_replace($escapeEnclosures, $this->enclosure, $rowDatum); // Convert encoding if necessary if ($this->inputEncoding !== 'UTF-8') { $rowDatum = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::convertEncoding($rowDatum, 'UTF-8', $this->inputEncoding); } // Set cell value $sheet->getCell($columnLetter . $currentRow)->setValue($rowDatum); } ++$columnLetter; } ++$currentRow; } // Close file fclose($fileHandle); if ($this->contiguous) { $this->contiguousRow = $currentRow; } ini_set('auto_detect_line_endings', $lineEnding); // Return return $spreadsheet; } /** * Get delimiter. * * @return string */ public function getDelimiter() { return $this->delimiter; } /** * Set delimiter. * * @param string $pValue Delimiter, defaults to , * * @return CSV */ public function setDelimiter($pValue = ',') { $this->delimiter = $pValue; return $this; } /** * Get enclosure. * * @return string */ public function getEnclosure() { return $this->enclosure; } /** * Set enclosure. * * @param string $pValue Enclosure, defaults to " * * @return CSV */ public function setEnclosure($pValue = '"') { if ($pValue == '') { $pValue = '"'; } $this->enclosure = $pValue; return $this; } /** * Get sheet index. * * @return int */ public function getSheetIndex() { return $this->sheetIndex; } /** * Set sheet index. * * @param int $pValue Sheet index * * @return CSV */ public function setSheetIndex($pValue = 0) { $this->sheetIndex = $pValue; return $this; } /** * Set Contiguous. * * @param bool $contiguous */ public function setContiguous($contiguous = false) { $this->contiguous = (bool) $contiguous; if (!$contiguous) { $this->contiguousRow = -1; } return $this; } /** * Get Contiguous. * * @return bool */ public function getContiguous() { return $this->contiguous; } /** * Can the current IReader read the file? * * @param string $pFilename * * @throws Exception * * @return bool */ public function canRead($pFilename) { // Check if file exists try { $this->openFile($pFilename); } catch (Exception $e) { return false; } fclose($this->fileHandle); return true; } }