PHPExcel_Writer_Excel5
[ class tree: PHPExcel_Writer_Excel5 ] [ index: PHPExcel_Writer_Excel5 ] [ all elements ]

Source for file Worksheet.php

Documentation is available at Worksheet.php

  1. <?php
  2. /**
  3.  * PHPExcel
  4.  *
  5.  * Copyright (c) 2006 - 2010 PHPExcel
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with this library; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  20.  *
  21.  * @category   PHPExcel
  22.  * @package    PHPExcel_Writer_Excel5
  23.  * @copyright  Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
  24.  * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
  25.  * @version    1.7.3c, 2010-06-01
  26.  */
  27.  
  28. // Original file header of PEAR::Spreadsheet_Excel_Writer_Worksheet (used as the base for this class):
  29. // -----------------------------------------------------------------------------------------
  30. // /*
  31. // *  Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
  32. // *
  33. // *  The majority of this is _NOT_ my code.  I simply ported it from the
  34. // *  PERL Spreadsheet::WriteExcel module.
  35. // *
  36. // *  The author of the Spreadsheet::WriteExcel module is John McNamara
  37. // *  <jmcnamara@cpan.org>
  38. // *
  39. // *  I _DO_ maintain this code, and John McNamara has nothing to do with the
  40. // *  porting of this code to PHP.  Any questions directly related to this
  41. // *  class library should be directed to me.
  42. // *
  43. // *  License Information:
  44. // *
  45. // *    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
  46. // *    Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
  47. // *
  48. // *    This library is free software; you can redistribute it and/or
  49. // *    modify it under the terms of the GNU Lesser General Public
  50. // *    License as published by the Free Software Foundation; either
  51. // *    version 2.1 of the License, or (at your option) any later version.
  52. // *
  53. // *    This library is distributed in the hope that it will be useful,
  54. // *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  55. // *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  56. // *    Lesser General Public License for more details.
  57. // *
  58. // *    You should have received a copy of the GNU Lesser General Public
  59. // *    License along with this library; if not, write to the Free Software
  60. // *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  61. // */
  62.  
  63.  
  64. /**
  65.  * PHPExcel_Writer_Excel5_Worksheet
  66.  *
  67.  * @category   PHPExcel
  68.  * @package    PHPExcel_Writer_Excel5
  69.  * @copyright  Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
  70.  */
  71. {
  72.     /**
  73.      * Formula parser
  74.      *
  75.      * @var PHPExcel_Writer_Excel5_Parser 
  76.      */
  77.     private $_parser;
  78.  
  79.     /**
  80.      * Maximum number of characters for a string (LABEL record in BIFF5)
  81.      * @var integer 
  82.      */
  83.     public $_xls_strmax;
  84.  
  85.     /**
  86.      * Array containing format information for columns
  87.      * @var array 
  88.      */
  89.     public $_colinfo;
  90.  
  91.     /**
  92.      * Array containing the selected area for the worksheet
  93.      * @var array 
  94.      */
  95.     public $_selection;
  96.  
  97.     /**
  98.      * The active pane for the worksheet
  99.      * @var integer 
  100.      */
  101.     public $_active_pane;
  102.  
  103.     /**
  104.      * Whether to use outline.
  105.      * @var integer 
  106.      */
  107.     public $_outline_on;
  108.  
  109.     /**
  110.      * Auto outline styles.
  111.      * @var bool 
  112.      */
  113.     public $_outline_style;
  114.  
  115.     /**
  116.      * Whether to have outline summary below.
  117.      * @var bool 
  118.      */
  119.     public $_outline_below;
  120.  
  121.     /**
  122.      * Whether to have outline summary at the right.
  123.      * @var bool 
  124.      */
  125.     public $_outline_right;
  126.  
  127.     /**
  128.      * Reference to the total number of strings in the workbook
  129.      * @var integer 
  130.      */
  131.     public $_str_total;
  132.  
  133.     /**
  134.      * Reference to the number of unique strings in the workbook
  135.      * @var integer 
  136.      */
  137.     public $_str_unique;
  138.  
  139.     /**
  140.      * Reference to the array containing all the unique strings in the workbook
  141.      * @var array 
  142.      */
  143.     public $_str_table;
  144.  
  145.     /**
  146.      * Color cache
  147.      */
  148.     private $_colors;
  149.  
  150.     /**
  151.      * Index of first used row (at least 0)
  152.      * @var int 
  153.      */
  154.     private $_firstRowIndex;
  155.  
  156.     /**
  157.      * Index of last used row. (no used rows means -1)
  158.      * @var int 
  159.      */
  160.     private $_lastRowIndex;
  161.  
  162.     /**
  163.      * Index of first used column (at least 0)
  164.      * @var int 
  165.      */
  166.     private $_firstColumnIndex;
  167.  
  168.     /**
  169.      * Index of last used column (no used columns means -1)
  170.      * @var int 
  171.      */
  172.     private $_lastColumnIndex;
  173.  
  174.     /**
  175.      * Sheet object
  176.      * @var PHPExcel_Worksheet 
  177.      */
  178.     private $_phpSheet;
  179.  
  180.     /**
  181.      * Count cell style Xfs
  182.      *
  183.      * @var int 
  184.      */
  185.     private $_countCellStyleXfs;
  186.  
  187.     /**
  188.      * Constructor
  189.      *
  190.      * @param int  $BIFF_version         BIFF version
  191.      * @param int  $str_total        Total number of strings
  192.      * @param int  $str_unique        Total number of unique strings
  193.      * @param array  $str_table 
  194.      * @param mixed   $parser      The formula parser created for the Workbook
  195.      * @param string   $tempDir      The temporary directory to be used
  196.      * @param PHPExcel_Worksheet $phpSheet 
  197.      */
  198.     public function __construct($BIFF_version,
  199.                                                 &$str_total,
  200.                                                 &$str_unique&$str_table&$colors,
  201.                                                 $parser$preCalculateFormulas$phpSheet)
  202.     {
  203.         // It needs to call its parent's constructor explicitly
  204.         parent::__construct();
  205.  
  206.         $this->_BIFF_version    = $BIFF_version;
  207.         if ($BIFF_version == 0x0600{
  208.             // change BIFFwriter limit for CONTINUE records
  209.             $this->_limit = 8224;
  210.         }
  211.  
  212.  
  213.         $this->_preCalculateFormulas $preCalculateFormulas;
  214.         $this->_str_total        = &$str_total;
  215.         $this->_str_unique        = &$str_unique;
  216.         $this->_str_table        = &$str_table;
  217.         $this->_colors            &$colors;
  218.         $this->_parser            $parser;
  219.  
  220.         $this->_phpSheet $phpSheet;
  221.  
  222.         //$this->ext_sheets        = array();
  223.         //$this->offset            = 0;
  224.         $this->_xls_strmax        = 255;
  225.         $this->_colinfo            = array();
  226.         $this->_selection        = array(0,0,0,0);
  227.         $this->_active_pane        = 3;
  228.  
  229.         $this->_print_headers        0;
  230.  
  231.         $this->_outline_style        = 0;
  232.         $this->_outline_below        = 1;
  233.         $this->_outline_right        = 1;
  234.         $this->_outline_on            = 1;
  235.  
  236.         // calculate values for DIMENSIONS record
  237.         $this->_firstRowIndex    =  0;
  238.         $this->_lastRowIndex     = -1;
  239.         $this->_firstColumnIndex =  0;
  240.         $this->_lastColumnIndex  = -1;
  241.  
  242.         foreach ($this->_phpSheet->getCellCollection(falseas $cellID{
  243.             preg_match('/^(\w+)(\d+)$/U',$cellID,$matches);
  244.             list(,$col,$row$matches;
  245.             $column PHPExcel_Cell::columnIndexFromString($col1;
  246.  
  247.             // Don't break Excel!
  248.             if ($row 65536 or $column 256{
  249.                 break;
  250.             }
  251.  
  252.             $this->_firstRowIndex    min($this->_firstRowIndex$row);
  253.             $this->_lastRowIndex     max($this->_lastRowIndex$row);
  254.             $this->_firstColumnIndex min($this->_firstColumnIndex$column);
  255.             $this->_lastColumnIndex  max($this->_lastColumnIndex$column);
  256.         }
  257.  
  258.         $this->_countCellStyleXfs count($phpSheet->getParent()->getCellStyleXfCollection());
  259.     }
  260.  
  261.     /**
  262.      * Add data to the beginning of the workbook (note the reverse order)
  263.      * and to the end of the workbook.
  264.      *
  265.      * @access public
  266.      * @see PHPExcel_Writer_Excel5_Workbook::storeWorkbook()
  267.      */
  268.     function close()
  269.     {
  270.         $num_sheets $this->_phpSheet->getParent()->getSheetCount();
  271.  
  272.         // Write BOF record
  273.         $this->_storeBof(0x0010);
  274.  
  275.         // Write PRINTHEADERS
  276.         $this->_writePrintHeaders();
  277.  
  278.         // Write PRINTGRIDLINES
  279.         $this->_writePrintGridlines();
  280.  
  281.         // Write GRIDSET
  282.         $this->_writeGridset();
  283.  
  284.         // Calculate column widths
  285.         $this->_phpSheet->calculateColumnWidths();
  286.  
  287.         // Column dimensions
  288.         $columnDimensions $this->_phpSheet->getColumnDimensions();
  289.         for ($i 0$i 256++$i{
  290.             $hidden 0;
  291.             $level 0;
  292.             $xfIndex 15// there are 15 cell style Xfs
  293.  
  294.             if ($this->_phpSheet->getDefaultColumnDimension()->getWidth(>= 0{
  295.                 $width $this->_phpSheet->getDefaultColumnDimension()->getWidth();
  296.             else {
  297.                 $width PHPExcel_Shared_Font::getDefaultColumnWidthByFont($this->_phpSheet->getParent()->getDefaultStyle()->getFont());
  298.             }
  299.  
  300.             $columnLetter PHPExcel_Cell::stringFromColumnIndex($i);
  301.             if (isset($columnDimensions[$columnLetter])) {
  302.                 $columnDimension $columnDimensions[$columnLetter];
  303.                 if ($columnDimension->getWidth(>= 0{
  304.                     $width $columnDimension->getWidth();
  305.                 }
  306.                 $hidden $columnDimension->getVisible(1;
  307.                 $level $columnDimension->getOutlineLevel();
  308.                 $xfIndex $columnDimension->getXfIndex(15// there are 15 cell style Xfs
  309.             }
  310.  
  311.             // Components of _colinfo:
  312.             // $firstcol first column on the range
  313.             // $lastcol  last column on the range
  314.             // $width    width to set
  315.             // $xfIndex  The optional cell style Xf index to apply to the columns
  316.             // $hidden   The optional hidden atribute
  317.             // $level    The optional outline level
  318.             $this->_colinfo[array($i$i$width$xfIndex$hidden$level);
  319.         }
  320.  
  321.         // Write GUTS
  322.         $this->_writeGuts();
  323.  
  324.         // Write DEFAULTROWHEIGHT
  325.         if ($this->_BIFF_version == 0x0600{
  326.             $this->_writeDefaultRowHeight();
  327.         }
  328.  
  329.         // Write WSBOOL
  330.         $this->_writeWsbool();
  331.  
  332.         // Write horizontal and vertical page breaks
  333.         $this->_writeBreaks();
  334.  
  335.         // Write page header
  336.         $this->_writeHeader();
  337.  
  338.         // Write page footer
  339.         $this->_writeFooter();
  340.  
  341.         // Write page horizontal centering
  342.         $this->_writeHcenter();
  343.  
  344.         // Write page vertical centering
  345.         $this->_writeVcenter();
  346.  
  347.         // Write left margin
  348.         $this->_writeMarginLeft();
  349.  
  350.         // Write right margin
  351.         $this->_writeMarginRight();
  352.  
  353.         // Write top margin
  354.         $this->_writeMarginTop();
  355.  
  356.         // Write bottom margin
  357.         $this->_writeMarginBottom();
  358.  
  359.         // Write page setup
  360.         $this->_writeSetup();
  361.  
  362.         // Write sheet protection
  363.         $this->_writeProtect();
  364.  
  365.         // Write SCENPROTECT
  366.         $this->_writeScenProtect();
  367.  
  368.         // Write OBJECTPROTECT
  369.         $this->_writeObjectProtect();
  370.  
  371.         // Write sheet password
  372.         $this->_writePassword();
  373.  
  374.         // Write DEFCOLWIDTH record
  375.         $this->_writeDefcol();
  376.  
  377.         // Write the COLINFO records if they exist
  378.         if (!empty($this->_colinfo)) {
  379.             $colcount count($this->_colinfo);
  380.             for ($i 0$i $colcount++$i{
  381.                 $this->_writeColinfo($this->_colinfo[$i]);
  382.             }
  383.         }
  384.  
  385.         // Write EXTERNCOUNT of external references
  386.         if ($this->_BIFF_version == 0x0500{
  387.             $this->_writeExterncount($num_sheets);
  388.         }
  389.  
  390.         // Write EXTERNSHEET references
  391.         if ($this->_BIFF_version == 0x0500{
  392.             for ($i 0$i $num_sheets++$i{
  393.                 $this->_writeExternsheet($this->_phpSheet->getParent()->getSheet($i)->getTitle());
  394.             }
  395.         }
  396.  
  397.         // Write sheet dimensions
  398.         $this->_writeDimensions();
  399.  
  400.         // Row dimensions
  401.         foreach ($this->_phpSheet->getRowDimensions(as $rowDimension{
  402.             $xfIndex $rowDimension->getXfIndex(15// there are 15 cellXfs
  403.             $this->_writeRow$rowDimension->getRowIndex(1$rowDimension->getRowHeight()$xfIndex($rowDimension->getVisible('0' '1')$rowDimension->getOutlineLevel() );
  404.         }
  405.  
  406.         // Write Cells
  407.         foreach ($this->_phpSheet->getCellCollection(as $cellID{
  408.             $cell $this->_phpSheet->getCell($cellID);
  409.             $row $cell->getRow(1;
  410.             $column PHPExcel_Cell::columnIndexFromString($cell->getColumn()) 1;
  411.  
  412.             // Don't break Excel!
  413.             if ($row 65536 or $column 256{
  414.                 break;
  415.             }
  416.  
  417.             // Write cell value
  418.             $xfIndex $cell->getXfIndex(15// there are 15 cell style Xfs
  419.  
  420.             if ($cell->getValue(instanceof PHPExcel_RichText{
  421.                 $this->_writeString($row$column$cell->getValue()->getPlainText()$xfIndex);
  422.             else {
  423.                 switch ($cell->getDatatype()) {
  424.  
  425.                 case PHPExcel_Cell_DataType::TYPE_STRING:
  426.                     if ($cell->getValue(=== '' or $cell->getValue(=== null{
  427.                         $this->_writeBlank($row$column$xfIndex);
  428.                     else {
  429.                         $this->_writeString($row$column$cell->getValue()$xfIndex);
  430.                     }
  431.                     break;
  432.  
  433.                 case PHPExcel_Cell_DataType::TYPE_FORMULA:
  434.                     $calculatedValue $this->_preCalculateFormulas ?
  435.                         $cell->getCalculatedValue(null;
  436.                     $this->_writeFormula($row$column$cell->getValue()$xfIndex$calculatedValue);
  437.                     break;
  438.  
  439.                 case PHPExcel_Cell_DataType::TYPE_BOOL:
  440.                     $this->_writeBoolErr($row$column$cell->getValue()0$xfIndex);
  441.                     break;
  442.  
  443.                 case PHPExcel_Cell_DataType::TYPE_ERROR:
  444.                     $this->_writeBoolErr($row$column$this->_mapErrorCode($cell->getValue())1$xfIndex);
  445.                     break;
  446.  
  447.                 case PHPExcel_Cell_DataType::TYPE_NUMERIC:
  448.                     $this->_writeNumber($row$column$cell->getValue()$xfIndex);
  449.                     break;
  450.                 }
  451.             }
  452.         }
  453.  
  454.         // Append
  455.         if ($this->_BIFF_version == 0x0600{
  456.             $this->_writeMsoDrawing();
  457.         }
  458.         $this->_writeWindow2();
  459.         $this->_writeZoom();
  460.         if ($this->_phpSheet->getFreezePane()) {
  461.             $this->_writePanes();
  462.         }
  463.         $this->_writeSelection();
  464.         $this->_writeMergedCells();
  465.  
  466.         // Hyperlinks
  467.         if ($this->_BIFF_version == 0x0600{
  468.             foreach ($this->_phpSheet->getHyperLinkCollection(as $coordinate => $hyperlink{
  469.                 list($column$rowPHPExcel_Cell::coordinateFromString($coordinate);
  470.  
  471.                 $url $hyperlink->getUrl();
  472.  
  473.                 if strpos($url'sheet://'!== false {
  474.                     // internal to current workbook
  475.                     $url str_replace('sheet://''internal:'$url);
  476.  
  477.                 else if preg_match('/^(http:|https:|ftp:|mailto:)/'$url) ) {
  478.                     // URL
  479.                     // $url = $url;
  480.  
  481.                 else {
  482.                     // external (local file)
  483.                     $url 'external:' $url;
  484.                 }
  485.  
  486.                 $this->_writeUrl($row 1PHPExcel_Cell::columnIndexFromString($column1$url);
  487.             }
  488.         }
  489.  
  490.         if ($this->_BIFF_version == 0x0600{
  491.             $this->_writeDataValidity();
  492.             $this->_writeSheetLayout();
  493.             $this->_writeSheetProtection();
  494.             $this->_writeRangeProtection();
  495.         }
  496.  
  497.         $this->_storeEof();
  498.     }
  499.  
  500.     /**
  501.      * Write a cell range address in BIFF8
  502.      * always fixed range
  503.      * See section 2.5.14 in OpenOffice.org's Documentation of the Microsoft Excel File Format
  504.      *
  505.      * @param string $range E.g. 'A1' or 'A1:B6'
  506.      * @return string Binary data
  507.      */
  508.     private function _writeBIFF8CellRangeAddressFixed($range 'A1')
  509.     {
  510.         $explodes explode(':'$range);
  511.  
  512.         // extract first cell, e.g. 'A1'
  513.         $firstCell $explodes[0];
  514.  
  515.         // extract last cell, e.g. 'B6'
  516.         if (count($explodes== 1{
  517.             $lastCell $firstCell;
  518.         else {
  519.             $lastCell $explodes[1];
  520.         }
  521.  
  522.         $firstCellCoordinates PHPExcel_Cell::coordinateFromString($firstCell)// e.g. array(0, 1)
  523.         $lastCellCoordinates  PHPExcel_Cell::coordinateFromString($lastCell);  // e.g. array(1, 6)
  524.  
  525.         $data pack('vvvv',
  526.             $firstCellCoordinates[11,
  527.             $lastCellCoordinates[11,
  528.             PHPExcel_Cell::columnIndexFromString($firstCellCoordinates[0]1,
  529.             PHPExcel_Cell::columnIndexFromString($lastCellCoordinates[0]1
  530.         );
  531.  
  532.         return $data;
  533.     }
  534.  
  535.     /**
  536.      * Retrieves data from memory in one chunk, or from disk in $buffer
  537.      * sized chunks.
  538.      *
  539.      * @return string The data
  540.      */
  541.     function getData()
  542.     {
  543.         $buffer 4096;
  544.  
  545.         // Return data stored in memory
  546.         if (isset($this->_data)) {
  547.             $tmp   $this->_data;
  548.             unset($this->_data);
  549.             return $tmp;
  550.         }
  551.         // No data to return
  552.         return false;
  553.     }
  554.  
  555.     /**
  556.      * Set the option to print the row and column headers on the printed page.
  557.      *
  558.      * @access public
  559.      * @param integer $print Whether to print the headers or not. Defaults to 1 (print).
  560.      */
  561.     function printRowColHeaders($print 1)
  562.     {
  563.         $this->_print_headers $print;
  564.     }
  565.  
  566.     /**
  567.      * This method sets the properties for outlining and grouping. The defaults
  568.      * correspond to Excel's defaults.
  569.      *
  570.      * @param bool $visible 
  571.      * @param bool $symbols_below 
  572.      * @param bool $symbols_right 
  573.      * @param bool $auto_style 
  574.      */
  575.     function setOutline($visible true$symbols_below true$symbols_right true$auto_style false)
  576.     {
  577.         $this->_outline_on    = $visible;
  578.         $this->_outline_below = $symbols_below;
  579.         $this->_outline_right = $symbols_right;
  580.         $this->_outline_style = $auto_style;
  581.  
  582.         // Ensure this is a boolean vale for Window2
  583.         if ($this->_outline_on{
  584.             $this->_outline_on = 1;
  585.         }
  586.      }
  587.  
  588.     /**
  589.      * Write a double to the specified row and column (zero indexed).
  590.      * An integer can be written as a double. Excel will display an
  591.      * integer. $format is optional.
  592.      *
  593.      * Returns  0 : normal termination
  594.      *         -2 : row or column out of range
  595.      *
  596.      * @param integer $row    Zero indexed row
  597.      * @param integer $col    Zero indexed column
  598.      * @param float   $num    The number to write
  599.      * @param mixed   $format The optional XF format
  600.      * @return integer 
  601.      */
  602.     private function _writeNumber($row$col$num$xfIndex)
  603.     {
  604.         $record    0x0203;                 // Record identifier
  605.         $length    0x000E;                 // Number of bytes to follow
  606.  
  607.         $header    pack("vv",  $record$length);
  608.         $data      pack("vvv"$row$col$xfIndex);
  609.         $xl_double pack("d",   $num);
  610.         if (PHPExcel_Writer_Excel5_BIFFwriter::getByteOrder()) // if it's Big Endian
  611.             $xl_double strrev($xl_double);
  612.         }
  613.  
  614.         $this->_append($header.$data.$xl_double);
  615.         return(0);
  616.     }
  617.  
  618.     /**
  619.      * Write a LABELSST record or a LABEL record. Which one depends on BIFF version
  620.      *
  621.      * @param int $row Row index (0-based)
  622.      * @param int $col Column index (0-based)
  623.      * @param string $str The string
  624.      * @param int $xfIndex Index to XF record
  625.      */
  626.     private function _writeString($row$col$str$xfIndex)
  627.     {
  628.         if ($this->_BIFF_version == 0x0600{
  629.             $this->_writeLabelSst($row$col$str$xfIndex);
  630.         else {
  631.             $this->_writeLabel($row$col$str$xfIndex);
  632.         }
  633.     }
  634.     /**
  635.      * Write a string to the specified row and column (zero indexed).
  636.      * NOTE: there is an Excel 5 defined limit of 255 characters.
  637.      * $format is optional.
  638.      * Returns  0 : normal termination
  639.      *         -2 : row or column out of range
  640.      *         -3 : long string truncated to 255 chars
  641.      *
  642.      * @access public
  643.      * @param integer $row    Zero indexed row
  644.      * @param integer $col    Zero indexed column
  645.      * @param string  $str    The string to write
  646.      * @param mixed   $format The XF format for the cell
  647.      * @return integer 
  648.      */
  649.     private function _writeLabel($row$col$str$xfIndex)
  650.     {
  651.         $strlen    strlen($str);
  652.         $record    0x0204;                   // Record identifier
  653.         $length    0x0008 $strlen;         // Bytes to follow
  654.  
  655.         $str_error 0;
  656.  
  657.         if ($strlen $this->_xls_strmax// LABEL must be < 255 chars
  658.             $str       substr($str0$this->_xls_strmax);
  659.             $length    0x0008 $this->_xls_strmax;
  660.             $strlen    $this->_xls_strmax;
  661.             $str_error = -3;
  662.         }
  663.  
  664.         $header    pack("vv",   $record$length);
  665.         $data      pack("vvvv"$row$col$xfIndex$strlen);
  666.         $this->_append($header $data $str);
  667.         return($str_error);
  668.     }
  669.  
  670.     /**
  671.      * Write a string to the specified row and column (zero indexed).
  672.      * This is the BIFF8 version (no 255 chars limit).
  673.      * $format is optional.
  674.      * Returns  0 : normal termination
  675.      *         -2 : row or column out of range
  676.      *         -3 : long string truncated to 255 chars
  677.      *
  678.      * @access public
  679.      * @param integer $row    Zero indexed row
  680.      * @param integer $col    Zero indexed column
  681.      * @param string  $str    The string to write
  682.      * @param mixed   $format The XF format for the cell
  683.      * @return integer 
  684.      */
  685.     private function _writeLabelSst($row$col$str$xfIndex)
  686.     {
  687.         $record    0x00FD;                   // Record identifier
  688.         $length    0x000A;                   // Bytes to follow
  689.  
  690.         $str PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($str);
  691.  
  692.         /* check if string is already present */
  693.         if (!isset($this->_str_table[$str])) {
  694.             $this->_str_table[$str$this->_str_unique++;
  695.         }
  696.         $this->_str_total++;
  697.  
  698.         $header    pack('vv',   $record$length);
  699.         $data      pack('vvvV'$row$col$xfIndex$this->_str_table[$str]);
  700.         $this->_append($header.$data);
  701.     }
  702.  
  703.     /**
  704.      * Writes a note associated with the cell given by the row and column.
  705.      * NOTE records don't have a length limit.
  706.      *
  707.      * @param integer $row    Zero indexed row
  708.      * @param integer $col    Zero indexed column
  709.      * @param string  $note   The note to write
  710.      */
  711.     private function _writeNote($row$col$note)
  712.     {
  713.         $note_length    strlen($note);
  714.         $record         0x001C;                // Record identifier
  715.         $max_length     2048;                  // Maximun length for a NOTE record
  716.         //$length      = 0x0006 + $note_length;    // Bytes to follow
  717.  
  718.         // Length for this record is no more than 2048 + 6
  719.         $length    0x0006 min($note_length2048);
  720.         $header    pack("vv",   $record$length);
  721.         $data      pack("vvv"$row$col$note_length);
  722.         $this->_append($header $data substr($note02048));
  723.  
  724.         for ($i $max_length$i $note_length$i += $max_length{
  725.             $chunk  substr($note$i$max_length);
  726.             $length 0x0006 strlen($chunk);
  727.             $header pack("vv",   $record$length);
  728.             $data   pack("vvv"-10strlen($chunk));
  729.             $this->_append($header.$data.$chunk);
  730.         }
  731.         return(0);
  732.     }
  733.  
  734.     /**
  735.      * Write a blank cell to the specified row and column (zero indexed).
  736.      * A blank cell is used to specify formatting without adding a string
  737.      * or a number.
  738.      *
  739.      * A blank cell without a format serves no purpose. Therefore, we don't write
  740.      * a BLANK record unless a format is specified.
  741.      *
  742.      * Returns  0 : normal termination (including no format)
  743.      *         -1 : insufficient number of arguments
  744.      *         -2 : row or column out of range
  745.      *
  746.      * @param integer $row    Zero indexed row
  747.      * @param integer $col    Zero indexed column
  748.      * @param mixed   $format The XF format
  749.      */
  750.     function _writeBlank($row$col$xfIndex)
  751.     {
  752.         $record    0x0201;                 // Record identifier
  753.         $length    0x0006;                 // Number of bytes to follow
  754.  
  755.         $header    pack("vv",  $record$length);
  756.         $data      pack("vvv"$row$col$xfIndex);
  757.         $this->_append($header $data);
  758.         return 0;
  759.     }
  760.  
  761.     /**
  762.      * Write a boolean or an error type to the specified row and column (zero indexed)
  763.      *
  764.      * @param int $row Row index (0-based)
  765.      * @param int $col Column index (0-based)
  766.      * @param int $value 
  767.      * @param boolean $isError Error or Boolean?
  768.      * @param int $xfIndex 
  769.      */
  770.     private function _writeBoolErr($row$col$value$isError$xfIndex)
  771.     {
  772.         $record 0x0205;
  773.         $length 8;
  774.  
  775.         $header    pack("vv",  $record$length);
  776.         $data      pack("vvvCC"$row$col$xfIndex$value$isError);
  777.         $this->_append($header $data);
  778.         return 0;
  779.     }
  780.  
  781.     /**
  782.      * Write a formula to the specified row and column (zero indexed).
  783.      * The textual representation of the formula is passed to the parser in
  784.      * Parser.php which returns a packed binary string.
  785.      *
  786.      * Returns  0 : normal termination
  787.      *         -1 : formula errors (bad formula)
  788.      *         -2 : row or column out of range
  789.      *
  790.      * @param integer $row     Zero indexed row
  791.      * @param integer $col     Zero indexed column
  792.      * @param string  $formula The formula text string
  793.      * @param mixed   $format  The optional XF format
  794.      * @param mixed   $calculatedValue  Calculated value
  795.      * @return integer 
  796.      */
  797.     private function _writeFormula($row$col$formula$xfIndex$calculatedValue)
  798.     {
  799.         $record    0x0006;     // Record identifier
  800.  
  801.         // Initialize possible additional value for STRING record that should be written after the FORMULA record?
  802.         $stringValue null;
  803.  
  804.         // calculated value
  805.         if (isset($calculatedValue)) {
  806.  
  807.             // Since we can't yet get the data type of the calculated value,
  808.             // we use best effort to determine data type
  809.  
  810.             if (is_bool($calculatedValue)) {
  811.                 // Boolean value
  812.                 $num pack('CCCvCv'0x010x00(int)$calculatedValue0x000x000xFFFF);
  813.  
  814.             elseif (is_int($calculatedValue|| is_float($calculatedValue)) {
  815.                 // Numeric value
  816.                 $num pack('d'$calculatedValue);
  817.  
  818.             elseif (is_string($calculatedValue)) {
  819.                 if (array_key_exists($calculatedValuePHPExcel_Cell_DataType::getErrorCodes())) {
  820.                     // Error value
  821.                     $num pack('CCCvCv'0x020x00$this->_mapErrorCode($calculatedValue)0x000x000xFFFF);
  822.  
  823.                 elseif ($calculatedValue === '' && $this->_BIFF_version == 0x0600{
  824.                     // Empty string (and BIFF8)
  825.                     $num pack('CCCvCv'0x030x000x000x000x000xFFFF);
  826.  
  827.                 else {
  828.                     // Non-empty string value (or empty string BIFF5)
  829.                     $stringValue $calculatedValue;
  830.                     $num pack('CCCvCv'0x000x000x000x000x000xFFFF);
  831.  
  832.                 }
  833.  
  834.             else {
  835.                 // We are really not supposed to reach here
  836.                 $num pack('d'0x00);
  837.  
  838.             }
  839.  
  840.         else {
  841.             $num pack('d'0x00);
  842.         }
  843.  
  844.         $grbit     0x03;                // Option flags
  845.         $unknown   0x0000;              // Must be zero
  846.  
  847.         // Strip the '=' or '@' sign at the beginning of the formula string
  848.         if (preg_match("/^=/"$formula)) {
  849.             $formula preg_replace("/(^=)/"""$formula);
  850.         else {
  851.             // Error handling
  852.             $this->_writeString($row$col'Unrecognised character for formula');
  853.             return -1;
  854.         }
  855.  
  856.         // Parse the formula using the parser in Parser.php
  857.         try {
  858.             $error $this->_parser->parse($formula);
  859.             $formula $this->_parser->toReversePolish();
  860.  
  861.             $formlen    strlen($formula);    // Length of the binary string
  862.             $length     0x16 $formlen;     // Length of the record data
  863.  
  864.             $header    pack("vv",      $record$length);
  865.  
  866.             $data      pack("vvv"$row$col$xfIndex)
  867.                         . $num
  868.                         . pack("vVv"$grbit$unknown$formlen);
  869.             $this->_append($header $data $formula);
  870.  
  871.             // Append also a STRING record if necessary
  872.             if ($stringValue !== null{
  873.                 $this->_writeStringRecord($stringValue);
  874.             }
  875.  
  876.             return 0;
  877.  
  878.         catch (Exception $e{
  879.             // do nothing
  880.         }
  881.  
  882.     }
  883.  
  884.     /**
  885.      * Write a STRING record. This
  886.      *
  887.      * @param string $stringValue 
  888.      */
  889.     private function _writeStringRecord($stringValue)
  890.     {
  891.         $record 0x0207;     // Record identifier
  892.         $data PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($stringValue);
  893.  
  894.         $length strlen($data);
  895.         $header pack('vv'$record$length);
  896.  
  897.         $this->_append($header $data);
  898.     }
  899.  
  900.     /**
  901.      * Write a hyperlink.
  902.      * This is comprised of two elements: the visible label and
  903.      * the invisible link. The visible label is the same as the link unless an
  904.      * alternative string is specified. The label is written using the
  905.      * _writeString() method. Therefore the 255 characters string limit applies.
  906.      * $string and $format are optional.
  907.      *
  908.      * The hyperlink can be to a http, ftp, mail, internal sheet (not yet), or external
  909.      * directory url.
  910.      *
  911.      * Returns  0 : normal termination
  912.      *         -2 : row or column out of range
  913.      *         -3 : long string truncated to 255 chars
  914.      *
  915.      * @param integer $row    Row
  916.      * @param integer $col    Column
  917.      * @param string  $url    URL string
  918.      * @return integer 
  919.      */
  920.     private function _writeUrl($row$col$url)
  921.     {
  922.         // Add start row and col to arg list
  923.         return($this->_writeUrlRange($row$col$row$col$url));
  924.     }
  925.  
  926.     /**
  927.      * This is the more general form of _writeUrl(). It allows a hyperlink to be
  928.      * written to a range of cells. This function also decides the type of hyperlink
  929.      * to be written. These are either, Web (http, ftp, mailto), Internal
  930.      * (Sheet1!A1) or external ('c:\temp\foo.xls#Sheet1!A1').
  931.      *
  932.      * @access private
  933.      * @see _writeUrl()
  934.      * @param integer $row1   Start row
  935.      * @param integer $col1   Start column
  936.      * @param integer $row2   End row
  937.      * @param integer $col2   End column
  938.      * @param string  $url    URL string
  939.      * @return integer 
  940.      */
  941.  
  942.     function _writeUrlRange($row1$col1$row2$col2$url)
  943.     {
  944.  
  945.         // Check for internal/external sheet links or default to web link
  946.         if (preg_match('[^internal:]'$url)) {
  947.             return($this->_writeUrlInternal($row1$col1$row2$col2$url));
  948.         }
  949.         if (preg_match('[^external:]'$url)) {
  950.             return($this->_writeUrlExternal($row1$col1$row2$col2$url));
  951.         }
  952.         return($this->_writeUrlWeb($row1$col1$row2$col2$url));
  953.     }
  954.  
  955.  
  956.     /**
  957.      * Used to write http, ftp and mailto hyperlinks.
  958.      * The link type ($options) is 0x03 is the same as absolute dir ref without
  959.      * sheet. However it is differentiated by the $unknown2 data stream.
  960.      *
  961.      * @access private
  962.      * @see _writeUrl()
  963.      * @param integer $row1   Start row
  964.      * @param integer $col1   Start column
  965.      * @param integer $row2   End row
  966.      * @param integer $col2   End column
  967.      * @param string  $url    URL string
  968.      * @return integer 
  969.      */
  970.     function _writeUrlWeb($row1$col1$row2$col2$url)
  971.     {
  972.         $record      0x01B8;                       // Record identifier
  973.         $length      0x00000;                      // Bytes to follow
  974.  
  975.         // Pack the undocumented parts of the hyperlink stream
  976.         $unknown1    pack("H*""D0C9EA79F9BACE118C8200AA004BA90B02000000");
  977.         $unknown2    pack("H*""E0C9EA79F9BACE118C8200AA004BA90B");
  978.  
  979.         // Pack the option flags
  980.         $options     pack("V"0x03);
  981.  
  982.         // Convert URL to a null terminated wchar string
  983.         $url         join("\0"preg_split("''"$url-1PREG_SPLIT_NO_EMPTY));
  984.         $url         $url "\0\0\0";
  985.  
  986.         // Pack the length of the URL
  987.         $url_len     pack("V"strlen($url));
  988.  
  989.         // Calculate the data length
  990.         $length      0x34 strlen($url);
  991.  
  992.         // Pack the header data
  993.         $header      pack("vv",   $record$length);
  994.         $data        pack("vvvv"$row1$row2$col1$col2);
  995.  
  996.         // Write the packed data
  997.         $this->_append($header $data .
  998.                        $unknown1 $options .
  999.                        $unknown2 $url_len $url);
  1000.         return 0;
  1001.     }
  1002.  
  1003.     /**
  1004.      * Used to write internal reference hyperlinks such as "Sheet1!A1".
  1005.      *
  1006.      * @access private
  1007.      * @see _writeUrl()
  1008.      * @param integer $row1   Start row
  1009.      * @param integer $col1   Start column
  1010.      * @param integer $row2   End row
  1011.      * @param integer $col2   End column
  1012.      * @param string  $url    URL string
  1013.      * @return integer 
  1014.      */
  1015.     function _writeUrlInternal($row1$col1$row2$col2$url)
  1016.     {
  1017.         $record      0x01B8;                       // Record identifier
  1018.         $length      0x00000;                      // Bytes to follow
  1019.  
  1020.         // Strip URL type
  1021.         $url preg_replace('/^internal:/'''$url);
  1022.  
  1023.         // Pack the undocumented parts of the hyperlink stream
  1024.         $unknown1    pack("H*""D0C9EA79F9BACE118C8200AA004BA90B02000000");
  1025.  
  1026.         // Pack the option flags
  1027.         $options     pack("V"0x08);
  1028.  
  1029.         // Convert the URL type and to a null terminated wchar string
  1030.         $url .= "\0";
  1031.  
  1032.         // character count
  1033.         $url_len PHPExcel_Shared_String::CountCharacters($url);
  1034.         $url_len pack('V'$url_len);
  1035.  
  1036.         $url PHPExcel_Shared_String::ConvertEncoding($url'UTF-16LE''UTF-8');
  1037.  
  1038.         // Calculate the data length
  1039.         $length      0x24 strlen($url);
  1040.  
  1041.         // Pack the header data
  1042.         $header      pack("vv",   $record$length);
  1043.         $data        pack("vvvv"$row1$row2$col1$col2);
  1044.  
  1045.         // Write the packed data
  1046.         $this->_append($header $data .
  1047.                        $unknown1 $options .
  1048.                        $url_len $url);
  1049.         return 0;
  1050.     }
  1051.  
  1052.     /**
  1053.      * Write links to external directory names such as 'c:\foo.xls',
  1054.      * c:\foo.xls#Sheet1!A1', '../../foo.xls'. and '../../foo.xls#Sheet1!A1'.
  1055.      *
  1056.      * Note: Excel writes some relative links with the $dir_long string. We ignore
  1057.      * these cases for the sake of simpler code.
  1058.      *
  1059.      * @access private
  1060.      * @see _writeUrl()
  1061.      * @param integer $row1   Start row
  1062.      * @param integer $col1   Start column
  1063.      * @param integer $row2   End row
  1064.      * @param integer $col2   End column
  1065.      * @param string  $url    URL string
  1066.      * @return integer 
  1067.      */
  1068.     function _writeUrlExternal($row1$col1$row2$col2$url)
  1069.     {
  1070.         // Network drives are different. We will handle them separately
  1071.         // MS/Novell network drives and shares start with \\
  1072.         if (preg_match('[^external:\\\\]'$url)) {
  1073.             return//($this->_writeUrlExternal_net($row1, $col1, $row2, $col2, $url, $str, $format));
  1074.         }
  1075.  
  1076.         $record      0x01B8;                       // Record identifier
  1077.         $length      0x00000;                      // Bytes to follow
  1078.  
  1079.         // Strip URL type and change Unix dir separator to Dos style (if needed)
  1080.         //
  1081.         $url preg_replace('/^external:/'''$url);
  1082.         $url preg_replace('/\//'"\\"$url);
  1083.  
  1084.         // Determine if the link is relative or absolute:
  1085.         //   relative if link contains no dir separator, "somefile.xls"
  1086.         //   relative if link starts with up-dir, "..\..\somefile.xls"
  1087.         //   otherwise, absolute
  1088.  
  1089.         $absolute 0x00// relative path
  1090.         if preg_match('/^[A-Z]:/'$url) ) {
  1091.             $absolute 0x02// absolute path on Windows, e.g. C:\...
  1092.         }
  1093.         $link_type               0x01 $absolute;
  1094.  
  1095.         // Determine if the link contains a sheet reference and change some of the
  1096.         // parameters accordingly.
  1097.         // Split the dir name and sheet name (if it exists)
  1098.         $dir_long $url;
  1099.         if (preg_match("/\#/"$url)) {
  1100.             $link_type |= 0x08;
  1101.         }
  1102.  
  1103.  
  1104.         // Pack the link type
  1105.         $link_type   pack("V"$link_type);
  1106.  
  1107.         // Calculate the up-level dir count e.g.. (..\..\..\ == 3)
  1108.         $up_count    preg_match_all("/\.\.\\\/"$dir_long$useless);
  1109.         $up_count    pack("v"$up_count);
  1110.  
  1111.         // Store the short dos dir name (null terminated)
  1112.         $dir_short   preg_replace("/\.\.\\\/"''$dir_long"\0";
  1113.  
  1114.         // Store the long dir name as a wchar string (non-null terminated)
  1115.         $dir_long       $dir_long "\0";
  1116.  
  1117.         // Pack the lengths of the dir strings
  1118.         $dir_short_len pack("V"strlen($dir_short)      );
  1119.         $dir_long_len  pack("V"strlen($dir_long)       );
  1120.         $stream_len    pack("V"0);//strlen($dir_long) + 0x06);
  1121.  
  1122.         // Pack the undocumented parts of the hyperlink stream
  1123.         $unknown1 pack("H*",'D0C9EA79F9BACE118C8200AA004BA90B02000000'       );
  1124.         $unknown2 pack("H*",'0303000000000000C000000000000046'               );
  1125.         $unknown3 pack("H*",'FFFFADDE000000000000000000000000000000000000000');
  1126.         $unknown4 pack("v",  0x03                                            );
  1127.  
  1128.         // Pack the main data stream
  1129.         $data        pack("vvvv"$row1$row2$col1$col2.
  1130.                           $unknown1     .
  1131.                           $link_type    .
  1132.                           $unknown2     .
  1133.                           $up_count     .
  1134.                           $dir_short_len.
  1135.                           $dir_short    .
  1136.                           $unknown3     .
  1137.                           $stream_len   ;/*.
  1138.                           $dir_long_len .
  1139.                           $unknown4     .
  1140.                           $dir_long     .
  1141.                           $sheet_len    .
  1142.                           $sheet        ;*/
  1143.  
  1144.         // Pack the header data
  1145.         $length   strlen($data);
  1146.         $header   pack("vv"$record$length);
  1147.  
  1148.         // Write the packed data
  1149.         $this->_append($header$data);
  1150.         return 0;
  1151.     }
  1152.  
  1153.     /**
  1154.      * This method is used to set the height and format for a row.
  1155.      *
  1156.      * @param integer $row    The row to set
  1157.      * @param integer $height Height we are giving to the row.
  1158.      *                         Use null to set XF without setting height
  1159.      * @param integer $xfIndex  The optional cell style Xf index to apply to the columns
  1160.      * @param bool    $hidden The optional hidden attribute
  1161.      * @param integer $level  The optional outline level for row, in range [0,7]
  1162.      */
  1163.     private function _writeRow($row$height$xfIndex$hidden false$level 0)
  1164.     {
  1165.         $record      0x0208;               // Record identifier
  1166.         $length      0x0010;               // Number of bytes to follow
  1167.  
  1168.         $colMic      0x0000;               // First defined column
  1169.         $colMac      0x0000;               // Last defined column
  1170.         $irwMac      0x0000;               // Used by Excel to optimise loading
  1171.         $reserved    0x0000;               // Reserved
  1172.         $grbit       0x0000;               // Option flags
  1173.         $ixfe        $xfIndex;
  1174.  
  1175.         if $height ){
  1176.             $height null;
  1177.         }
  1178.  
  1179.         // Use _writeRow($row, null, $XF) to set XF format without setting height
  1180.         if ($height != null{
  1181.             $miyRw $height 20;  // row height
  1182.         else {
  1183.             $miyRw 0xff;          // default row height is 256
  1184.         }
  1185.  
  1186.         // Set the options flags. fUnsynced is used to show that the font and row
  1187.         // heights are not compatible. This is usually the case for WriteExcel.
  1188.         // The collapsed flag 0x10 doesn't seem to be used to indicate that a row
  1189.         // is collapsed. Instead it is used to indicate that the previous row is
  1190.         // collapsed. The zero height flag, 0x20, is used to collapse a row.
  1191.  
  1192.         $grbit |= $level;
  1193.         if ($hidden{
  1194.             $grbit |= 0x0020;
  1195.         }
  1196.         if ($height !== null{
  1197.             $grbit |= 0x0040// fUnsynced
  1198.         }
  1199.         if ($xfIndex !== 0xF{
  1200.             $grbit |= 0x0080;
  1201.         }
  1202.         $grbit |= 0x0100;
  1203.  
  1204.         $header   pack("vv",       $record$length);
  1205.         $data     pack("vvvvvvvv"$row$colMic$colMac$miyRw,
  1206.                                      $irwMac,$reserved$grbit$ixfe);
  1207.         $this->_append($header.$data);
  1208.     }
  1209.  
  1210.     /**
  1211.      * Writes Excel DIMENSIONS to define the area in which there is data.
  1212.      */
  1213.     private function _writeDimensions()
  1214.     {
  1215.         $record 0x0200// Record identifier
  1216.  
  1217.         if ($this->_BIFF_version == 0x0500{
  1218.             $length 0x000A;               // Number of bytes to follow
  1219.             $data pack("vvvvv"
  1220.                     $this->_firstRowIndex
  1221.                     $this->_lastRowIndex 1
  1222.                     $this->_firstColumnIndex
  1223.                     $this->_lastColumnIndex 1
  1224.                     0x0000 // reserved
  1225.                 );
  1226.  
  1227.         elseif ($this->_BIFF_version == 0x0600{
  1228.             $length 0x000E;
  1229.             $data pack('VVvvv'
  1230.                     $this->_firstRowIndex
  1231.                     $this->_lastRowIndex 1
  1232.                     $this->_firstColumnIndex
  1233.                     $this->_lastColumnIndex 1
  1234.                     0x0000 // reserved
  1235.                 );
  1236.         }
  1237.  
  1238.         $header pack("vv"$record$length);
  1239.         $this->_append($header.$data);
  1240.     }
  1241.  
  1242.     /**
  1243.      * Write BIFF record Window2.
  1244.      */
  1245.     private function _writeWindow2()
  1246.     {
  1247.         $record         0x023E;     // Record identifier
  1248.         if ($this->_BIFF_version == 0x0500{
  1249.             $length         0x000A;     // Number of bytes to follow
  1250.         elseif ($this->_BIFF_version == 0x0600{
  1251.             $length         0x0012;
  1252.         }
  1253.  
  1254.         $grbit          0x00B6;     // Option flags
  1255.         $rwTop          0x0000;     // Top row visible in window
  1256.         $colLeft        0x0000;     // Leftmost column visible in window
  1257.  
  1258.  
  1259.         // The options flags that comprise $grbit
  1260.         $fDspFmla       0;                     // 0 - bit
  1261.         $fDspGrid       $this->_phpSheet->getShowGridlines(0// 1
  1262.         $fDspRwCol      $this->_phpSheet->getShowRowColHeaders(0// 2
  1263.         $fFrozen        $this->_phpSheet->getFreezePane(0;        // 3
  1264.         $fDspZeros      1;                     // 4
  1265.         $fDefaultHdr    1;                     // 5
  1266.         $fArabic        $this->_phpSheet->getRightToLeft(0// 6
  1267.         $fDspGuts       $this->_outline_on;    // 7
  1268.         $fFrozenNoSplit 0;                     // 0 - bit
  1269.         // no support in PHPExcel for selected sheet, therefore sheet is only selected if it is the active sheet
  1270.         $fSelected      ($this->_phpSheet === $this->_phpSheet->getParent()->getActiveSheet()) 0;
  1271.         $fPaged         1;                     // 2
  1272.  
  1273.         $grbit             $fDspFmla;
  1274.         $grbit            |= $fDspGrid       << 1;
  1275.         $grbit            |= $fDspRwCol      << 2;
  1276.         $grbit            |= $fFrozen        << 3;
  1277.         $grbit            |= $fDspZeros      << 4;
  1278.         $grbit            |= $fDefaultHdr    << 5;
  1279.         $grbit            |= $fArabic        << 6;
  1280.         $grbit            |= $fDspGuts       << 7;
  1281.         $grbit            |= $fFrozenNoSplit << 8;
  1282.         $grbit            |= $fSelected      << 9;
  1283.         $grbit            |= $fPaged         << 10;
  1284.  
  1285.         $header  pack("vv",   $record$length);
  1286.         $data    pack("vvv"$grbit$rwTop$colLeft);
  1287.         // FIXME !!!
  1288.         if ($this->_BIFF_version == 0x0500{
  1289.             $rgbHdr         0x00000000// Row/column heading and gridline color
  1290.             $data .= pack("V"$rgbHdr);
  1291.         elseif ($this->_BIFF_version == 0x0600{
  1292.             $rgbHdr       0x0040// Row/column heading and gridline color index
  1293.             $zoom_factor_page_break 0x0000;
  1294.             $zoom_factor_normal     0x0000;
  1295.             $data .= pack("vvvvV"$rgbHdr0x0000$zoom_factor_page_break$zoom_factor_normal0x00000000);
  1296.         }
  1297.         $this->_append($header.$data);
  1298.     }
  1299.  
  1300.     /**
  1301.      * Write BIFF record DEFAULTROWHEIGHT.
  1302.      */
  1303.     private function _writeDefaultRowHeight()
  1304.     {
  1305.         $defaultRowHeight $this->_phpSheet->getDefaultRowDimension()->getRowHeight();
  1306.  
  1307.         if ($defaultRowHeight 0{
  1308.             return;
  1309.         }
  1310.  
  1311.         // convert to twips
  1312.         $defaultRowHeight = (int) 20 $defaultRowHeight;
  1313.  
  1314.         $record   0x0225;      // Record identifier
  1315.         $length   0x0004;      // Number of bytes to follow
  1316.  
  1317.         $header   pack("vv"$record$length);
  1318.         $data     pack("vv",  1$defaultRowHeight);
  1319.         $this->_append($header $data);
  1320.     }
  1321.  
  1322.     /**
  1323.      * Write BIFF record DEFCOLWIDTH if COLINFO records are in use.
  1324.      */
  1325.     private function _writeDefcol()
  1326.     {
  1327.         $defaultColWidth 8;
  1328.  
  1329.         $record   0x0055;      // Record identifier
  1330.         $length   0x0002;      // Number of bytes to follow
  1331.  
  1332.         $header pack("vv"$record$length);
  1333.         $data pack("v"$defaultColWidth);
  1334.         $this->_append($header $data);
  1335.     }
  1336.  
  1337.     /**
  1338.      * Write BIFF record COLINFO to define column widths
  1339.      *
  1340.      * Note: The SDK says the record length is 0x0B but Excel writes a 0x0C
  1341.      * length record.
  1342.      *
  1343.      * @param array $col_array This is the only parameter received and is composed of the following:
  1344.      *                 0 => First formatted column,
  1345.      *                 1 => Last formatted column,
  1346.      *                 2 => Col width (8.43 is Excel default),
  1347.      *                 3 => The optional XF format of the column,
  1348.      *                 4 => Option flags.
  1349.      *                 5 => Optional outline level
  1350.      */
  1351.     private function _writeColinfo($col_array)
  1352.     {
  1353.         if (isset($col_array[0])) {
  1354.             $colFirst $col_array[0];
  1355.         }
  1356.         if (isset($col_array[1])) {
  1357.             $colLast $col_array[1];
  1358.         }
  1359.         if (isset($col_array[2])) {
  1360.             $coldx $col_array[2];
  1361.         else {
  1362.             $coldx 8.43;
  1363.         }
  1364.         if (isset($col_array[3])) {
  1365.             $xfIndex $col_array[3];
  1366.         else {
  1367.             $xfIndex 15;
  1368.         }
  1369.         if (isset($col_array[4])) {
  1370.             $grbit $col_array[4];
  1371.         else {
  1372.             $grbit 0;
  1373.         }
  1374.         if (isset($col_array[5])) {
  1375.             $level $col_array[5];
  1376.         else {
  1377.             $level 0;
  1378.         }
  1379.         $record   0x007D;          // Record identifier
  1380.         $length   0x000C;          // Number of bytes to follow
  1381.  
  1382.         $coldx   *= 256;             // Convert to units of 1/256 of a char
  1383.  
  1384.         $ixfe     $xfIndex;
  1385.         $reserved 0x0000;            // Reserved
  1386.  
  1387.         $level max(0min($level7));
  1388.         $grbit |= $level << 8;
  1389.  
  1390.         $header   pack("vv",     $record$length);
  1391.         $data     pack("vvvvvv"$colFirst$colLast$coldx,
  1392.                                    $ixfe$grbit$reserved);
  1393.         $this->_append($header.$data);
  1394.     }
  1395.  
  1396.     /**
  1397.      * Write BIFF record SELECTION.
  1398.      */
  1399.     private function _writeSelection()
  1400.     {
  1401.         // look up the selected cell range
  1402.         $selectedCells $this->_phpSheet->getSelectedCells();
  1403.         $selectedCells PHPExcel_Cell::splitRange($this->_phpSheet->getSelectedCells());
  1404.         $selectedCells $selectedCells[0];
  1405.         if (count($selectedCells== 2{
  1406.             list($first$last$selectedCells;
  1407.         else {
  1408.             $first $selectedCells[0];
  1409.             $last  $selectedCells[0];
  1410.         }
  1411.  
  1412.         list($colFirst$rwFirstPHPExcel_Cell::coordinateFromString($first);
  1413.         $colFirst PHPExcel_Cell::columnIndexFromString($colFirst1// base 0 column index
  1414.         --$rwFirst// base 0 row index
  1415.  
  1416.         list($colLast$rwLastPHPExcel_Cell::coordinateFromString($last);
  1417.         $colLast PHPExcel_Cell::columnIndexFromString($colLast1// base 0 column index
  1418.         --$rwLast// base 0 row index
  1419.  
  1420.         // make sure we are not out of bounds
  1421.         $colFirst min($colFirst255);
  1422.         $colLast  min($colLast,  255);
  1423.         if ($this->_BIFF_version == 0x0600{
  1424.             $rwFirst min($rwFirst65535);
  1425.             $rwLast  min($rwLast,  65535);
  1426.         else {
  1427.             $rwFirst min($rwFirst16383);
  1428.             $rwLast  min($rwLast,  16383);
  1429.         }
  1430.  
  1431.         $record   0x001D;                  // Record identifier
  1432.         $length   0x000F;                  // Number of bytes to follow
  1433.  
  1434.         $pnn      $this->_active_pane;     // Pane position
  1435.         $rwAct    $rwFirst;                // Active row
  1436.         $colAct   $colFirst;               // Active column
  1437.         $irefAct  0;                       // Active cell ref
  1438.         $cref     1;                       // Number of refs
  1439.  
  1440.         if (!isset($rwLast)) {
  1441.             $rwLast   $rwFirst;       // Last  row in reference
  1442.         }
  1443.         if (!isset($colLast)) {
  1444.             $colLast  $colFirst;      // Last  col in reference
  1445.         }
  1446.  
  1447.         // Swap last row/col for first row/col as necessary
  1448.         if ($rwFirst $rwLast{
  1449.             list($rwFirst$rwLastarray($rwLast$rwFirst);
  1450.         }
  1451.  
  1452.         if ($colFirst $colLast{
  1453.             list($colFirst$colLastarray($colLast$colFirst);
  1454.         }
  1455.  
  1456.         $header   pack("vv",         $record$length);
  1457.         $data     pack("CvvvvvvCC",  $pnn$rwAct$colAct,
  1458.                                        $irefAct$cref,
  1459.                                        $rwFirst$rwLast,
  1460.                                        $colFirst$colLast);
  1461.         $this->_append($header $data);
  1462.     }
  1463.  
  1464.     /**
  1465.      * Store the MERGEDCELLS records for all ranges of merged cells
  1466.      */
  1467.     private function _writeMergedCells()
  1468.     {
  1469.         $mergeCells $this->_phpSheet->getMergeCells();
  1470.         $countMergeCells count($mergeCells);
  1471.  
  1472.         if ($countMergeCells == 0{
  1473.             return;
  1474.         }
  1475.  
  1476.         // maximum allowed number of merged cells per record
  1477.         if ($this->_BIFF_version == 0x0600{
  1478.             $maxCountMergeCellsPerRecord 1027;
  1479.         else {
  1480.             $maxCountMergeCellsPerRecord 259;
  1481.         }
  1482.  
  1483.         // record identifier
  1484.         $record 0x00E5;
  1485.  
  1486.         // counter for total number of merged cells treated so far by the writer
  1487.         $i 0;
  1488.  
  1489.         // counter for number of merged cells written in record currently being written
  1490.         $j 0;
  1491.  
  1492.         // initialize record data
  1493.         $recordData '';
  1494.  
  1495.         // loop through the merged cells
  1496.         foreach ($mergeCells as $mergeCell{
  1497.             ++$i;
  1498.             ++$j;
  1499.  
  1500.             // extract the row and column indexes
  1501.             $range PHPExcel_Cell::splitRange($mergeCell);
  1502.             list($first$last$range[0];
  1503.             list($firstColumn$firstRowPHPExcel_Cell::coordinateFromString($first);
  1504.             list($lastColumn$lastRowPHPExcel_Cell::coordinateFromString($last);
  1505.  
  1506.             $recordData .= pack('vvvv'$firstRow 1$lastRow 1PHPExcel_Cell::columnIndexFromString($firstColumn1PHPExcel_Cell::columnIndexFromString($lastColumn1);
  1507.  
  1508.             // flush record if we have reached limit for number of merged cells, or reached final merged cell
  1509.             if ($j == $maxCountMergeCellsPerRecord or $i == $countMergeCells{
  1510.                 $recordData pack('v'$j$recordData;
  1511.                 $length strlen($recordData);
  1512.                 $header pack('vv'$record$length);
  1513.                 $this->_append($header $recordData);
  1514.  
  1515.                 // initialize for next record, if any
  1516.                 $recordData '';
  1517.                 $j 0;
  1518.             }
  1519.         }
  1520.     }
  1521.  
  1522.     /**
  1523.      * Write SHEETLAYOUT record
  1524.      */
  1525.     private function _writeSheetLayout()
  1526.     {
  1527.         if (!$this->_phpSheet->isTabColorSet()) {
  1528.             return;
  1529.         }
  1530.  
  1531.         $recordData pack(
  1532.             'vvVVVvv'
  1533.             0x0862
  1534.             0x0000        // unused
  1535.             0x00000000    // unused
  1536.             0x00000000    // unused
  1537.             0x00000014    // size of record data
  1538.             $this->_colors[$this->_phpSheet->getTabColor()->getRGB()]    // color index
  1539.             0x0000        // unused
  1540.         );
  1541.  
  1542.         $length strlen($recordData);
  1543.  
  1544.         $record 0x0862// Record identifier
  1545.         $header pack('vv'$record$length);
  1546.         $this->_append($header $recordData);
  1547.     }
  1548.  
  1549.     /**
  1550.      * Write SHEETPROTECTION
  1551.      */
  1552.     private function _writeSheetProtection()
  1553.     {
  1554.         // record identifier
  1555.         $record 0x0867;
  1556.  
  1557.         // prepare options
  1558.         $options  =   (int) !$this->_phpSheet->getProtection()->getObjects()
  1559.                     | (int) !$this->_phpSheet->getProtection()->getScenarios()           << 1
  1560.                     | (int) !$this->_phpSheet->getProtection()->getFormatCells()         << 2
  1561.                     | (int) !$this->_phpSheet->getProtection()->getFormatColumns()       << 3
  1562.                     | (int) !$this->_phpSheet->getProtection()->getFormatRows()          << 4
  1563.                     | (int) !$this->_phpSheet->getProtection()->getInsertColumns()       << 5
  1564.                     | (int) !$this->_phpSheet->getProtection()->getInsertRows()          << 6
  1565.                     | (int) !$this->_phpSheet->getProtection()->getInsertHyperlinks()    << 7
  1566.                     | (int) !$this->_phpSheet->getProtection()->getDeleteColumns()       << 8
  1567.                     | (int) !$this->_phpSheet->getProtection()->getDeleteRows()          << 9
  1568.                     | (int) !$this->_phpSheet->getProtection()->getSelectLockedCells()   << 10
  1569.                     | (int) !$this->_phpSheet->getProtection()->getSort()                << 11
  1570.                     | (int) !$this->_phpSheet->getProtection()->getAutoFilter()          << 12
  1571.                     | (int) !$this->_phpSheet->getProtection()->getPivotTables()         << 13
  1572.                     | (int) !$this->_phpSheet->getProtection()->getSelectUnlockedCells(<< 14 ;
  1573.  
  1574.         // record data
  1575.         $recordData pack(
  1576.             'vVVCVVvv'
  1577.             0x0867        // repeated record identifier
  1578.             0x0000        // not used
  1579.             0x0000        // not used
  1580.             0x00            // not used
  1581.             0x01000200    // unknown data
  1582.             0xFFFFFFFF    // unknown data
  1583.             $options        // options
  1584.             0x0000        // not used
  1585.         );
  1586.  
  1587.         $length strlen($recordData);
  1588.         $header pack('vv'$record$length);
  1589.  
  1590.         $this->_append($header $recordData);
  1591.     }
  1592.  
  1593.     /**
  1594.      * Write BIFF record RANGEPROTECTION
  1595.      *
  1596.      * Openoffice.org's Documentaion of the Microsoft Excel File Format uses term RANGEPROTECTION for these records
  1597.      * Microsoft Office Excel 97-2007 Binary File Format Specification uses term FEAT for these records
  1598.      */
  1599.     private function _writeRangeProtection()
  1600.     {
  1601.         foreach ($this->_phpSheet->getProtectedCells(as $range => $password{
  1602.             // number of ranges, e.g. 'A1:B3 C20:D25'
  1603.             $cellRanges explode(' '$range);
  1604.             $cref count($cellRanges);
  1605.  
  1606.             $recordData pack(
  1607.                 'vvVVvCVvVv',
  1608.                 0x0868,
  1609.                 0x00,
  1610.                 0x0000,
  1611.                 0x0000,
  1612.                 0x02,
  1613.                 0x0,
  1614.                 0x0000,
  1615.                 $cref,
  1616.                 0x0000,
  1617.                 0x00
  1618.             );
  1619.  
  1620.             foreach ($cellRanges as $cellRange{
  1621.                 $recordData .= $this->_writeBIFF8CellRangeAddressFixed($cellRange);
  1622.             }
  1623.  
  1624.             // the rgbFeat structure
  1625.             $recordData .= pack(
  1626.                 'VV',
  1627.                 0x0000,
  1628.                 hexdec($password)
  1629.             );
  1630.  
  1631.             $recordData .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong('p' md5($recordData));
  1632.  
  1633.             $length strlen($recordData);
  1634.  
  1635.             $record 0x0868;        // Record identifier
  1636.             $header pack("vv"$record$length);
  1637.             $this->_append($header $recordData);
  1638.         }
  1639.     }
  1640.  
  1641.     /**
  1642.      * Write BIFF record EXTERNCOUNT to indicate the number of external sheet
  1643.      * references in a worksheet.
  1644.      *
  1645.      * Excel only stores references to external sheets that are used in formulas.
  1646.      * For simplicity we store references to all the sheets in the workbook
  1647.      * regardless of whether they are used or not. This reduces the overall
  1648.      * complexity and eliminates the need for a two way dialogue between the formula
  1649.      * parser the worksheet objects.
  1650.      *
  1651.      * @param integer $count The number of external sheet references in this worksheet
  1652.      */
  1653.     private function _writeExterncount($count)
  1654.     {
  1655.         $record 0x0016;          // Record identifier
  1656.         $length 0x0002;          // Number of bytes to follow
  1657.  
  1658.         $header pack("vv"$record$length);
  1659.         $data   pack("v",  $count);
  1660.         $this->_append($header $data);
  1661.     }
  1662.  
  1663.     /**
  1664.      * Writes the Excel BIFF EXTERNSHEET record. These references are used by
  1665.      * formulas. A formula references a sheet name via an index. Since we store a
  1666.      * reference to all of the external worksheets the EXTERNSHEET index is the same
  1667.      * as the worksheet index.
  1668.      *
  1669.      * @param string $sheetname The name of a external worksheet
  1670.      */
  1671.     private function _writeExternsheet($sheetname)
  1672.     {
  1673.         $record    0x0017;         // Record identifier
  1674.  
  1675.         // References to the current sheet are encoded differently to references to
  1676.         // external sheets.
  1677.         //
  1678.         if ($this->_phpSheet->getTitle(== $sheetname{
  1679.             $sheetname '';
  1680.             $length    0x02;  // The following 2 bytes
  1681.             $cch       1;     // The following byte
  1682.             $rgch      0x02;  // Self reference
  1683.         else {
  1684.             $length    0x02 strlen($sheetname);
  1685.             $cch       strlen($sheetname);
  1686.             $rgch      0x03;  // Reference to a sheet in the current workbook
  1687.         }
  1688.  
  1689.         $header pack("vv",  $record$length);
  1690.         $data   pack("CC"$cch$rgch);
  1691.         $this->_append($header $data $sheetname);
  1692.     }
  1693.  
  1694.     /**
  1695.      * Writes the Excel BIFF PANE record.
  1696.      * The panes can either be frozen or thawed (unfrozen).
  1697.      * Frozen panes are specified in terms of an integer number of rows and columns.
  1698.      * Thawed panes are specified in terms of Excel's units for rows and columns.
  1699.      */
  1700.     private function _writePanes()
  1701.     {
  1702.         $panes array();
  1703.         if ($freezePane $this->_phpSheet->getFreezePane()) {
  1704.             list($column$rowPHPExcel_Cell::coordinateFromString($freezePane);
  1705.             $panes[0$row 1;
  1706.             $panes[1PHPExcel_Cell::columnIndexFromString($column1;
  1707.         else {
  1708.             // thaw panes
  1709.             return;
  1710.         }
  1711.  
  1712.         $y       = isset($panes[0]$panes[0null;
  1713.         $x       = isset($panes[1]$panes[1null;
  1714.         $rwTop   = isset($panes[2]$panes[2null;
  1715.         $colLeft = isset($panes[3]$panes[3null;
  1716.         if (count($panes4// if Active pane was received
  1717.             $pnnAct $panes[4];
  1718.         else {
  1719.             $pnnAct null;
  1720.         }
  1721.         $record  0x0041;       // Record identifier
  1722.         $length  0x000A;       // Number of bytes to follow
  1723.  
  1724.         // Code specific to frozen or thawed panes.
  1725.         if ($this->_phpSheet->getFreezePane()) {
  1726.             // Set default values for $rwTop and $colLeft
  1727.             if (!isset($rwTop)) {
  1728.                 $rwTop   $y;
  1729.             }
  1730.             if (!isset($colLeft)) {
  1731.                 $colLeft $x;
  1732.             }
  1733.         else {
  1734.             // Set default values for $rwTop and $colLeft
  1735.             if (!isset($rwTop)) {
  1736.                 $rwTop   0;
  1737.             }
  1738.             if (!isset($colLeft)) {
  1739.                 $colLeft 0;
  1740.             }
  1741.  
  1742.             // Convert Excel's row and column units to the internal units.
  1743.             // The default row height is 12.75
  1744.             // The default column width is 8.43
  1745.             // The following slope and intersection values were interpolated.
  1746.             //
  1747.             $y 20*$y      255;
  1748.             $x 113.879*$x 390;
  1749.         }
  1750.  
  1751.  
  1752.         // Determine which pane should be active. There is also the undocumented
  1753.         // option to override this should it be necessary: may be removed later.
  1754.         //
  1755.         if (!isset($pnnAct)) {
  1756.             if ($x != && $y != 0{
  1757.                 $pnnAct 0// Bottom right
  1758.             }
  1759.             if ($x != && $y == 0{
  1760.                 $pnnAct 1// Top right
  1761.             }
  1762.             if ($x == && $y != 0{
  1763.                 $pnnAct 2// Bottom left
  1764.             }
  1765.             if ($x == && $y == 0{
  1766.                 $pnnAct 3// Top left
  1767.             }
  1768.         }
  1769.  
  1770.         $this->_active_pane = $pnnAct// Used in _writeSelection
  1771.  
  1772.         $header     pack("vv",    $record$length);
  1773.         $data       pack("vvvvv"$x$y$rwTop$colLeft$pnnAct);
  1774.         $this->_append($header $data);
  1775.     }
  1776.  
  1777.     /**
  1778.      * Store the page setup SETUP BIFF record.
  1779.      */
  1780.     private function _writeSetup()
  1781.     {
  1782.         $record       0x00A1;                  // Record identifier
  1783.         $length       0x0022;                  // Number of bytes to follow
  1784.  
  1785.         $iPaperSize   $this->_phpSheet->getPageSetup()->getPaperSize();    // Paper size
  1786.  
  1787.         $iScale $this->_phpSheet->getPageSetup()->getScale(?
  1788.             $this->_phpSheet->getPageSetup()->getScale(100;   // Print scaling factor
  1789.  
  1790.         $iPageStart   0x01;                 // Starting page number
  1791.         $iFitWidth    = (int) $this->_phpSheet->getPageSetup()->getFitToWidth();    // Fit to number of pages wide
  1792.         $iFitHeight    = (int) $this->_phpSheet->getPageSetup()->getFitToHeight();    // Fit to number of pages high
  1793.         $grbit        0x00;                 // Option flags
  1794.         $iRes         0x0258;               // Print resolution
  1795.         $iVRes        0x0258;               // Vertical print resolution
  1796.  
  1797.         $numHdr       $this->_phpSheet->getPageMargins()->getHeader();  // Header Margin
  1798.  
  1799.         $numFtr       $this->_phpSheet->getPageMargins()->getFooter();   // Footer Margin
  1800.         $iCopies      0x01;                 // Number of copies
  1801.  
  1802.         $fLeftToRight 0x0;                     // Print over then down
  1803.  
  1804.         // Page orientation
  1805.         $fLandscape ($this->_phpSheet->getPageSetup()->getOrientation(== PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE?
  1806.             0x0 0x1;
  1807.  
  1808.         $fNoPls       0x0;                     // Setup not read from printer
  1809.         $fNoColor     0x0;                     // Print black and white
  1810.         $fDraft       0x0;                     // Print draft quality
  1811.         $fNotes       0x0;                     // Print notes
  1812.         $fNoOrient    0x0;                     // Orientation not set
  1813.         $fUsePage     0x0;                     // Use custom starting page
  1814.  
  1815.         $grbit           $fLeftToRight;
  1816.         $grbit          |= $fLandscape    << 1;
  1817.         $grbit          |= $fNoPls        << 2;
  1818.         $grbit          |= $fNoColor      << 3;
  1819.         $grbit          |= $fDraft        << 4;
  1820.         $grbit          |= $fNotes        << 5;
  1821.         $grbit          |= $fNoOrient     << 6;
  1822.         $grbit          |= $fUsePage      << 7;
  1823.  
  1824.         $numHdr pack("d"$numHdr);
  1825.         $numFtr pack("d"$numFtr);
  1826.         if (PHPExcel_Writer_Excel5_BIFFwriter::getByteOrder()) // if it's Big Endian
  1827.             $numHdr strrev($numHdr);
  1828.             $numFtr strrev($numFtr);
  1829.         }
  1830.  
  1831.         $header pack("vv"$record$length);
  1832.         $data1  pack("vvvvvvvv"$iPaperSize,
  1833.                                    $iScale,
  1834.                                    $iPageStart,
  1835.                                    $iFitWidth,
  1836.                                    $iFitHeight,
  1837.                                    $grbit,
  1838.                                    $iRes,
  1839.                                    $iVRes);
  1840.         $data2  $numHdr.$numFtr;
  1841.         $data3  pack("v"$iCopies);
  1842.         $this->_append($header $data1 $data2 $data3);
  1843.     }
  1844.  
  1845.     /**
  1846.      * Store the header caption BIFF record.
  1847.      */
  1848.     private function _writeHeader()
  1849.     {
  1850.         $record  0x0014;               // Record identifier
  1851.  
  1852.         /* removing for now
  1853.         // need to fix character count (multibyte!)
  1854.         if (strlen($this->_phpSheet->getHeaderFooter()->getOddHeader()) <= 255) {
  1855.             $str      = $this->_phpSheet->getHeaderFooter()->getOddHeader();       // header string
  1856.         } else {
  1857.             $str = '';
  1858.         }
  1859.         */
  1860.  
  1861.         if ($this->_BIFF_version == 0x0600{
  1862.             $recordData PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddHeader());
  1863.             $length strlen($recordData);
  1864.         else {
  1865.             $cch      strlen($this->_phpSheet->getHeaderFooter()->getOddHeader());         // Length of header string
  1866.             $length  $cch;             // Bytes to follow
  1867.             $data      pack("C",  $cch);
  1868.             $recordData $data $this->_phpSheet->getHeaderFooter()->getOddHeader();
  1869.         }
  1870.  
  1871.         $header   pack("vv"$record$length);
  1872.  
  1873.         $this->_append($header $recordData);
  1874.     }
  1875.  
  1876.     /**
  1877.      * Store the footer caption BIFF record.
  1878.      */
  1879.     private function _writeFooter()
  1880.     {
  1881.         $record  0x0015;               // Record identifier
  1882.  
  1883.         /* removing for now
  1884.         // need to fix character count (multibyte!)
  1885.         if (strlen($this->_phpSheet->getHeaderFooter()->getOddFooter()) <= 255) {
  1886.             $str = $this->_phpSheet->getHeaderFooter()->getOddFooter();
  1887.         } else {
  1888.             $str = '';
  1889.         }
  1890.         */
  1891.  
  1892.         if ($this->_BIFF_version == 0x0600{
  1893.             $recordData PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddFooter());
  1894.             $length strlen($recordData);
  1895.         else {
  1896.             $cch      strlen($this->_phpSheet->getHeaderFooter()->getOddFooter());         // Length of footer string
  1897.             $length  $cch;
  1898.             $data      pack("C",  $cch);
  1899.             $recordData $data $this->_phpSheet->getHeaderFooter()->getOddFooter();
  1900.         }
  1901.  
  1902.         $header    pack("vv"$record$length);
  1903.  
  1904.         $this->_append($header $recordData);
  1905.     }
  1906.  
  1907.     /**
  1908.      * Store the horizontal centering HCENTER BIFF record.
  1909.      *
  1910.      * @access private
  1911.      */
  1912.     private function _writeHcenter()
  1913.     {
  1914.         $record   0x0083;              // Record identifier
  1915.         $length   0x0002;              // Bytes to follow
  1916.  
  1917.         $fHCenter $this->_phpSheet->getPageSetup()->getHorizontalCentered(0;     // Horizontal centering
  1918.  
  1919.         $header    pack("vv"$record$length);
  1920.         $data      pack("v",  $fHCenter);
  1921.  
  1922.         $this->_append($header.$data);
  1923.     }
  1924.  
  1925.     /**
  1926.      * Store the vertical centering VCENTER BIFF record.
  1927.      */
  1928.     private function _writeVcenter()
  1929.     {
  1930.         $record   0x0084;              // Record identifier
  1931.         $length   0x0002;              // Bytes to follow
  1932.  
  1933.         $fVCenter $this->_phpSheet->getPageSetup()->getVerticalCentered(0;     // Horizontal centering
  1934.  
  1935.         $header    pack("vv"$record$length);
  1936.         $data      pack("v",  $fVCenter);
  1937.         $this->_append($header $data);
  1938.     }
  1939.  
  1940.     /**
  1941.      * Store the LEFTMARGIN BIFF record.
  1942.      */
  1943.     private function _writeMarginLeft()
  1944.     {
  1945.         $record  0x0026;                   // Record identifier
  1946.         $length  0x0008;                   // Bytes to follow
  1947.  
  1948.         $margin  $this->_phpSheet->getPageMargins()->getLeft();     // Margin in inches
  1949.  
  1950.         $header    pack("vv",  $record$length);
  1951.         $data      pack("d",   $margin);
  1952.         if (PHPExcel_Writer_Excel5_BIFFwriter::getByteOrder()) // if it's Big Endian
  1953.             $data strrev($data);
  1954.         }
  1955.  
  1956.         $this->_append($header $data);
  1957.     }
  1958.  
  1959.     /**
  1960.      * Store the RIGHTMARGIN BIFF record.
  1961.      */
  1962.     private function _writeMarginRight()
  1963.     {
  1964.         $record  0x0027;                   // Record identifier
  1965.         $length  0x0008;                   // Bytes to follow
  1966.  
  1967.         $margin  $this->_phpSheet->getPageMargins()->getRight();     // Margin in inches
  1968.  
  1969.         $header    pack("vv",  $record$length);
  1970.         $data      pack("d",   $margin);
  1971.         if (PHPExcel_Writer_Excel5_BIFFwriter::getByteOrder()) // if it's Big Endian
  1972.             $data strrev($data);
  1973.         }
  1974.  
  1975.         $this->_append($header $data);
  1976.     }
  1977.  
  1978.     /**
  1979.      * Store the TOPMARGIN BIFF record.
  1980.      */
  1981.     private function _writeMarginTop()
  1982.     {
  1983.         $record  0x0028;                   // Record identifier
  1984.         $length  0x0008;                   // Bytes to follow
  1985.  
  1986.         $margin  $this->_phpSheet->getPageMargins()->getTop();     // Margin in inches
  1987.  
  1988.         $header    pack("vv",  $record$length);
  1989.         $data      pack("d",   $margin);
  1990.         if (PHPExcel_Writer_Excel5_BIFFwriter::getByteOrder()) // if it's Big Endian
  1991.             $data strrev($data);
  1992.         }
  1993.  
  1994.         $this->_append($header $data);
  1995.     }
  1996.  
  1997.     /**
  1998.      * Store the BOTTOMMARGIN BIFF record.
  1999.      */
  2000.     private function _writeMarginBottom()
  2001.     {
  2002.         $record  0x0029;                   // Record identifier
  2003.         $length  0x0008;                   // Bytes to follow
  2004.  
  2005.         $margin  $this->_phpSheet->getPageMargins()->getBottom();     // Margin in inches
  2006.  
  2007.         $header    pack("vv",  $record$length);
  2008.         $data      pack("d",   $margin);
  2009.         if (PHPExcel_Writer_Excel5_BIFFwriter::getByteOrder()) // if it's Big Endian
  2010.             $data strrev($data);
  2011.         }
  2012.  
  2013.         $this->_append($header $data);
  2014.     }
  2015.  
  2016.     /**
  2017.      * Write the PRINTHEADERS BIFF record.
  2018.      */
  2019.     private function _writePrintHeaders()
  2020.     {
  2021.         $record      0x002a;                   // Record identifier
  2022.         $length      0x0002;                   // Bytes to follow
  2023.  
  2024.         $fPrintRwCol $this->_print_headers;     // Boolean flag
  2025.  
  2026.         $header      pack("vv"$record$length);
  2027.         $data        pack("v"$fPrintRwCol);
  2028.         $this->_append($header $data);
  2029.     }
  2030.  
  2031.     /**
  2032.      * Write the PRINTGRIDLINES BIFF record. Must be used in conjunction with the
  2033.      * GRIDSET record.
  2034.      */
  2035.     private function _writePrintGridlines()
  2036.     {
  2037.         $record      0x002b;                    // Record identifier
  2038.         $length      0x0002;                    // Bytes to follow
  2039.  
  2040.         $fPrintGrid  $this->_phpSheet->getPrintGridlines(0;    // Boolean flag
  2041.  
  2042.         $header      pack("vv"$record$length);
  2043.         $data        pack("v"$fPrintGrid);
  2044.         $this->_append($header $data);
  2045.     }
  2046.  
  2047.     /**
  2048.      * Write the GRIDSET BIFF record. Must be used in conjunction with the
  2049.      * PRINTGRIDLINES record.
  2050.      */
  2051.     private function _writeGridset()
  2052.     {
  2053.         $record      0x0082;                        // Record identifier
  2054.         $length      0x0002;                        // Bytes to follow
  2055.  
  2056.         $fGridSet    !$this->_phpSheet->getPrintGridlines();     // Boolean flag
  2057.  
  2058.         $header      pack("vv",  $record$length);
  2059.         $data        pack("v",   $fGridSet);
  2060.         $this->_append($header $data);
  2061.     }
  2062.  
  2063.     /**
  2064.      * Write the GUTS BIFF record. This is used to configure the gutter margins
  2065.      * where Excel outline symbols are displayed. The visibility of the gutters is
  2066.      * controlled by a flag in WSBOOL.
  2067.      *
  2068.      * @see _writeWsbool()
  2069.      */
  2070.     private  function _writeGuts()
  2071.     {
  2072.         $record      0x0080;   // Record identifier
  2073.         $length      0x0008;   // Bytes to follow
  2074.  
  2075.         $dxRwGut     0x0000;   // Size of row gutter
  2076.         $dxColGut    0x0000;   // Size of col gutter
  2077.  
  2078.         // determine maximum row outline level
  2079.         $maxRowOutlineLevel 0;
  2080.         foreach ($this->_phpSheet->getRowDimensions(as $rowDimension{
  2081.             $maxRowOutlineLevel max($maxRowOutlineLevel$rowDimension->getOutlineLevel());
  2082.         }
  2083.  
  2084.         $col_level   0;
  2085.  
  2086.         // Calculate the maximum column outline level. The equivalent calculation
  2087.         // for the row outline level is carried out in _writeRow().
  2088.         $colcount count($this->_colinfo);
  2089.         for ($i 0$i $colcount++$i{
  2090.             $col_level max($this->_colinfo[$i][5]$col_level);
  2091.         }
  2092.  
  2093.         // Set the limits for the outline levels (0 <= x <= 7).
  2094.         $col_level max(0min($col_level7));
  2095.  
  2096.         // The displayed level is one greater than the max outline levels
  2097.         if ($maxRowOutlineLevel{
  2098.             ++$maxRowOutlineLevel;
  2099.         }
  2100.         if ($col_level{
  2101.             ++$col_level;
  2102.         }
  2103.  
  2104.         $header      pack("vv",   $record$length);
  2105.         $data        pack("vvvv"$dxRwGut$dxColGut$maxRowOutlineLevel$col_level);
  2106.  
  2107.         $this->_append($header.$data);
  2108.     }
  2109.  
  2110.  
  2111.     /**
  2112.      * Write the WSBOOL BIFF record, mainly for fit-to-page. Used in conjunction
  2113.      * with the SETUP record.
  2114.      */
  2115.     private function _writeWsbool()
  2116.     {
  2117.         $record      0x0081;   // Record identifier
  2118.         $length      0x0002;   // Bytes to follow
  2119.         $grbit       0x0000;
  2120.  
  2121.         // The only option that is of interest is the flag for fit to page. So we
  2122.         // set all the options in one go.
  2123.         //
  2124.         // Set the option flags
  2125.         $grbit |= 0x0001;                           // Auto page breaks visible
  2126.         if ($this->_outline_style{
  2127.             $grbit |= 0x0020// Auto outline styles
  2128.         }
  2129.         if ($this->_phpSheet->getShowSummaryBelow()) {
  2130.             $grbit |= 0x0040// Outline summary below
  2131.         }
  2132.         if ($this->_phpSheet->getShowSummaryRight()) {
  2133.             $grbit |= 0x0080// Outline summary right
  2134.         }
  2135.         if ($this->_phpSheet->getPageSetup()->getFitToPage()) {
  2136.             $grbit |= 0x0100// Page setup fit to page
  2137.         }
  2138.         if ($this->_outline_on{
  2139.             $grbit |= 0x0400// Outline symbols displayed
  2140.         }
  2141.  
  2142.         $header      pack("vv"$record$length);
  2143.         $data        pack("v",  $grbit);
  2144.         $this->_append($header $data);
  2145.     }
  2146.  
  2147.     /**
  2148.      * Write the HORIZONTALPAGEBREAKS and VERTICALPAGEBREAKS BIFF records.
  2149.      */
  2150.     private function _writeBreaks()
  2151.     {
  2152.         // initialize
  2153.         $vbreaks array();
  2154.         $hbreaks array();
  2155.  
  2156.         foreach ($this->_phpSheet->getBreaks(as $cell => $breakType{
  2157.             // Fetch coordinates
  2158.             $coordinates PHPExcel_Cell::coordinateFromString($cell);
  2159.  
  2160.             // Decide what to do by the type of break
  2161.             switch ($breakType{
  2162.                 case PHPExcel_Worksheet::BREAK_COLUMN:
  2163.                     // Add to list of vertical breaks
  2164.                     $vbreaks[PHPExcel_Cell::columnIndexFromString($coordinates[0]1;
  2165.                     break;
  2166.  
  2167.                 case PHPExcel_Worksheet::BREAK_ROW:
  2168.                     // Add to list of horizontal breaks
  2169.                     $hbreaks[$coordinates[1];
  2170.                     break;
  2171.  
  2172.                 case PHPExcel_Worksheet::BREAK_NONE:
  2173.                 default:
  2174.                     // Nothing to do
  2175.                     break;
  2176.             }
  2177.         }
  2178.  
  2179.         //horizontal page breaks
  2180.         if (count($hbreaks0{
  2181.  
  2182.             // Sort and filter array of page breaks
  2183.             sort($hbreaksSORT_NUMERIC);
  2184.             if ($hbreaks[0== 0// don't use first break if it's 0
  2185.                 array_shift($hbreaks);
  2186.             }
  2187.  
  2188.             $record  0x001b;               // Record identifier
  2189.             $cbrk    count($hbreaks);       // Number of page breaks
  2190.             if ($this->_BIFF_version == 0x0600{
  2191.                 $length  $cbrk;      // Bytes to follow
  2192.             else {
  2193.                 $length  $cbrk;      // Bytes to follow
  2194.             }
  2195.  
  2196.             $header  pack("vv"$record$length);
  2197.             $data    pack("v",  $cbrk);
  2198.  
  2199.             // Append each page break
  2200.             foreach ($hbreaks as $hbreak{
  2201.                 if ($this->_BIFF_version == 0x0600{
  2202.                     $data .= pack("vvv"$hbreak0x00000x00ff);
  2203.                 else {
  2204.                     $data .= pack("v"$hbreak);
  2205.                 }
  2206.             }
  2207.  
  2208.             $this->_append($header $data);
  2209.         }
  2210.  
  2211.         // vertical page breaks
  2212.         if (count($vbreaks0{
  2213.  
  2214.             // 1000 vertical pagebreaks appears to be an internal Excel 5 limit.
  2215.             // It is slightly higher in Excel 97/200, approx. 1026
  2216.             $vbreaks array_slice($vbreaks01000);
  2217.  
  2218.             // Sort and filter array of page breaks
  2219.             sort($vbreaksSORT_NUMERIC);
  2220.             if ($vbreaks[0== 0// don't use first break if it's 0
  2221.                 array_shift($vbreaks);
  2222.             }
  2223.  
  2224.             $record  0x001a;               // Record identifier
  2225.             $cbrk    count($vbreaks);       // Number of page breaks
  2226.             if ($this->_BIFF_version == 0x0600{
  2227.                 $length  $cbrk;      // Bytes to follow
  2228.             else {
  2229.                 $length  $cbrk;      // Bytes to follow
  2230.             }
  2231.  
  2232.             $header  pack("vv",  $record$length);
  2233.             $data    pack("v",   $cbrk);
  2234.  
  2235.             // Append each page break
  2236.             foreach ($vbreaks as $vbreak{
  2237.                 if ($this->_BIFF_version == 0x0600{
  2238.                     $data .= pack("vvv"$vbreak0x00000xffff);
  2239.                 else {
  2240.                     $data .= pack("v"$vbreak);
  2241.                 }
  2242.             }
  2243.  
  2244.             $this->_append($header $data);
  2245.         }
  2246.     }
  2247.  
  2248.     /**
  2249.      * Set the Biff PROTECT record to indicate that the worksheet is protected.
  2250.      */
  2251.     private function _writeProtect()
  2252.     {
  2253.         // Exit unless sheet protection has been specified
  2254.         if (!$this->_phpSheet->getProtection()->getSheet()) {
  2255.             return;
  2256.         }
  2257.  
  2258.         $record      0x0012;             // Record identifier
  2259.         $length      0x0002;             // Bytes to follow
  2260.  
  2261.         $fLock       1;    // Worksheet is protected
  2262.  
  2263.         $header      pack("vv"$record$length);
  2264.         $data        pack("v",  $fLock);
  2265.  
  2266.         $this->_append($header.$data);
  2267.     }
  2268.  
  2269.     /**
  2270.      * Write SCENPROTECT
  2271.      */
  2272.     private function _writeScenProtect()
  2273.     {
  2274.         // Exit if sheet protection is not active
  2275.         if (!$this->_phpSheet->getProtection()->getSheet()) {
  2276.             return;
  2277.         }
  2278.  
  2279.         // Exit if scenarios are not protected
  2280.         if (!$this->_phpSheet->getProtection()->getScenarios()) {
  2281.             return;
  2282.         }
  2283.  
  2284.         $record 0x00DD// Record identifier
  2285.         $length 0x0002// Bytes to follow
  2286.  
  2287.         $header pack('vv'$record$length);
  2288.         $data pack('v'1);
  2289.  
  2290.         $this->_append($header $data);
  2291.     }
  2292.  
  2293.     /**
  2294.      * Write OBJECTPROTECT
  2295.      */
  2296.     private function _writeObjectProtect()
  2297.     {
  2298.         // Exit if sheet protection is not active
  2299.         if (!$this->_phpSheet->getProtection()->getSheet()) {
  2300.             return;
  2301.         }
  2302.  
  2303.         // Exit if objects are not protected
  2304.         if (!$this->_phpSheet->getProtection()->getObjects()) {
  2305.             return;
  2306.         }
  2307.  
  2308.         $record 0x0063// Record identifier
  2309.         $length 0x0002// Bytes to follow
  2310.  
  2311.         $header pack('vv'$record$length);
  2312.         $data pack('v'1);
  2313.  
  2314.         $this->_append($header $data);
  2315.     }
  2316.  
  2317.     /**
  2318.      * Write the worksheet PASSWORD record.
  2319.      */
  2320.     private function _writePassword()
  2321.     {
  2322.         // Exit unless sheet protection and password have been specified
  2323.         if (!$this->_phpSheet->getProtection()->getSheet(|| !$this->_phpSheet->getProtection()->getPassword()) {
  2324.             return;
  2325.         }
  2326.  
  2327.         $record      0x0013;               // Record identifier
  2328.         $length      0x0002;               // Bytes to follow
  2329.  
  2330.         $wPassword   hexdec($this->_phpSheet->getProtection()->getPassword());     // Encoded password
  2331.  
  2332.         $header      pack("vv"$record$length);
  2333.         $data        pack("v",  $wPassword);
  2334.  
  2335.         $this->_append($header $data);
  2336.     }
  2337.  
  2338.  
  2339.     /**
  2340.      * Insert a 24bit bitmap image in a worksheet.
  2341.      *
  2342.      * @access public
  2343.      * @param integer $row     The row we are going to insert the bitmap into
  2344.      * @param integer $col     The column we are going to insert the bitmap into
  2345.      * @param mixed   $bitmap  The bitmap filename or GD-image resource
  2346.      * @param integer $x       The horizontal position (offset) of the image inside the cell.
  2347.      * @param integer $y       The vertical position (offset) of the image inside the cell.
  2348.      * @param float   $scale_x The horizontal scale
  2349.      * @param float   $scale_y The vertical scale
  2350.      */
  2351.     function insertBitmap($row$col$bitmap$x 0$y 0$scale_x 1$scale_y 1)
  2352.     {
  2353.         $bitmap_array (is_resource($bitmap$this->_processBitmapGd($bitmap$this->_processBitmap($bitmap));
  2354.         list($width$height$size$data$bitmap_array//$this->_processBitmap($bitmap);
  2355.  
  2356.         // Scale the frame of the image.
  2357.         $width  *= $scale_x;
  2358.         $height *= $scale_y;
  2359.  
  2360.         // Calculate the vertices of the image and write the OBJ record
  2361.         $this->_positionImage($col$row$x$y$width$height);
  2362.  
  2363.         // Write the IMDATA record to store the bitmap data
  2364.         $record      0x007f;
  2365.         $length      $size;
  2366.         $cf          0x09;
  2367.         $env         0x01;
  2368.         $lcb         $size;
  2369.  
  2370.         $header      pack("vvvvV"$record$length$cf$env$lcb);
  2371.         $this->_append($header.$data);
  2372.     }
  2373.  
  2374.     /**
  2375.      * Calculate the vertices that define the position of the image as required by
  2376.      * the OBJ record.
  2377.      *
  2378.      *         +------------+------------+
  2379.      *         |     A      |      B     |
  2380.      *   +-----+------------+------------+
  2381.      *   |     |(x1,y1)     |            |
  2382.      *   |  1  |(A1)._______|______      |
  2383.      *   |     |    |              |     |
  2384.      *   |     |    |              |     |
  2385.      *   +-----+----|    BITMAP    |-----+
  2386.      *   |     |    |              |     |
  2387.      *   |  2  |    |______________.     |
  2388.      *   |     |            |        (B2)|
  2389.      *   |     |            |     (x2,y2)|
  2390.      *   +---- +------------+------------+
  2391.      *
  2392.      * Example of a bitmap that covers some of the area from cell A1 to cell B2.
  2393.      *
  2394.      * Based on the width and height of the bitmap we need to calculate 8 vars:
  2395.      *     $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2.
  2396.      * The width and height of the cells are also variable and have to be taken into
  2397.      * account.
  2398.      * The values of $col_start and $row_start are passed in from the calling
  2399.      * function. The values of $col_end and $row_end are calculated by subtracting
  2400.      * the width and height of the bitmap from the width and height of the
  2401.      * underlying cells.
  2402.      * The vertices are expressed as a percentage of the underlying cell width as
  2403.      * follows (rhs values are in pixels):
  2404.      *
  2405.      *       x1 = X / W *1024
  2406.      *       y1 = Y / H *256
  2407.      *       x2 = (X-1) / W *1024
  2408.      *       y2 = (Y-1) / H *256
  2409.      *
  2410.      *       Where:  X is distance from the left side of the underlying cell
  2411.      *               Y is distance from the top of the underlying cell
  2412.      *               W is the width of the cell
  2413.      *               H is the height of the cell
  2414.      * The SDK incorrectly states that the height should be expressed as a
  2415.      *        percentage of 1024.
  2416.      *
  2417.      * @access private
  2418.      * @param integer $col_start Col containing upper left corner of object
  2419.      * @param integer $row_start Row containing top left corner of object
  2420.      * @param integer $x1        Distance to left side of object
  2421.      * @param integer $y1        Distance to top of object
  2422.      * @param integer $width     Width of image frame
  2423.      * @param integer $height    Height of image frame
  2424.      */
  2425.     function _positionImage($col_start$row_start$x1$y1$width$height)
  2426.     {
  2427.         // Initialise end cell to the same as the start cell
  2428.         $col_end    $col_start;  // Col containing lower right corner of object
  2429.         $row_end    $row_start;  // Row containing bottom right corner of object
  2430.  
  2431.         // Zero the specified offset if greater than the cell dimensions
  2432.         if ($x1 >= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_start))) {
  2433.             $x1 0;
  2434.         }
  2435.         if ($y1 >= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_start 1)) {
  2436.             $y1 0;
  2437.         }
  2438.  
  2439.         $width      $width  $x1 -1;
  2440.         $height     $height $y1 -1;
  2441.  
  2442.         // Subtract the underlying cell widths to find the end cell of the image
  2443.         while ($width >= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_end))) {
  2444.             $width -= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_end));
  2445.             ++$col_end;
  2446.         }
  2447.  
  2448.         // Subtract the underlying cell heights to find the end cell of the image
  2449.         while ($height >= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_end 1)) {
  2450.             $height -= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_end 1);
  2451.             ++$row_end;
  2452.         }
  2453.  
  2454.         // Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell
  2455.         // with zero eight or width.
  2456.         //
  2457.         if (PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_start)) == 0{
  2458.             return;
  2459.         }
  2460.         if (PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_end))   == 0{
  2461.             return;
  2462.         }
  2463.         if (PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_start 1== 0{
  2464.             return;
  2465.         }
  2466.         if (PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_end 1)   == 0{
  2467.             return;
  2468.         }
  2469.  
  2470.         // Convert the pixel values to the percentage value expected by Excel
  2471.         $x1 $x1     PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_start))   1024;
  2472.         $y1 $y1     PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_start 1)   *  256;
  2473.         $x2 $width  PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_end))     1024// Distance to right side of object
  2474.         $y2 $height PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_end 1)     *  256// Distance to bottom of object
  2475.  
  2476.         $this->_writeObjPicture($col_start$x1,
  2477.                                  $row_start$y1,
  2478.                                  $col_end$x2,
  2479.                                  $row_end$y2);
  2480.     }
  2481.  
  2482.     /**
  2483.      * Store the OBJ record that precedes an IMDATA record. This could be generalise
  2484.      * to support other Excel objects.
  2485.      *
  2486.      * @param integer $colL Column containing upper left corner of object
  2487.      * @param integer $dxL  Distance from left side of cell
  2488.      * @param integer $rwT  Row containing top left corner of object
  2489.      * @param integer $dyT  Distance from top of cell
  2490.      * @param integer $colR Column containing lower right corner of object
  2491.      * @param integer $dxR  Distance from right of cell
  2492.      * @param integer $rwB  Row containing bottom right corner of object
  2493.      * @param integer $dyB  Distance from bottom of cell
  2494.      */
  2495.     private function _writeObjPicture($colL,$dxL,$rwT,$dyT,$colR,$dxR,$rwB,$dyB)
  2496.     {
  2497.         $record      0x005d;   // Record identifier
  2498.         $length      0x003c;   // Bytes to follow
  2499.  
  2500.         $cObj        0x0001;   // Count of objects in file (set to 1)
  2501.         $OT          0x0008;   // Object type. 8 = Picture
  2502.         $id          0x0001;   // Object ID
  2503.         $grbit       0x0614;   // Option flags
  2504.  
  2505.         $cbMacro     0x0000;   // Length of FMLA structure
  2506.         $Reserved1   0x0000;   // Reserved
  2507.         $Reserved2   0x0000;   // Reserved
  2508.  
  2509.         $icvBack     0x09;     // Background colour
  2510.         $icvFore     0x09;     // Foreground colour
  2511.         $fls         0x00;     // Fill pattern
  2512.         $fAuto       0x00;     // Automatic fill
  2513.         $icv         0x08;     // Line colour
  2514.         $lns         0xff;     // Line style
  2515.         $lnw         0x01;     // Line weight
  2516.         $fAutoB      0x00;     // Automatic border
  2517.         $frs         0x0000;   // Frame style
  2518.         $cf          0x0009;   // Image format, 9 = bitmap
  2519.         $Reserved3   0x0000;   // Reserved
  2520.         $cbPictFmla  0x0000;   // Length of FMLA structure
  2521.         $Reserved4   0x0000;   // Reserved
  2522.         $grbit2      0x0001;   // Option flags
  2523.         $Reserved5   0x0000;   // Reserved
  2524.  
  2525.  
  2526.         $header      pack("vv"$record$length);
  2527.         $data        pack("V"$cObj);
  2528.         $data       .= pack("v"$OT);
  2529.         $data       .= pack("v"$id);
  2530.         $data       .= pack("v"$grbit);
  2531.         $data       .= pack("v"$colL);
  2532.         $data       .= pack("v"$dxL);
  2533.         $data       .= pack("v"$rwT);
  2534.         $data       .= pack("v"$dyT);
  2535.         $data       .= pack("v"$colR);
  2536.         $data       .= pack("v"$dxR);
  2537.         $data       .= pack("v"$rwB);
  2538.         $data       .= pack("v"$dyB);
  2539.         $data       .= pack("v"$cbMacro);
  2540.         $data       .= pack("V"$Reserved1);
  2541.         $data       .= pack("v"$Reserved2);
  2542.         $data       .= pack("C"$icvBack);
  2543.         $data       .= pack("C"$icvFore);
  2544.         $data       .= pack("C"$fls);
  2545.         $data       .= pack("C"$fAuto);
  2546.         $data       .= pack("C"$icv);
  2547.         $data       .= pack("C"$lns);
  2548.         $data       .= pack("C"$lnw);
  2549.         $data       .= pack("C"$fAutoB);
  2550.         $data       .= pack("v"$frs);
  2551.         $data       .= pack("V"$cf);
  2552.         $data       .= pack("v"$Reserved3);
  2553.         $data       .= pack("v"$cbPictFmla);
  2554.         $data       .= pack("v"$Reserved4);
  2555.         $data       .= pack("v"$grbit2);
  2556.         $data       .= pack("V"$Reserved5);
  2557.  
  2558.         $this->_append($header $data);
  2559.     }
  2560.  
  2561.     /**
  2562.      * Convert a GD-image into the internal format.
  2563.      *
  2564.      * @access private
  2565.      * @param resource $image The image to process
  2566.      * @return array Array with data and properties of the bitmap
  2567.      */
  2568.     function _processBitmapGd($image{
  2569.         $width imagesx($image);
  2570.         $height imagesy($image);
  2571.  
  2572.         $data pack("Vvvvv"0x000c$width$height0x010x18);
  2573.         for ($j=$height$j--{
  2574.             for ($i=0$i $width++$i{
  2575.                 $color imagecolorsforindex($imageimagecolorat($image$i$j));
  2576.                 foreach (array("red""green""blue"as $key{
  2577.                     $color[$key$color[$keyround((255 $color[$key]$color["alpha"127);
  2578.                 }
  2579.                 $data .= chr($color["blue"]chr($color["green"]chr($color["red"]);
  2580.             }
  2581.             if (3*$width 4{
  2582.                 $data .= str_repeat("\x00"3*$width 4);
  2583.             }
  2584.         }
  2585.  
  2586.         return array($width$heightstrlen($data)$data);
  2587.     }
  2588.  
  2589.     /**
  2590.      * Convert a 24 bit bitmap into the modified internal format used by Windows.
  2591.      * This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the
  2592.      * MSDN library.
  2593.      *
  2594.      * @access private
  2595.      * @param string $bitmap The bitmap to process
  2596.      * @return array Array with data and properties of the bitmap
  2597.      */
  2598.     function _processBitmap($bitmap)
  2599.     {
  2600.         // Open file.
  2601.         $bmp_fd @fopen($bitmap,"rb");
  2602.         if (!$bmp_fd{
  2603.             throw new Exception("Couldn't import $bitmap");
  2604.         }
  2605.  
  2606.         // Slurp the file into a string.
  2607.         $data fread($bmp_fdfilesize($bitmap));
  2608.  
  2609.         // Check that the file is big enough to be a bitmap.
  2610.         if (strlen($data<= 0x36{
  2611.             throw new Exception("$bitmap doesn't contain enough data.\n");
  2612.         }
  2613.  
  2614.         // The first 2 bytes are used to identify the bitmap.
  2615.         $identity unpack("A2ident"$data);
  2616.         if ($identity['ident'!= "BM"{
  2617.             throw new Exception("$bitmap doesn't appear to be a valid bitmap image.\n");
  2618.         }
  2619.  
  2620.         // Remove bitmap data: ID.
  2621.         $data substr($data2);
  2622.  
  2623.         // Read and remove the bitmap size. This is more reliable than reading
  2624.         // the data size at offset 0x22.
  2625.         //
  2626.         $size_array   unpack("Vsa"substr($data04));
  2627.         $size   $size_array['sa'];
  2628.         $data   substr($data4);
  2629.         $size  -= 0x36// Subtract size of bitmap header.
  2630.         $size  += 0x0C// Add size of BIFF header.
  2631.  
  2632.         // Remove bitmap data: reserved, offset, header length.
  2633.         $data substr($data12);
  2634.  
  2635.         // Read and remove the bitmap width and height. Verify the sizes.
  2636.         $width_and_height unpack("V2"substr($data08));
  2637.         $width  $width_and_height[1];
  2638.         $height $width_and_height[2];
  2639.         $data   substr($data8);
  2640.         if ($width 0xFFFF{
  2641.             throw new Exception("$bitmap: largest image width supported is 65k.\n");
  2642.         }
  2643.         if ($height 0xFFFF{
  2644.             throw new Exception("$bitmap: largest image height supported is 65k.\n");
  2645.         }
  2646.  
  2647.         // Read and remove the bitmap planes and bpp data. Verify them.
  2648.         $planes_and_bitcount unpack("v2"substr($data04));
  2649.         $data substr($data4);
  2650.         if ($planes_and_bitcount[2!= 24// Bitcount
  2651.             throw new Exception("$bitmap isn't a 24bit true color bitmap.\n");
  2652.         }
  2653.         if ($planes_and_bitcount[1!= 1{
  2654.             throw new Exception("$bitmap: only 1 plane supported in bitmap image.\n");
  2655.         }
  2656.  
  2657.         // Read and remove the bitmap compression. Verify compression.
  2658.         $compression unpack("Vcomp"substr($data04));
  2659.         $data substr($data4);
  2660.  
  2661.         //$compression = 0;
  2662.         if ($compression['comp'!= 0{
  2663.             throw new Exception("$bitmap: compression not supported in bitmap image.\n");
  2664.         }
  2665.  
  2666.         // Remove bitmap data: data size, hres, vres, colours, imp. colours.
  2667.         $data substr($data20);
  2668.  
  2669.         // Add the BITMAPCOREHEADER data
  2670.         $header  pack("Vvvvv"0x000c$width$height0x010x18);
  2671.         $data    $header $data;
  2672.  
  2673.         return (array($width$height$size$data));
  2674.     }
  2675.  
  2676.     /**
  2677.      * Store the window zoom factor. This should be a reduced fraction but for
  2678.      * simplicity we will store all fractions with a numerator of 100.
  2679.      */
  2680.     private function _writeZoom()
  2681.     {
  2682.         // If scale is 100 we don't need to write a record
  2683.         if ($this->_phpSheet->getSheetView()->getZoomScale(== 100{
  2684.             return;
  2685.         }
  2686.  
  2687.         $record      0x00A0;               // Record identifier
  2688.         $length      0x0004;               // Bytes to follow
  2689.  
  2690.         $header      pack("vv"$record$length);
  2691.         $data        pack("vv"$this->_phpSheet->getSheetView()->getZoomScale()100);
  2692.         $this->_append($header $data);
  2693.     }
  2694.  
  2695.     /**
  2696.      * Write MSODRAWING record
  2697.      */
  2698.     private function _writeMsoDrawing()
  2699.     {
  2700.         // check if there are any shapes for this sheet
  2701.         if (count($this->_phpSheet->getDrawingCollection()) == 0{
  2702.             return;
  2703.         }
  2704.  
  2705.         // create intermediate Escher object
  2706.         $escher new PHPExcel_Shared_Escher();
  2707.  
  2708.         // dgContainer
  2709.         $dgContainer new PHPExcel_Shared_Escher_DgContainer();
  2710.  
  2711.         // set the drawing index (we use sheet index + 1)
  2712.         $dgContainer->setDgId($this->_phpSheet->getParent()->getIndex($this->_phpSheet1);
  2713.         $escher->setDgContainer($dgContainer);
  2714.  
  2715.         // spgrContainer
  2716.         $spgrContainer new PHPExcel_Shared_Escher_DgContainer_SpgrContainer();
  2717.         $dgContainer->setSpgrContainer($spgrContainer);
  2718.  
  2719.         // add one shape which is the group shape
  2720.         $spContainer new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();
  2721.         $spContainer->setSpgr(true);
  2722.         $spContainer->setSpType(0);
  2723.         $spContainer->setSpId(($this->_phpSheet->getParent()->getIndex($this->_phpSheet1<< 10);
  2724.         $spgrContainer->addChild($spContainer);
  2725.  
  2726.         // add the shapes
  2727.  
  2728.         // outer loop is for determining BSE index
  2729.         $blipIndex 0// 1-based index to BstoreContainer
  2730.  
  2731.         $countShapes 0// count number of shapes (minus group shape), in this sheet
  2732.  
  2733.         foreach ($this->_phpSheet->getParent()->getAllsheets(as $sheet{
  2734.             foreach ($sheet->getDrawingCollection(as $drawing{
  2735.                 ++$blipIndex;
  2736.  
  2737.                 if ($sheet === $this->_phpSheet{
  2738.                     ++$countShapes;
  2739.  
  2740.                     // add the shape
  2741.                     $spContainer new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();
  2742.  
  2743.                     // set the shape type
  2744.                     $spContainer->setSpType(0x004B);
  2745.  
  2746.                     // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
  2747.                     $spId $countShapes
  2748.                         | ($this->_phpSheet->getParent()->getIndex($this->_phpSheet1<< 10;
  2749.                     $spContainer->setSpId($spId);
  2750.  
  2751.                     // keep track of last spId
  2752.                     $lastSpId $spId;
  2753.  
  2754.                     // set the BLIP index
  2755.                     $spContainer->setOPT(0x4104$blipIndex);
  2756.  
  2757.                     // set coordinates and offsets, client anchor
  2758.                     $coordinates $drawing->getCoordinates();
  2759.                     $offsetX $drawing->getOffsetX();
  2760.                     $offsetY $drawing->getOffsetY();
  2761.                     $width $drawing->getWidth();
  2762.                     $height $drawing->getHeight();
  2763.  
  2764.                     $twoAnchor PHPExcel_Shared_Excel5::oneAnchor2twoAnchor($this->_phpSheet$coordinates$offsetX$offsetY$width$height);
  2765.  
  2766.                     $spContainer->setStartCoordinates($twoAnchor['startCoordinates']);
  2767.                     $spContainer->setStartOffsetX($twoAnchor['startOffsetX']);
  2768.                     $spContainer->setStartOffsetY($twoAnchor['startOffsetY']);
  2769.                     $spContainer->setEndCoordinates($twoAnchor['endCoordinates']);
  2770.                     $spContainer->setEndOffsetX($twoAnchor['endOffsetX']);
  2771.                     $spContainer->setEndOffsetY($twoAnchor['endOffsetY']);
  2772.  
  2773.                     $spgrContainer->addChild($spContainer);
  2774.                 }
  2775.             }
  2776.         }
  2777.  
  2778.         // set last shape index
  2779.         $dgContainer->setLastSpId($lastSpId);
  2780.  
  2781.         // write the Escher stream
  2782.         $writer new PHPExcel_Writer_Excel5_Escher($escher);
  2783.         $data $writer->close();
  2784.         $spOffsets $writer->getSpOffsets();
  2785.  
  2786.         // write the neccesary MSODRAWING, OBJ records
  2787.  
  2788.         // split the Escher stream
  2789.         $spOffsets[00;
  2790.         $nm count($spOffsets1// number of shapes excluding first shape
  2791.         for ($i 1$i <= $nm++$i{
  2792.             // MSODRAWING record
  2793.             $record 0x00EC;            // Record identifier
  2794.  
  2795.             // chunk of Escher stream for one shape
  2796.  
  2797.             $dataChunk substr($data$spOffsets[$i -1]$spOffsets[$i$spOffsets[$i 1]);
  2798.  
  2799.             $length strlen($dataChunk);
  2800.             $header pack("vv"$record$length);
  2801.  
  2802.             $this->_append($header $dataChunk);
  2803.  
  2804.             // OBJ record
  2805.             $record 0x005D// record identifier
  2806.             $objData '';
  2807.  
  2808.             // ftCmo
  2809.             $objData .=
  2810.                 pack('vvvvvVVV'
  2811.                     0x0015    // 0x0015 = ftCmo
  2812.                     0x0012    // length of ftCmo data
  2813.                     0x0008    // object type, 0x0008 = picture
  2814.                     $i        // object id number, Excel seems to use 1-based index, local for the sheet
  2815.                     0x6011    // option flags, 0x6011 is what OpenOffice.org uses
  2816.                     0            // reserved
  2817.                     0            // reserved
  2818.                     0            // reserved
  2819.                 );
  2820.             // ftEnd
  2821.             $objData .=
  2822.                 pack('vv'
  2823.                     0x0000    // 0x0000 = ftEnd
  2824.                     0x0000    // length of ftEnd data
  2825.                 );
  2826.  
  2827.             $length strlen($objData);
  2828.             $header pack('vv'$record$length);
  2829.             $this->_append($header $objData);
  2830.         }
  2831.  
  2832.     }
  2833.  
  2834.     /**
  2835.      * Store the DATAVALIDATIONS and DATAVALIDATION records.
  2836.      */
  2837.     private function _writeDataValidity()
  2838.     {
  2839.         // Datavalidation collection
  2840.         $dataValidationCollection $this->_phpSheet->getDataValidationCollection();
  2841.  
  2842.         // Write data validations?
  2843.         if (count($dataValidationCollection0{
  2844.  
  2845.             // DATAVALIDATIONS record
  2846.             $record 0x01B2;      // Record identifier
  2847.         $length      0x0012;      // Bytes to follow
  2848.  
  2849.             $grbit  0x0000;       // Prompt box at cell, no cached validity data at DV records
  2850.         $horPos      0x00000000;  // Horizontal position of prompt box, if fixed position
  2851.         $verPos      0x00000000;  // Vertical position of prompt box, if fixed position
  2852.             $objId  0xFFFFFFFF;  // Object identifier of drop down arrow object, or -1 if not visible
  2853.  
  2854.         $header      pack('vv'$record$length);
  2855.         $data        pack('vVVVV'$grbit$horPos$verPos$objId,
  2856.                                          count($dataValidationCollection));
  2857.         $this->_append($header.$data);
  2858.  
  2859.             // DATAVALIDATION records
  2860.             $record 0x01BE;              // Record identifier
  2861.  
  2862.             foreach ($dataValidationCollection as $cellCoordinate => $dataValidation{
  2863.                 // initialize record data
  2864.                 $data '';
  2865.  
  2866.                 // options
  2867.                 $options 0x00000000;
  2868.  
  2869.                 // data type
  2870.                 $type $dataValidation->getType();
  2871.                 switch ($type{
  2872.                     case PHPExcel_Cell_DataValidation::TYPE_NONE:        $type 0x00;    break;
  2873.                     case PHPExcel_Cell_DataValidation::TYPE_WHOLE:        $type 0x01;    break;
  2874.                     case PHPExcel_Cell_DataValidation::TYPE_DECIMAL:    $type 0x02;    break;
  2875.                     case PHPExcel_Cell_DataValidation::TYPE_LIST:        $type 0x03;    break;
  2876.                     case PHPExcel_Cell_DataValidation::TYPE_DATE:        $type 0x04;    break;
  2877.                     case PHPExcel_Cell_DataValidation::TYPE_TIME:        $type 0x05;    break;
  2878.                     case PHPExcel_Cell_DataValidation::TYPE_TEXTLENGTH:    $type 0x06;    break;
  2879.                     case PHPExcel_Cell_DataValidation::TYPE_CUSTOM:        $type 0x07;    break;
  2880.                 }
  2881.                 $options |= $type << 0;
  2882.  
  2883.                 // error style
  2884.                 $errorStyle $dataValidation->getType();
  2885.                 switch ($errorStyle{
  2886.                     case PHPExcel_Cell_DataValidation::STYLE_STOP:            $errorStyle 0x00;        break;
  2887.                     case PHPExcel_Cell_DataValidation::STYLE_WARNING:        $errorStyle 0x01;        break;
  2888.                     case PHPExcel_Cell_DataValidation::STYLE_INFORMATION:    $errorStyle 0x02;        break;
  2889.                 }
  2890.                 $options |= $errorStyle << 4;
  2891.  
  2892.                 // explicit formula?
  2893.                 if ($type == 0x03 && preg_match('/^\".*\"$/'$dataValidation->getFormula1())) {
  2894.                     $options |= 0x01                << 7;
  2895.                 }
  2896.  
  2897.                 // empty cells allowed
  2898.                 $options |= $dataValidation->getAllowBlank(<< 8;
  2899.  
  2900.                 // show drop down
  2901.                 $options |= (!$dataValidation->getShowDropDown()) << 9;
  2902.  
  2903.                 // show input message
  2904.                 $options |= $dataValidation->getShowInputMessage(<< 18;
  2905.  
  2906.                 // show error message
  2907.                 $options |= $dataValidation->getShowErrorMessage(<< 19;
  2908.  
  2909.                 // condition operator
  2910.                 $operator $dataValidation->getOperator();
  2911.                 switch ($operator{
  2912.                     case PHPExcel_Cell_DataValidation::OPERATOR_BETWEEN$operator 0x00            ;    break;
  2913.                     case PHPExcel_Cell_DataValidation::OPERATOR_NOTBETWEEN$operator 0x01        ;    break;
  2914.                     case PHPExcel_Cell_DataValidation::OPERATOR_EQUAL$operator 0x02                ;    break;
  2915.                     case PHPExcel_Cell_DataValidation::OPERATOR_NOTEQUAL$operator 0x03            ;    break;
  2916.                     case PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHAN$operator 0x04        ;    break;
  2917.                     case PHPExcel_Cell_DataValidation::OPERATOR_LESSTHAN$operator 0x05            ;    break;
  2918.                     case PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHANOREQUAL$operator 0x06;    break;
  2919.                     case PHPExcel_Cell_DataValidation::OPERATOR_LESSTHANOREQUAL$operator 0x07    ;    break;
  2920.                 }
  2921.                 $options |= $operator << 20;
  2922.  
  2923.                 $data        pack('V'$options);
  2924.  
  2925.                 // prompt title
  2926.                 $promptTitle $dataValidation->getPromptTitle(!== '' ?
  2927.                     $dataValidation->getPromptTitle(chr(0);
  2928.                 $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($promptTitle);
  2929.  
  2930.                 // error title
  2931.                 $errorTitle $dataValidation->getErrorTitle(!== '' ?
  2932.                     $dataValidation->getErrorTitle(chr(0);
  2933.                 $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($errorTitle);
  2934.  
  2935.                 // prompt text
  2936.                 $prompt $dataValidation->getPrompt(!== '' ?
  2937.                     $dataValidation->getPrompt(chr(0);
  2938.                 $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($prompt);
  2939.  
  2940.                 // error text
  2941.                 $error $dataValidation->getError(!== '' ?
  2942.                     $dataValidation->getError(chr(0);
  2943.                 $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($error);
  2944.  
  2945.                 // formula 1
  2946.                 try {
  2947.                     $formula1 $dataValidation->getFormula1();
  2948.                     if ($type == 0x03// list type
  2949.                         $formula1 str_replace(','chr(0)$formula1);
  2950.                     }
  2951.                     $this->_parser->parse($formula1);
  2952.                     $formula1 $this->_parser->toReversePolish();
  2953.                     $sz1 strlen($formula1);
  2954.  
  2955.                 catch(Exception $e{
  2956.                     $sz1 0;
  2957.                     $formula1 '';
  2958.                 }
  2959.                 $data .= pack('vv'$sz10x0000);
  2960.                 $data .= $formula1;
  2961.  
  2962.                 // formula 2
  2963.                 try {
  2964.                     $formula2 $dataValidation->getFormula2();
  2965.                     if ($formula2 === ''{
  2966.                         throw new Exception('No formula2');
  2967.                     }
  2968.                     $this->_parser->parse($formula2);
  2969.                     $formula2 $this->_parser->toReversePolish();
  2970.                     $sz2 strlen($formula2);
  2971.  
  2972.                 catch(Exception $e{
  2973.                     $sz2 0;
  2974.                     $formula2 '';
  2975.                 }
  2976.                 $data .= pack('vv'$sz20x0000);
  2977.                 $data .= $formula2;
  2978.  
  2979.                 // cell range address list
  2980.                 $data .= pack('v'0x0001);
  2981.                 $data .= $this->_writeBIFF8CellRangeAddressFixed($cellCoordinate);
  2982.  
  2983.                 $length strlen($data);
  2984.             $header pack("vv"$record$length);
  2985.  
  2986.                 $this->_append($header $data);
  2987.             }
  2988.         }
  2989.     }
  2990.  
  2991.     /**
  2992.      * Map Error code
  2993.      */
  2994.     private function _mapErrorCode($errorCode{
  2995.         switch ($errorCode{
  2996.             case '#NULL!':    return 0x00;
  2997.             case '#DIV/0!':    return 0x07;
  2998.             case '#VALUE!':    return 0x0F;
  2999.             case '#REF!':    return 0x17;
  3000.             case '#NAME?':    return 0x1D;
  3001.             case '#NUM!':    return 0x24;
  3002.             case '#N/A':    return 0x2A;
  3003.         }
  3004.  
  3005.         return 0;
  3006.     }
  3007.  
  3008. }

Documentation generated on Tue, 01 Jun 2010 17:08:39 +0200 by phpDocumentor 1.4.3