Source for file reader.php
Documentation is available at reader.php
//require_once 'PEAR.php';  
require_once 'oleread.inc';  
define('Spreadsheet_Excel_Reader_HAVE_ICONV', function_exists('iconv'));  
define('Spreadsheet_Excel_Reader_BIFF8', 0x600);  
define('Spreadsheet_Excel_Reader_BIFF7', 0x500);  
define('Spreadsheet_Excel_Reader_WorkbookGlobals', 0x5);  
define('Spreadsheet_Excel_Reader_Worksheet', 0x10);  
define('Spreadsheet_Excel_Reader_Type_BOF', 0x809);  
define('Spreadsheet_Excel_Reader_Type_EOF', 0x0a);  
define('Spreadsheet_Excel_Reader_Type_BOUNDSHEET', 0x85);  
define('Spreadsheet_Excel_Reader_Type_DIMENSION', 0x200);  
define('Spreadsheet_Excel_Reader_Type_ROW', 0x208);  
define('Spreadsheet_Excel_Reader_Type_DBCELL', 0xd7);  
define('Spreadsheet_Excel_Reader_Type_FILEPASS', 0x2f);  
define('Spreadsheet_Excel_Reader_Type_NOTE', 0x1c);  
define('Spreadsheet_Excel_Reader_Type_TXO', 0x1b6);  
define('Spreadsheet_Excel_Reader_Type_RK', 0x7e);  
define('Spreadsheet_Excel_Reader_Type_RK2', 0x27e);  
define('Spreadsheet_Excel_Reader_Type_MULRK', 0xbd);  
define('Spreadsheet_Excel_Reader_Type_MULBLANK', 0xbe);  
define('Spreadsheet_Excel_Reader_Type_INDEX', 0x20b);  
define('Spreadsheet_Excel_Reader_Type_SST', 0xfc);  
define('Spreadsheet_Excel_Reader_Type_EXTSST', 0xff);  
define('Spreadsheet_Excel_Reader_Type_CONTINUE', 0x3c);  
define('Spreadsheet_Excel_Reader_Type_LABEL', 0x204);  
define('Spreadsheet_Excel_Reader_Type_LABELSST', 0xfd);  
define('Spreadsheet_Excel_Reader_Type_NUMBER', 0x203);  
define('Spreadsheet_Excel_Reader_Type_NAME', 0x18);  
define('Spreadsheet_Excel_Reader_Type_ARRAY', 0x221);  
define('Spreadsheet_Excel_Reader_Type_STRING', 0x207);  
define('Spreadsheet_Excel_Reader_Type_FORMULA', 0x406);  
define('Spreadsheet_Excel_Reader_Type_FORMULA2', 0x6);  
define('Spreadsheet_Excel_Reader_Type_FORMAT', 0x41e);  
define('Spreadsheet_Excel_Reader_Type_XF', 0xe0);  
define('Spreadsheet_Excel_Reader_Type_BOOLERR', 0x205);  
define('Spreadsheet_Excel_Reader_Type_UNKNOWN', 0xffff);  
define('Spreadsheet_Excel_Reader_Type_NINETEENFOUR', 0x22);  
define('Spreadsheet_Excel_Reader_Type_MERGEDCELLS', 0xE5);  
define('Spreadsheet_Excel_Reader_utcOffsetDays' , 25569);  
define('Spreadsheet_Excel_Reader_utcOffsetDays1904', 24107);  
define('Spreadsheet_Excel_Reader_msInADay', 24 * 
60 * 
60);  
//define('Spreadsheet_Excel_Reader_DEF_NUM_FORMAT', "%.2f");  
define('Spreadsheet_Excel_Reader_DEF_NUM_FORMAT', "%s");  
// function file_get_contents for PHP < 4.3.0  
// Thanks Marian Steinbach for this function  
        $file = 
@fopen($filename, "rb", $use_include_path);  
            while (!feof($file)) $data .= 
