diff --git a/src/Spout/Common/Type.php b/src/Spout/Common/Type.php index 6af7f35..35ca3c9 100644 --- a/src/Spout/Common/Type.php +++ b/src/Spout/Common/Type.php @@ -10,4 +10,6 @@ abstract class Type { const CSV = "csv"; const XLSX = "xlsx"; + const XLS = "xls"; + const HTM = "htm"; } diff --git a/src/Spout/Writer/HTM.php b/src/Spout/Writer/HTM.php new file mode 100644 index 0000000..dfd20d1 --- /dev/null +++ b/src/Spout/Writer/HTM.php @@ -0,0 +1,103 @@ +filePointer, "\n"); + fwrite($this->filePointer, "\n"); + fwrite($this->filePointer, "" . htmlentities(basename(basename($this->outputFilePath, '.html'), '.htm')) . "\n"); + fwrite($this->filePointer, "\n"); + fwrite($this->filePointer, "\n"); + fwrite($this->filePointer, "\n"); + } + + /** + * Adds data to the currently opened writer. + * + * @param array $dataRow Array containing data to be written. + * Example $dataRow = ['data1', 1234, null, '', 'data5']; + * @return void + * @throws \Box\Spout\Common\Exception\IOException If unable to write data + */ + protected function addRowToWriter(array $dataRow) + { + $wasWriteSuccessful = true; + if ($this->lastWrittenRowIndex == 0) { + $wasWriteSuccessful = $wasWriteSuccessful && fwrite($this->filePointer, "\n"); + } + if ($this->lastWrittenRowIndex == 1) { + $wasWriteSuccessful = $wasWriteSuccessful && fwrite($this->filePointer, "\n"); + } + $wasWriteSuccessful = $wasWriteSuccessful && fwrite($this->filePointer, "\n"); + foreach ($dataRow as $cell) { + $cell = nl2br(htmlentities($cell)); + + if ($this->lastWrittenRowIndex == 0) { + $wasWriteSuccessful = $wasWriteSuccessful && fwrite($this->filePointer, "\t\n"); + } else + { + $wasWriteSuccessful = $wasWriteSuccessful && fwrite($this->filePointer, "\t\n"); + } + } + $wasWriteSuccessful = $wasWriteSuccessful && fwrite($this->filePointer, "\n"); + if ($this->lastWrittenRowIndex == 0) { + $wasWriteSuccessful = $wasWriteSuccessful && fwrite($this->filePointer, "\n"); + } + + if ($wasWriteSuccessful === false) { + throw new IOException('Unable to write data'); + } + + $this->lastWrittenRowIndex++; + if ($this->lastWrittenRowIndex % self::FLUSH_THRESHOLD === 0) { + $this->globalFunctionsHelper->fflush($this->filePointer); + } + } + + /** + * Closes the HTM streamer, preventing any additional writing. + * If set, sets the headers and redirects output to the browser. + * + * @return void + */ + protected function closeWriter() + { + if ($this->filePointer) { + if ($this->lastWrittenRowIndex >= 1) { + fwrite($this->filePointer, "\n"); + } + fwrite($this->filePointer, "
{$cell}{$cell}
\n"); + fwrite($this->filePointer, "\n"); + fwrite($this->filePointer, "\n"); + + $this->globalFunctionsHelper->fclose($this->filePointer); + } + + $this->lastWrittenRowIndex = 0; + } +} diff --git a/src/Spout/Writer/WriterFactory.php b/src/Spout/Writer/WriterFactory.php index 321f0f1..5635ff4 100644 --- a/src/Spout/Writer/WriterFactory.php +++ b/src/Spout/Writer/WriterFactory.php @@ -33,6 +33,12 @@ class WriterFactory case Type::XLSX: $writer = new XLSX(); break; + case Type::XLS: + $writer = new XLS(); + break; + case Type::HTM: + $writer = new HTM(); + break; default: throw new UnsupportedTypeException('No writers supporting the given type: ' . $writerType); } diff --git a/src/Spout/Writer/XLS.php b/src/Spout/Writer/XLS.php new file mode 100644 index 0000000..dc3a295 --- /dev/null +++ b/src/Spout/Writer/XLS.php @@ -0,0 +1,193 @@ +col = 0; + $this->row = 0; + $this->bofMarker(); + } + + /** + * Writes the Excel Beginning of File marker + * + * @see pack() + * @return nothing + */ + private function bofMarker() + { + fwrite($this->filePointer, pack("ssssss", 0x809, 0x8, 0x0, 0x10, 0x0, 0x0)); + } + + /** + * Moves internal cursor all the way left, col = 0 + * + * @return nothing + */ + function home() + { + $this->col = 0; + } + + /** + * Moves internal cursor right by the amount specified + * + * @param optional integer $amount The amount to move right by, defaults to 1 + * @return integer The current column after the move + */ + function right($amount = 1) + { + $this->col += $amount; + return $this->col; + } + + /** + * Moves internal cursor down by amount + * + * @param optional integer $amount The amount to move down by, defaults to 1 + * @return integer The current row after the move + */ + function down($amount = 1) + { + $this->row += $amount; + return $this->row; + } + + /** + * Writes a number to the Excel Spreadsheet + * + * @see pack() + * @param integer $value The value to write out + * @return boolean Success status + */ + function number($value) + { + $wasWriteSuccessful = true; + $wasWriteSuccessful = $wasWriteSuccessful && fwrite($this->filePointer, pack("sssss", 0x203, 14, $this->row, $this->col, 0x0)); + $wasWriteSuccessful = $wasWriteSuccessful && fwrite($this->filePointer, pack("d", $value)); + return $wasWriteSuccessful; + } + + /** + * Writes a string (or label) to the Excel Spreadsheet + * + * @see pack() + * @param string $value The value to write out + * @return boolean Success status + */ + function label($value) + { + $value = str_replace(array("\r\n", "\r"), "\n", $value); + + // We're doing BIFF5, not BIFF8 - meaning a 255 char limit. If you want something good, use XLSX, else XLS for compatibility. + if (strlen($value) >= 255) { + $value = substr($value, 0, 255); + } + + $length = strlen($value); + $wasWriteSuccessful = true; + $wasWriteSuccessful = $wasWriteSuccessful && fwrite($this->filePointer, pack("ssssss", 0x204, 8 + $length, $this->row, $this->col, 0x0, $length)); + if ($value !='') { + $wasWriteSuccessful = $wasWriteSuccessful && fwrite($this->filePointer, $value); + } + return $wasWriteSuccessful; + } + + /** + * Adds data to the currently opened writer. + * + * @param array $dataRow Array containing data to be written. + * Example $dataRow = ['data1', 1234, null, '', 'data5']; + * @return void + * @throws \Box\Spout\Common\Exception\IOException If unable to write data + */ + protected function addRowToWriter(array $dataRow) + { + if ($this->row == 65536) { + // Hit the limit. You should have chosen XLSX + return; + } + + $wasWriteSuccessful = true; + + $this->home(); + foreach ($dataRow as $cell) { + if (is_integer($cell)) { + $wasWriteSuccessful = $wasWriteSuccessful && $this->number($cell); + } else + { + $wasWriteSuccessful = $wasWriteSuccessful && $this->label($cell); + } + $this->right(); + } + $this->down(); + + if ($wasWriteSuccessful === false) { + throw new IOException('Unable to write data'); + } + + if ($this->row % self::FLUSH_THRESHOLD === 0) { + $this->globalFunctionsHelper->fflush($this->filePointer); + } + } + + /** + * Writes the Excel End of File marker + * + * @see pack() + * @return nothing + */ + private function eofMarker() + { + fwrite($this->filePointer, pack("ss", 0x0A, 0x00)); + } + + /** + * Closes the XLS streamer, preventing any additional writing. + * If set, sets the headers and redirects output to the browser. + * + * @return void + */ + protected function closeWriter() + { + if ($this->filePointer) { + $this->eofMarker(); + + $this->globalFunctionsHelper->fclose($this->filePointer); + } + + $this->row = 0; + $this->col = 0; + } +}