"Fossies" - the Fresh Open Source Software Archive

Member "php_writeexcel-0.3.0/class.writeexcel_olewriter.inc.php" (1 Nov 2005, 11085 Bytes) of package /linux/www/old/php_writeexcel-0.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 <?php
    2 
    3 /*
    4  * Copyleft 2002 Johann Hanne
    5  *
    6  * This is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Lesser General Public
    8  * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
   10  *
   11  * This software is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14  * Lesser General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU Lesser General Public
   17  * License along with this software; if not, write to the
   18  * Free Software Foundation, Inc., 59 Temple Place,
   19  * Suite 330, Boston, MA  02111-1307 USA
   20  */
   21 
   22 /*
   23  * This is the Spreadsheet::WriteExcel Perl package ported to PHP
   24  * Spreadsheet::WriteExcel was written by John McNamara, jmcnamara@cpan.org
   25  */
   26 
   27 class writeexcel_olewriter {
   28     var $_OLEfilename;
   29     var $_OLEtmpfilename; /* ABR */
   30     var $_filehandle;
   31     var $_fileclosed;
   32     var $_internal_fh;
   33     var $_biff_only;
   34     var $_size_allowed;
   35     var $_biffsize;
   36     var $_booksize;
   37     var $_big_blocks;
   38     var $_list_blocks;
   39     var $_root_start;
   40     var $_block_count;
   41 
   42     /*
   43      * Constructor
   44      */
   45     function writeexcel_olewriter($filename) {
   46 
   47         $this->_OLEfilename  = $filename;
   48         $this->_filehandle   = false;
   49         $this->_fileclosed   = 0;
   50         $this->_internal_fh  = 0;
   51         $this->_biff_only    = 0;
   52         $this->_size_allowed = 0;
   53         $this->_biffsize     = 0;
   54         $this->_booksize     = 0;
   55         $this->_big_blocks   = 0;
   56         $this->_list_blocks  = 0;
   57         $this->_root_start   = 0;
   58         $this->_block_count  = 4;
   59 
   60         $this->_initialize();
   61     }
   62 
   63     /*
   64      * Check for a valid filename and store the filehandle.
   65      */
   66     function _initialize() {
   67         $OLEfile = $this->_OLEfilename;
   68 
   69         /* Check for a filename. Workbook.pm will catch this first. */
   70         if ($OLEfile == '') {
   71             trigger_error("Filename required", E_USER_ERROR);
   72         }
   73 
   74         /*
   75          * If the filename is a resource it is assumed that it is a valid
   76          * filehandle, if not we create a filehandle.
   77          */
   78         if (is_resource($OLEfile)) {
   79             $fh = $OLEfile;
   80         } else {
   81             // Create a new file, open for writing
   82             $fh = fopen($OLEfile, "wb");
   83             // The workbook class also checks this but something may have
   84             // happened since then.
   85             if (!$fh) {
   86                 trigger_error("Can't open $OLEfile. It may be in use or ".
   87                               "protected", E_USER_ERROR);
   88             }
   89 
   90             $this->_internal_fh = 1;
   91         }
   92 
   93         // Store filehandle
   94         $this->_filehandle = $fh;
   95     }
   96 
   97     /*
   98      * Set the size of the data to be written to the OLE stream
   99      *
  100      * $big_blocks = (109 depot block x (128 -1 marker word)
  101      *               - (1 x end words)) = 13842
  102      * $maxsize    = $big_blocks * 512 bytes = 7087104
  103      */
  104     function set_size($size) {
  105         $maxsize = 7087104;
  106 
  107         if ($size > $maxsize) {
  108             trigger_error("Maximum file size, $maxsize, exceeded. To create ".
  109                           "files bigger than this limit please use the ".
  110                           "workbookbig class.", E_USER_ERROR);
  111             return ($this->_size_allowed = 0);
  112         }
  113 
  114         $this->_biffsize = $size;
  115 
  116         // Set the min file size to 4k to avoid having to use small blocks
  117         if ($size > 4096) {
  118             $this->_booksize = $size;
  119         } else {
  120             $this->_booksize = 4096;
  121         }
  122 
  123         return ($this->_size_allowed = 1);
  124     }
  125 
  126     /*
  127      * Calculate various sizes needed for the OLE stream
  128      */
  129     function _calculate_sizes() {
  130         $datasize = $this->_booksize;
  131 
  132         if ($datasize % 512 == 0) {
  133             $this->_big_blocks = $datasize/512;
  134         } else {
  135             $this->_big_blocks = floor($datasize/512)+1;
  136         }
  137         // There are 127 list blocks and 1 marker blocks for each big block
  138         // depot + 1 end of chain block
  139         $this->_list_blocks = floor(($this->_big_blocks)/127)+1;
  140         $this->_root_start  = $this->_big_blocks;
  141 
  142         //print $this->_biffsize.    "\n";
  143         //print $this->_big_blocks.  "\n";
  144         //print $this->_list_blocks. "\n";
  145     }
  146 
  147     /*
  148      * Write root entry, big block list and close the filehandle.
  149      * This method must be called so that the file contents are
  150      * actually written.
  151      */
  152     function close() {
  153 
  154         if (!$this->_size_allowed) {
  155             return;
  156         }
  157 
  158         if (!$this->_biff_only) {
  159             $this->_write_padding();
  160             $this->_write_property_storage();
  161             $this->_write_big_block_depot();
  162         }
  163 
  164         // Close the filehandle if it was created internally.
  165         if ($this->_internal_fh) {
  166             fclose($this->_filehandle);
  167         }
  168 /* ABR */
  169         if ($this->_OLEtmpfilename != '') {
  170             $fh = fopen($this->_OLEtmpfilename, "rb");
  171             if ($fh == false) {
  172                 trigger_error("Can't read temporary file.", E_USER_ERROR);
  173             }
  174             fpassthru($fh);
  175             fclose($fh);
  176             unlink($this->_OLEtmpfilename);
  177         };
  178 
  179         $this->_fileclosed = 1;
  180     }
  181 
  182     /*
  183      * Write BIFF data to OLE file.
  184      */
  185     function write($data) {
  186         fputs($this->_filehandle, $data);
  187     }
  188 
  189     /*
  190      * Write OLE header block.
  191      */
  192     function write_header() {
  193         if ($this->_biff_only) {
  194             return;
  195         }
  196 
  197         $this->_calculate_sizes();
  198 
  199         $root_start      = $this->_root_start;
  200         $num_lists       = $this->_list_blocks;
  201 
  202         $id              = pack("C8", 0xD0, 0xCF, 0x11, 0xE0,
  203                                       0xA1, 0xB1, 0x1A, 0xE1);
  204         $unknown1        = pack("VVVV", 0x00, 0x00, 0x00, 0x00);
  205         $unknown2        = pack("vv",   0x3E, 0x03);
  206         $unknown3        = pack("v",    -2);
  207         $unknown4        = pack("v",    0x09);
  208         $unknown5        = pack("VVV",  0x06, 0x00, 0x00);
  209         $num_bbd_blocks  = pack("V",    $num_lists);
  210         $root_startblock = pack("V",    $root_start);
  211         $unknown6        = pack("VV",   0x00, 0x1000);
  212         $sbd_startblock  = pack("V",    -2);
  213         $unknown7        = pack("VVV",  0x00, -2 ,0x00);
  214         $unused          = pack("V",    -1);
  215 
  216         fputs($this->_filehandle, $id);
  217         fputs($this->_filehandle, $unknown1);
  218         fputs($this->_filehandle, $unknown2);
  219         fputs($this->_filehandle, $unknown3);
  220         fputs($this->_filehandle, $unknown4);
  221         fputs($this->_filehandle, $unknown5);
  222         fputs($this->_filehandle, $num_bbd_blocks);
  223         fputs($this->_filehandle, $root_startblock);
  224         fputs($this->_filehandle, $unknown6);
  225         fputs($this->_filehandle, $sbd_startblock);
  226         fputs($this->_filehandle, $unknown7);
  227 
  228         for ($c=1;$c<=$num_lists;$c++) {
  229             $root_start++;
  230             fputs($this->_filehandle, pack("V", $root_start));
  231         }
  232 
  233         for ($c=$num_lists;$c<=108;$c++) {
  234             fputs($this->_filehandle, $unused);
  235         }
  236     }
  237 
  238     /*
  239      * Write big block depot.
  240      */
  241     function _write_big_block_depot() {
  242         $num_blocks   = $this->_big_blocks;
  243         $num_lists    = $this->_list_blocks;
  244         $total_blocks = $num_lists * 128;
  245         $used_blocks  = $num_blocks + $num_lists + 2;
  246 
  247         $marker       = pack("V", -3);
  248         $end_of_chain = pack("V", -2);
  249         $unused       = pack("V", -1);
  250 
  251         for ($i=1;$i<=($num_blocks-1);$i++) {
  252             fputs($this->_filehandle, pack("V", $i));
  253         }
  254 
  255         fputs($this->_filehandle, $end_of_chain);
  256         fputs($this->_filehandle, $end_of_chain);
  257 
  258         for ($c=1;$c<=$num_lists;$c++) {
  259             fputs($this->_filehandle, $marker);
  260         }
  261 
  262         for ($c=$used_blocks;$c<=$total_blocks;$c++) {
  263             fputs($this->_filehandle, $unused);
  264         }
  265     }
  266 
  267     /*
  268      * Write property storage. TODO: add summary sheets
  269      */
  270     function _write_property_storage() {
  271         $rootsize = -2;
  272         $booksize = $this->_booksize;
  273 
  274         //                name          type  dir start  size
  275         $this->_write_pps('Root Entry', 0x05,   1,   -2, 0x00);
  276         $this->_write_pps('Book',       0x02,  -1, 0x00, $booksize);
  277         $this->_write_pps('',           0x00,  -1, 0x00, 0x0000);
  278         $this->_write_pps('',           0x00,  -1, 0x00, 0x0000);
  279     }
  280 
  281     /*
  282      * Write property sheet in property storage
  283      */
  284     function _write_pps($name, $type, $dir, $start, $size) {
  285         $names           = array();
  286         $length          = 0;
  287 
  288         if ($name != '') {
  289             $name   = $name . "\0";
  290             // Simulate a Unicode string
  291             $chars=preg_split("''", $name, -1, PREG_SPLIT_NO_EMPTY);
  292             foreach ($chars as $char) {
  293                 array_push($names, ord($char));
  294             }
  295             $length = strlen($name) * 2;
  296         }
  297 
  298         $rawname         = call_user_func_array('pack', array_merge(array("v*"), $names));
  299         $zero            = pack("C",  0);
  300 
  301         $pps_sizeofname  = pack("v",  $length);   //0x40
  302         $pps_type        = pack("v",  $type);     //0x42
  303         $pps_prev        = pack("V",  -1);        //0x44
  304         $pps_next        = pack("V",  -1);        //0x48
  305         $pps_dir         = pack("V",  $dir);      //0x4c
  306 
  307         $unknown1        = pack("V",  0);
  308 
  309         $pps_ts1s        = pack("V",  0);         //0x64
  310         $pps_ts1d        = pack("V",  0);         //0x68
  311         $pps_ts2s        = pack("V",  0);         //0x6c
  312         $pps_ts2d        = pack("V",  0);         //0x70
  313         $pps_sb          = pack("V",  $start);    //0x74
  314         $pps_size        = pack("V",  $size);     //0x78
  315 
  316         fputs($this->_filehandle, $rawname);
  317         fputs($this->_filehandle, str_repeat($zero, (64-$length)));
  318         fputs($this->_filehandle, $pps_sizeofname);
  319         fputs($this->_filehandle, $pps_type);
  320         fputs($this->_filehandle, $pps_prev);
  321         fputs($this->_filehandle, $pps_next);
  322         fputs($this->_filehandle, $pps_dir);
  323         fputs($this->_filehandle, str_repeat($unknown1, 5));
  324         fputs($this->_filehandle, $pps_ts1s);
  325         fputs($this->_filehandle, $pps_ts1d);
  326         fputs($this->_filehandle, $pps_ts2d);
  327         fputs($this->_filehandle, $pps_ts2d);
  328         fputs($this->_filehandle, $pps_sb);
  329         fputs($this->_filehandle, $pps_size);
  330         fputs($this->_filehandle, $unknown1);
  331     }
  332 
  333     /*
  334      * Pad the end of the file
  335      */
  336     function _write_padding() {
  337         $biffsize = $this->_biffsize;
  338 
  339         if ($biffsize < 4096) {
  340             $min_size = 4096;
  341         } else {
  342             $min_size = 512;
  343         }
  344 
  345         if ($biffsize % $min_size != 0) {
  346             $padding  = $min_size - ($biffsize % $min_size);
  347             fputs($this->_filehandle, str_repeat("\0", $padding));
  348         }
  349     }
  350 
  351 }
  352 
  353 ?>