fread($file, 1024);  
            // There was a problem opening the file  
//class Spreadsheet_Excel_Reader extends PEAR {  
        0x2 => 
"%1.2f", // "0.00",  
        0x3 => 
"%1.0f", //"#,##0",  
        0x4 => 
"%1.2f", //"#,##0.00",  
        0x5 => 
"%1.0f", /*"$#,##0;($#,##0)",*/  
        0x6 => 
'$%1.0f', /*"$#,##0;($#,##0)",*/  
        0x7 => 
'$%1.2f', //"$#,##0.00;($#,##0.00)",  
        0x8 => 
'$%1.2f', //"$#,##0.00;($#,##0.00)",  
        0x9 => 
'%1.0f%%', // "0%"  
        0xa => 
'%1.2f%%', // "0.00%"  
        0xb => 
'%1.2f', // 0.00E00",  
        0x25 => 
'%1.0f', // "#,##0;(#,##0)",  
        0x26 => 
'%1.0f', //"#,##0;(#,##0)",  
        0x27 => 
'%1.2f', //"#,##0.00;(#,##0.00)",  
        0x28 => 
'%1.2f', //"#,##0.00;(#,##0.00)",  
        0x29 => 
'%1.0f', //"#,##0;(#,##0)",  
        0x2a => 
'$%1.0f', //"$#,##0;($#,##0)",  
        0x2b => 
'%1.2f', //"#,##0.00;(#,##0.00)",  
        0x2c => 
'$%1.2f', //"$#,##0.00;($#,##0.00)",  
        0x30 => 
