[ Index ]

PHP Cross Reference of phpwcms V1.4.3 _r380 (23.11.09)

title

Body

[close]

/include/inc_ext/PEAR/Spreadsheet/Excel/Writer/ -> BIFFwriter.php (source)

   1  <?php
   2  /*
   3  *  Module written/ported by Xavier Noguer <xnoguer@php.net>
   4  *
   5  *  The majority of this is _NOT_ my code.  I simply ported it from the
   6  *  PERL Spreadsheet::WriteExcel module.
   7  *
   8  *  The author of the Spreadsheet::WriteExcel module is John McNamara
   9  *  <jmcnamara@cpan.org>
  10  *
  11  *  I _DO_ maintain this code, and John McNamara has nothing to do with the
  12  *  porting of this code to PHP.  Any questions directly related to this
  13  *  class library should be directed to me.
  14  *
  15  *  License Information:
  16  *
  17  *    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
  18  *    Copyright (c) 2002-2003 Xavier Noguer xnoguer@php.net
  19  *
  20  *    This library is free software; you can redistribute it and/or
  21  *    modify it under the terms of the GNU Lesser General Public
  22  *    License as published by the Free Software Foundation; either
  23  *    version 2.1 of the License, or (at your option) any later version.
  24  *
  25  *    This library is distributed in the hope that it will be useful,
  26  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  27  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  28  *    Lesser General Public License for more details.
  29  *
  30  *    You should have received a copy of the GNU Lesser General Public
  31  *    License along with this library; if not, write to the Free Software
  32  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  33  */
  34  
  35  require_once 'PEAR.php';
  36  
  37  /**
  38  * Class for writing Excel BIFF records.
  39  *
  40  * From "MICROSOFT EXCEL BINARY FILE FORMAT" by Mark O'Brien (Microsoft Corporation):
  41  *
  42  * BIFF (BInary File Format) is the file format in which Excel documents are
  43  * saved on disk.  A BIFF file is a complete description of an Excel document.
  44  * BIFF files consist of sequences of variable-length records. There are many
  45  * different types of BIFF records.  For example, one record type describes a
  46  * formula entered into a cell; one describes the size and location of a
  47  * window into a document; another describes a picture format.
  48  *
  49  * @author   Xavier Noguer <xnoguer@php.net>
  50  * @category FileFormats
  51  * @package  Spreadsheet_Excel_Writer
  52  */
  53  
  54  class Spreadsheet_Excel_Writer_BIFFwriter extends PEAR
  55  {
  56      /**
  57      * The BIFF/Excel version (5).
  58      * @var integer
  59      */
  60      var $_BIFF_version = 0x0500;
  61  
  62      /**
  63      * The byte order of this architecture. 0 => little endian, 1 => big endian
  64      * @var integer
  65      */
  66      var $_byte_order;
  67  
  68      /**
  69      * The string containing the data of the BIFF stream
  70      * @var string
  71      */
  72      var $_data;
  73  
  74      /**
  75      * The size of the data in bytes. Should be the same as strlen($this->_data)
  76      * @var integer
  77      */
  78      var $_datasize;
  79  
  80      /**
  81      * The maximun length for a BIFF record. See _addContinue()
  82      * @var integer
  83      * @see _addContinue()
  84      */
  85      var $_limit;
  86  
  87      /**
  88      * Constructor
  89      *
  90      * @access public
  91      */
  92      function Spreadsheet_Excel_Writer_BIFFwriter()
  93      {
  94          $this->_byte_order = '';
  95          $this->_data       = '';
  96          $this->_datasize   = 0;
  97          $this->_limit      = 2080;
  98          // Set the byte order
  99          $this->_setByteOrder();
 100      }
 101  
 102      /**
 103      * Determine the byte order and store it as class data to avoid
 104      * recalculating it for each call to new().
 105      *
 106      * @access private
 107      */
 108      function _setByteOrder()
 109      {
 110          // Check if "pack" gives the required IEEE 64bit float
 111          $teststr = pack("d", 1.2345);
 112          $number  = pack("C8", 0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F);
 113          if ($number == $teststr) {
 114              $byte_order = 0;    // Little Endian
 115          } elseif ($number == strrev($teststr)){
 116              $byte_order = 1;    // Big Endian
 117          } else {
 118              // Give up. I'll fix this in a later version.
 119              return $this->raiseError("Required floating point format ".
 120                                       "not supported on this platform.");
 121          }
 122          $this->_byte_order = $byte_order;
 123      }
 124  
 125      /**
 126      * General storage function
 127      *
 128      * @param string $data binary data to prepend
 129      * @access private
 130      */
 131      function _prepend($data)
 132      {
 133          if (strlen($data) > $this->_limit) {
 134              $data = $this->_addContinue($data);
 135          }
 136          $this->_data      = $data.$this->_data;
 137          $this->_datasize += strlen($data);
 138      }
 139  
 140      /**
 141      * General storage function
 142      *
 143      * @param string $data binary data to append
 144      * @access private
 145      */
 146      function _append($data)
 147      {
 148          if (strlen($data) > $this->_limit) {
 149              $data = $this->_addContinue($data);
 150          }
 151          $this->_data      = $this->_data.$data;
 152          $this->_datasize += strlen($data);
 153      }
 154  
 155      /**
 156      * Writes Excel BOF record to indicate the beginning of a stream or
 157      * sub-stream in the BIFF file.
 158      *
 159      * @param  integer $type Type of BIFF file to write: 0x0005 Workbook,
 160      *                       0x0010 Worksheet.
 161      * @access private
 162      */
 163      function _storeBof($type)
 164      {
 165          $record  = 0x0809;        // Record identifier
 166  
 167          // According to the SDK $build and $year should be set to zero.
 168          // However, this throws a warning in Excel 5. So, use magic numbers.
 169          if ($this->_BIFF_version == 0x0500) {
 170              $length  = 0x0008;
 171              $unknown = '';
 172              $build   = 0x096C;
 173              $year    = 0x07C9;
 174          } elseif ($this->_BIFF_version == 0x0600) {
 175              $length  = 0x0010;
 176              $unknown = pack("VV", 0x00000041, 0x00000006); //unknown last 8 bytes for BIFF8
 177              $build   = 0x0DBB;
 178              $year    = 0x07CC;
 179          }
 180          $version = $this->_BIFF_version;
 181  
 182          $header  = pack("vv",   $record, $length);
 183          $data    = pack("vvvv", $version, $type, $build, $year);
 184          $this->_prepend($header . $data . $unknown);
 185      }
 186  
 187      /**
 188      * Writes Excel EOF record to indicate the end of a BIFF stream.
 189      *
 190      * @access private
 191      */
 192      function _storeEof()
 193      {
 194          $record    = 0x000A;   // Record identifier
 195          $length    = 0x0000;   // Number of bytes to follow
 196          $header    = pack("vv", $record, $length);
 197          $this->_append($header);
 198      }
 199  
 200      /**
 201      * Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In
 202      * Excel 97 the limit is 8228 bytes. Records that are longer than these limits
 203      * must be split up into CONTINUE blocks.
 204      *
 205      * This function takes a long BIFF record and inserts CONTINUE records as
 206      * necessary.
 207      *
 208      * @param  string  $data The original binary data to be written
 209      * @return string        A very convenient string of continue blocks
 210      * @access private
 211      */
 212      function _addContinue($data)
 213      {
 214          $limit  = $this->_limit;
 215          $record = 0x003C;         // Record identifier
 216  
 217          // The first 2080/8224 bytes remain intact. However, we have to change
 218          // the length field of the record.
 219          $tmp = substr($data, 0, 2).pack("v", $limit-4).substr($data, 4, $limit - 4);
 220  
 221          $header = pack("vv", $record, $limit);  // Headers for continue records
 222  
 223          // Retrieve chunks of 2080/8224 bytes +4 for the header.
 224          $data_length = strlen($data);
 225          for ($i = $limit; $i <  ($data_length - $limit); $i += $limit) {
 226              $tmp .= $header;
 227              $tmp .= substr($data, $i, $limit);
 228          }
 229  
 230          // Retrieve the last chunk of data
 231          $header  = pack("vv", $record, strlen($data) - $i);
 232          $tmp    .= $header;
 233          $tmp    .= substr($data, $i, strlen($data) - $i);
 234  
 235          return $tmp;
 236      }
 237  }
 238  ?>


Generated: Wed Dec 30 05:55:15 2009 Cross-referenced by PHPXref 0.7