1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
|
<?php
/**
* @version 1.4.0
* @package RSform!Pro 1.4.0
* @copyright (C) 2007-2013 www.rsjoomla.com
* @license GPL, http://www.gnu.org/copyleft/gpl.html
*/
defined('_JEXEC') or die('Restricted access');
class RSFormProXLS
{
/* 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",
);
var $start_row = 0;
var $end_row = 0;
var $use_headers = 0;
/**
* 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 open($path, $mode, $start_row=0)
{
$this->xlsfilename = $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);
$this->position = strlen($str);
}
if (preg_match("/a/", $this->mode))
{
$this->position = filesize($this->xlsfilename);
$this->start_row = (int) $start_row;
}
if ($this->use_headers)
$this->start_row += 1;
}
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 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 write($data)
{
if (is_array($data))
$data = serialize($data);
// buffer the data
$this->buffer .= $data;
$bufsize = strlen($data);
return $bufsize;
}
function write_headers($_data)
{
$row = 0;
// write the column headers only if we are not appending
if (preg_match("/^w|x/", $this->mode))
{
// write the column headers
foreach (array_values($_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);
}
return true;
}
return false;
}
/**
* 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;
if (is_array($data) && !empty($data))
{
$row = $this->start_row;
foreach (array_values($data) as $_data)
{
if (is_array($_data) && !empty($_data))
{
foreach (array_values($_data) as $col => $val)
{
$size += $this->_xlsWriteCell($row, $col, $val);
}
$row++;
}
}
$this->end_row = $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
{
$val = utf8_decode($val);
// 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 close()
{
$was_empty = empty($this->buffer);
// flush the buffer
$bufsize = $this->_xls_stream_write(unserialize($this->buffer));
// ...and empty it
$this->buffer = null;
// write the buffer when we are appending and the buffer is empty
// this should be the last step
if (preg_match("/a/", $this->mode) && $was_empty)
{
// 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 eof()
{
$eof = true;
if (is_resource($this->fp))
{
$eof = feof($this->fp);
}
return $eof;
}
}
?> |
Partager