'%1.0f'); //"##0.0E0";  
    function read($sFileName) {  
        $res = 
$this->_ole->read($sFileName);  
        // oops, something goes wrong (Darko Miljanovic)  
            if($this->_ole->error == 
1) {  
                die('The filename ' . 
$sFileName . 
' is not readable');      
            // check other error codes here (eg bad fileformat, etc...)  
        $this->data = 
$this->_ole->getWorkBook();  
        $res = $this->_ole->read($sFileName);  
        if ($this->isError($res)) {  
            return $this->raiseError($res);  
        $total = $this->_ole->ppsTotal();  
        for ($i = 0; $i < $total; $i++) {  
            if ($this->_ole->isFile($i)) {  
                $type = unpack("v", $this->_ole->getData($i, 0, 2));  
                if ($type[''] == 0x0809)  { // check if it's a BIFF stream  
                    $this->data = $this->_ole->getData($i, 0, $this->_ole->getDataLength($i));  
        if ($this->_index === null) {  
            return $this->raiseError("$file doesn't seem to be an Excel file");  
    //echo "data =".$this->data;      
        $version = 
ord($this->data[$pos + 
4]) | 
ord($this->data[$pos + 
5])<<
8;  
        $substreamType = 
ord($this->data[$pos + 
6]) | 
ord($this->data[$pos + 
7])<<
8;  
        //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n";  
                     $limitpos = 
$spos + 
$length;  
                                       for ($i = 
0; $i < 
$uniqueStrings; $i++
) {  
        // Read in the number of characters  
                                                if ($spos == 
$limitpos) {  
                                                $conlength = 
ord($this->data[$spos+
2]) | 
ord($this->data[$spos+
3])<<
8;  
                                                $limitpos = 
$spos + 
$conlength;  
                                                $numChars = 
ord($this->data[$spos]) | 
(ord($this->data[$spos+
1]) << 
8);  
                                                //echo "i = $i pos = $pos numChars = $numChars ";  
                                                $optionFlags = 
ord($this->data[$spos]);  
                                        $asciiEncoding = 
(($optionFlags & 0x01) == 
0) ;  
                                                $extendedString = 
( ($optionFlags & 0x04) != 
0);  
                                                // See if string contains formatting information  
                                                $richString = 
( ($optionFlags & 0x08) != 
0);  
                                                        $formattingRuns = 
ord($this->data[$spos]) | 
(ord($this->data[$spos+
1]) << 
8);  
                                                $len = 
($asciiEncoding)? 
$numChars : 
$numChars*
2;  
                                                if ($spos + 
$len < 
$limitpos) {  
                                                        $retstr = 
substr($this->data, $spos, $limitpos - 
$spos);  
                                                        $bytesRead = 
$limitpos - 
$spos;  
                                                        $charsLeft = 
$numChars - 
(($asciiEncoding) ? 
$bytesRead : 
($bytesRead / 
2));  
                                                                $conlength = 
ord($this->data[$spos+
2]) | 
ord($this->data[$spos+
3])<<
8;  
                                                                $limitpos = 
$spos + 
$conlength;  
                                                                  if ($asciiEncoding && 
($option == 
0)) {  
                                                                                $len = 
min($charsLeft, $limitpos - 
$spos); // min($charsLeft, $conlength);  
                                                                  }elseif (!$asciiEncoding && 
($option != 
0)){  
                                                                                $len = 
min($charsLeft * 
2, $limitpos - 
$spos); // min($charsLeft, $conlength);  
                                                                  }elseif (!$asciiEncoding && 
($option == 
0)) {  
                                                                // Bummer - the string starts off as Unicode, but after the  
                                                                // continuation it is in straightforward ASCII encoding  
                                                                                $len = 
min($charsLeft, $limitpos - 
$spos); // min($charsLeft, $conlength);  
                                                                        for ($j = 
0; $j < 
$len; $j++
) {  
                                                                 $retstr .= 
$this->data[$spos + 
$j].
chr(0);  
                                                                    for ($j = 
0; $j < 
strlen($retstr); $j++
) {  
                                                                      $newstr = 
$retstr[$j].
chr(0);  
                                                                                $len = 
min($charsLeft * 
2, $limitpos - 
$spos); // min($charsLeft, $conlength);  
                                                $retstr = 
($asciiEncoding) ? 
$retstr : 
$this->_encodeUTF16($retstr);  
//                                              echo "Str $i = $retstr\n";  
                                                  $spos += 
4 * 
$formattingRuns;  
                                                // For extended strings, skip over the extended string data  
                                                  $spos += 
$extendedRunLength;  
                                                        //if ($retstr == 'Derby'){  
                    /*$continueRecords = array();  
                    while ($this->getNextCode() == Type_CONTINUE) {  
                        $continueRecords[] = &$this->nextRecord();  
                    $this->shareStrings = new SSTRecord($r, $continueRecords);  
                    //print_r($this->shareStrings->strings);  
                     // echo 'SST read: '.($time_end-$time_start)."\n";  
                        $indexCode = 
ord($this->data[$pos+
4]) | 
ord($this->data[$pos+
5]) << 
8;  
                            if (ord($this->data[$pos+
8]) == 
0){  
                                $formatString = 
substr($this->data, $pos+
9, $numchars);  
                                $formatString = 
substr($this->data, $pos+
9, $numchars*
2);  
                            $numchars = 
ord($this->data[$pos+
6]);  
                            $formatString = 
substr($this->data, $pos+
7, $numchars*
2);  
                        //global $dateFormats, $numberFormats;  
                        $indexCode = 
ord($this->data[$pos+
6]) | 
ord($this->data[$pos+
7]) << 
8;  
                        //echo "\nType.XF ".count($this->formatRecords['xfrecords'])." $indexCode ";  
                            //echo "isdate ".$dateFormats[$indexCode];  
                        //echo "isnumber ".$this->numberFormats[$indexCode];  
                                //echo "\ndate-time=$formatstr=\n";  
                                if (preg_match("/[^hmsday\/\-:\s]/i", $formatstr) == 
0) { // found day and time format  
                                    //echo "\ndate-time $formatstr \n";  
                    //echo "Type.NINETEENFOUR\n";  
                    $this->nineteenFour = 
(ord($this->data[$pos+
4]) == 
1);  
                    //echo "Type.BOUNDSHEET\n";  
                        $rec_typeFlag = 
ord($this->data[$pos+
8]);  
                        $rec_visibilityFlag = 
ord($this->data[$pos+
9]);  
                        $rec_length = 
ord($this->data[$pos+
10]);  
                            $chartype =  
ord($this->data[$pos+
11]);  
                                $rec_name    = 
substr($this->data, $pos+
12, $rec_length);  
                                $rec_name    = 
substr($this->data, $pos+
11, $rec_length);  
            //echo "Code = ".base_convert($r['code'],10,16)."\n";  
            //$r = &$this->nextRecord();  
            //echo "1 Code = ".base_convert($r['code'],10,16)."\n";  
        $version = 
ord($this->data[$spos + 
4]) | 
ord($this->data[$spos + 
5])<<
8;  
        $substreamType = 
ord($this->data[$spos + 
6]) | 
ord($this->data[$spos + 
7])<<
8;  
        //echo "Start parse code=".base_convert($code,10,16)." version=".base_convert($version,10,16)." substreamType=".base_convert($substreamType,10,16).""."\n";  
        //var_dump($this->formatRecords);  
    //echo "code $code $length";  
            //echo "mem= ".memory_get_usage()."\n";  
//            $r = &$this->file->nextRecord();  
            $lowcode = 
ord($this->data[$spos]);  
            $code = 
$lowcode | 
ord($this->data[$spos+
1])<<
8;  
            //echo "Code=".base_convert($code,10,16)." $code\n";  
            $this->multiplier = 
1; // need for format with %  
                    //echo 'Type_DIMENSION ';  
                    if (!isset
($this->numRows)) {  
                    //echo 'numRows '.$this->numRows.' '.$this->numCols."\n";  
                    for ($i = 
0; $i < 
$cellRanges; $i++
) {  
                        $fr =  
ord($this->data[$spos + 
8*
$i + 
2]) | 
ord($this->data[$spos + 
8*
$i + 
3])<<
8;  
                        $lr =  
ord($this->data[$spos + 
8*
$i + 
4]) | 
ord($this->data[$spos + 
8*
$i + 
5])<<
8;  
                        $fc =  
ord($this->data[$spos + 
8*
$i + 
6]) | 
ord($this->data[$spos + 
8*
$i + 
7])<<
8;  
                        $lc =  
ord($this->data[$spos + 
8*
$i + 
8]) | 
ord($this->data[$spos + 
8*
$i + 
9])<<
8;  
                        //$this->sheets[$this->sn]['mergedCells'][] = array($fr + 1, $fc + 1, $lr + 1, $lc + 1);  
                            $this->sheets[$this->sn]['cellsInfo'][$fr+
1][$fc+
1]['rowspan'] = 
$lr - 
$fr + 
1;  
                            $this->sheets[$this->sn]['cellsInfo'][$fr+
1][$fc+
1]['colspan'] = 
$lc - 
$fc + 
1;  
                    //echo "Merged Cells $cellRanges $lr $fr $lc $fc\n";  
                    //echo 'Spreadsheet_Excel_Reader_Type_RK'."\n";  
                        list
($string, $raw) = 
$this->createDate($numValue); 
                        $string = 
sprintf($this->curformat, $numValue * 
$this->multiplier);  
                        //$this->addcell(RKRecord($r));  
                    $this->addcell($row, $column, $string, $raw);  
                    //echo "Type_RK $row $column $string $raw {$this->curformat}\n";  
                        $this->addcell($row, $column, $this->sst[$index]);  
                        //echo "LabelSST $row $column $string\n";  
                    $colLast    = 
ord($this->data[$spos + 
$length - 
2]) | 
ord($this->data[$spos + 
$length - 
1])<<
8;  
                    $columns    = 
$colLast - 
$colFirst + 
1;  
                    for ($i = 
0; $i < 
$columns; $i++
) {  
                        if ($this->isDate($tmppos-
4)) {  
                            list
($string, $raw) = 
$this->createDate($numValue); 
                            $string = 
sprintf($this->curformat, $numValue * 
$this->multiplier);  
                      //$rec['rknumbers'][$i]['xfindex'] = ord($rec['data'][$pos]) | ord($rec['data'][$pos+1]) << 8;  
                      $this->addcell($row, $colFirst + 
$i, $string, $raw);  
                      //echo "MULRK $row ".($colFirst + $i)." $string\n";  
                    // Get the individual cell records from the multiple record  
                    $tmp = 
unpack("d", substr($this->data, $spos + 
6, 8)); // It machine machine dependent  
                        list
($string, $raw) = 
$this->createDate($tmp['']); 
                     //   $this->addcell(DateRecord($r, 1));  
                        $string = 
sprintf($this->curformat, $raw * 
$this->multiplier);  
                     //   $this->addcell(NumberRecord($r));  
                    $this->addcell($row, $column, $string, $raw);  
                    //echo "Number $row $column $string\n";  
                    if ((ord($this->data[$spos+
6])==
0) && 
(ord($this->data[$spos+
12])==
255) && 
(ord($this->data[$spos+
13])==
255)) {  
                        //String formula. Result follows in a STRING record  
                        //echo "FORMULA $row $column Formula with a string<br>\n";  
                    } elseif ((ord($this->data[$spos+
6])==
1) && 
(ord($this->data[$spos+
12])==
255) && 
(ord($this->data[$spos+
13])==
255)) {  
                        //Boolean formula. Result is in +2; 0=false,1=true  
                    } elseif ((ord($this->data[$spos+
6])==
2) && 
(ord($this->data[$spos+
12])==
255) && 
(ord($this->data[$spos+
13])==
255)) {  
                        //Error formula. Error code is in +2;  
                    } elseif ((ord($this->data[$spos+
6])==
3) && 
(ord($this->data[$spos+
12])==
255) && 
(ord($this->data[$spos+
13])==
255)) {  
                        //Formula result is a null string.  
                        // result is a number, so first 14 bytes are just like a _NUMBER record  
                        $tmp = 
unpack("d", substr($this->data, $spos + 
6, 8)); // It machine machine dependent  
                            list
($string, $raw) = 
$this->createDate($tmp['']); 
                         //   $this->addcell(DateRecord($r, 1));  
                            $string = 
sprintf($this->curformat, $tmp[''] * 
$this->multiplier);  
                         //   $this->addcell(NumberRecord($r));  
                        $this->addcell($row, $column, $string, $raw);  
                        //echo "Number $row $column $string\n";  
                    $string = 
ord($this->data[$spos+
6]);  
                    $this->addcell($row, $column, $string);  
                    //echo 'Type_BOOLERR '."\n";  
                   // $this->addcell(LabelRecord($r));  
                    //echo ' unknown :'.base_convert($r['code'],10,16)."\n";  
        if (!isset
($this->sheets[$this->sn]['numRows']))  
             $this->sheets[$this->sn]['numRows'] = 
$this->sheets[$this->sn]['maxrow'];  
        if (!isset
($this->sheets[$this->sn]['numCols']))  
             $this->sheets[$this->sn]['numCols'] = 
$this->sheets[$this->sn]['maxcol'];  
        //$xfindex = GetInt2d(, 4);  
        $xfindex = 
ord($this->data[$spos+
4]) | 
ord($this->data[$spos+
5]) << 
8;  
        //echo 'check is date '.$xfindex.' '.$this->formatRecords['xfrecords'][$xfindex]['type']."\n";  
        //var_dump($this->formatRecords['xfrecords'][$xfindex]);  
        if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 
'date') {  
            $this->curformat = 
$this->formatRecords['xfrecords'][$xfindex]['format'];  
            if ($this->formatRecords['xfrecords'][$xfindex]['type'] == 
'number') {  
                $this->curformat = 
$this->formatRecords['xfrecords'][$xfindex]['format'];  
                $this->rectype = 
'number';  
                if (($xfindex == 
0x9) || 
($xfindex == 
0xa)){  
                $this->rectype = 
'unknown';  
            $string = 
date ($this->curformat, $utcValue);  
            $hours = 
floor($numValue * 
24);  
            $mins = 
floor($numValue * 
24 * 
60) - 
$hours * 
60;  
            $string = 
date ($this->curformat, mktime($hours, $mins, $secs));  
        return array($string, $raw);  
        //for ($i=0; $i<8; $i++) { echo ord($this->data[$i+$spos+6]) . " "; } echo "<br>";  
        $sign = 
($rknumhigh & 0x80000000) >> 
31;  
        $exp =  
($rknumhigh & 0x7ff00000) >> 
20;  
        $mantissa = 
(0x100000 | 
($rknumhigh & 0x000fffff));  
        $mantissalow1 = 
($rknumlow & 0x80000000) >> 
31;  
        $mantissalow2 = 
($rknumlow & 0x7fffffff);  
        $value = 
$mantissa / 
pow( 2 , (20- 
($exp - 
1023)));  
        if ($mantissalow1 != 
0) $value += 
1 / 
pow (2 , (21 - 
($exp - 
1023)));  
        $value += 
$mantissalow2 / 
pow (2 , (52 - 
($exp - 
1023)));  
        //echo "Sign = $sign, Exp = $exp, mantissahighx = $mantissa, mantissalow1 = $mantissalow1, mantissalow2 = $mantissalow2<br>\n";  
        if ($sign) {$value = -
1 * 
$value;}  
    function addcell($row, $col, $string, $raw = 
''){  
        //echo "ADD cel $row-$col $string\n";  
        $this->sheets[$this->sn]['maxrow'] = 
max($this->sheets[$this->sn]['maxrow'], $row+
1);  
        $this->sheets[$this->sn]['maxcol'] = 
max($this->sheets[$this->sn]['maxcol'], $col+
1);  
        $this->sheets[$this->sn]['cells'][$row+
1][$col+
1] = 
$string;  
            $this->sheets[$this->sn]['cellsInfo'][$row+
1][$col+
1]['raw'] = 
$raw;  
        if (isset
($this->rectype))  
            $this->sheets[$this->sn]['cellsInfo'][$row+
1][$col+
1]['type'] = 
$this->rectype;  
        if (($rknum & 0x02) != 
0) {  
// first comment out the previously existing 7 lines of code here  
//                $tmp = unpack("d", pack("VV", 0, ($rknum & 0xfffffffc)));  
//                if (array_key_exists(1, $tmp)) {  
// I got my info on IEEE754 encoding from   
// http://research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html  
// The RK format calls for using only the most significant 30 bits of the  
// 64 bit floating point value. The other 34 bits are assumed to be 0  
// So, we use the upper 30 bits of $rknum as follows...  
         $sign = 
($rknum & 0x80000000) >> 
31;  
        $exp = 
($rknum & 0x7ff00000) >> 
20;  
        $mantissa = 
(0x100000 | 
($rknum & 0x000ffffc));  
        $value = 
$mantissa / 
pow( 2 , (20- 
($exp - 
1023)));  
        if ($sign) {$value = -
1 * 
$value;}  
        if (($rknum & 0x01) != 
0) {  
        return ord($data[$pos]) | 
(ord($data[$pos+
1]) << 
8) | 
(ord($data[$pos+
2]) << 
16) | 
(ord($data[$pos+
3]) << 
24);  
 
 
	
		Documentation generated on Thu, 08 Jan 2009 17:48:27 +0100 by phpDocumentor 1.4.0a2