= 4.3.2 * @author Ignatius Teo * @copyright (C)2004 act28.com * @version 0.3 * @date 20 Jan 2005 * $Id: excel.php,v 1.3 2005/01/20 09:58:58 Owner Exp $ */ class xlsStream { /* private */ var $position = 0; // stream pointer var $mode = "rb"; // default stream open mode var $xlsfilename = null; // stream name var $fp = null; // internal stream pointer to physical file var $buffer = null; // internal write buffer var $endian = "unknown"; // little | unknown | big endian mode var $bin = array( "big" => "v", "little" => "s", "unknown" => "s", ); /** * detect server endian mode * thanks to Charles Turner for picking this one up * @access private * @params void * @returns void * @see http://www.phpdig.net/ref/rn45re877.html */ function _detect() { // A hex number that may represent 'abyz' $abyz = 0x6162797A; // Convert $abyz to a binary string containing 32 bits // Do the conversion the way that the system architecture wants to switch (pack ('L', $abyz)) { // Compare the value to the same value converted in a Little-Endian fashion case pack ('V', $abyz): $this->endian = "little"; break; // Compare the value to the same value converted in a Big-Endian fashion case pack ('N', $abyz): $this->endian = "big"; break; default: $this->endian = "unknown"; break; } } /** * called by fopen() to the stream * @param (string) $path file path * @param (string) $mode stream open mode * @param (int) $options stream options (STREAM_USE_PATH | * STREAM_REPORT_ERRORS) * @param (string) $opened_path stream opened path */ function stream_open($path, $mode, $options, &$opened_path) { $url = parse_url($path); $this->xlsfilename = '/' . $url['host'] . $url['path']; $this->position = 0; $this->mode = $mode; $this->_detect(); // detect endian mode //@TODO: test for invalid mode and trigger error if required // open underlying resource $this->fp = @fopen($this->xlsfilename, $this->mode); if (is_resource($this->fp)) { // empty the buffer $this->buffer = ""; if (preg_match("/^w|x/", $this->mode)) { // write an Excel stream header $str = pack(str_repeat($this->bin[$this->endian], 6), 0x809, 0x8, 0x0, 0x10, 0x0, 0x0); fwrite($this->fp, $str); $opened_path = $this->xlsfilename; $this->position = strlen($str); } } return is_resource($this->fp); } /** * read the underlying stream resource (automatically called by fread/fgets) * @todo modify this to convert an excel stream to an array * @param (int) $byte_count number of bytes to read (in 8192 byte blocks) */ function stream_read($byte_count) { if (is_resource($this->fp) && !feof($this->fp)) { $data .= fread($this->fp, $byte_count); $this->position = strlen($data); } return $data; } /** * called automatically by an fwrite() to the stream * @param (string) $data serialized array data string * representing a tabular worksheet */ function stream_write($data) { // buffer the data $this->buffer .= $data; $bufsize = strlen($data); return $bufsize; } /** * pseudo write function to manipulate the data * stream before writing it * modify this to suit your data array * @access private * @param (array) $data associative array representing * a tabular worksheet */ function _xls_stream_write($data) { $size = 0; // Nasty sloppy code mistake not to include this - MIS server is strict, not lenient about non-existent vars QLJ 11-12-2009 if (is_array($data) && !empty($data)) { $row = 0; foreach (array_values($data) as $_data) { if (is_array($_data) && !empty($_data)) { if ($row == 0) { // write the column headers foreach (array_keys($_data) as $col => $val) { // next line intentionally commented out // since we don't want a warning about the // extra bytes written // $size += $this->write($row, $col, $val); $this->_xlsWriteCell($row, $col, $val); } $row++; } $size = 0; // Nasty sloppy code mistake not to include this - MIS server is strict, not lenient about non-existent vars QLJ 11-12-2009 foreach (array_values($_data) as $col => $val) { $size += $this->_xlsWriteCell($row, $col, $val); } $row++; } } } return $size; } /** * Excel worksheet cell insertion * (single-worksheet supported only) * @access private * @param (int) $row worksheet row number (0...65536) * @param (int) $col worksheet column number (0..255) * @param (mixed) $val worksheet row number */ function _xlsWriteCell($row, $col, $val) { if (is_float($val) || is_int($val)) { // doubles, floats, integers $str = pack(str_repeat($this->bin[$this->endian], 5), 0x203, 14, $row, $col, 0x0); $str .= pack("d", $val); } else { // everything else is treated as a string $l = strlen($val); $str = pack(str_repeat($this->bin[$this->endian], 6), 0x204, 8 + $l, $row, $col, 0x0, $l); $str .= $val; } fwrite($this->fp, $str); $this->position += strlen($str); return strlen($str); } /** * called by an fclose() on the stream */ function stream_close() { if (preg_match("/^w|x/", $this->mode)) { // flush the buffer $bufsize = $this->_xls_stream_write(unserialize($this->buffer)); // ...and empty it $this->buffer = null; // write the xls EOF $str = pack(str_repeat($this->bin[$this->endian], 2), 0x0A, 0x00); $this->position += strlen($str); fwrite($this->fp, $str); } // ...and close the internal stream return fclose($this->fp); } function stream_eof() { $eof = true; if (is_resource($this->fp)) { $eof = feof($this->fp); } return $eof; } } stream_wrapper_register("xlsfile", "xlsStream") or die("Failed to register protocol: xlsfile"); ?>