!C99Shell v. 2.0 [PHP 7 Update] [25.02.2019]!

Software: Apache/2.4.18 (Ubuntu). PHP/7.0.33-0ubuntu0.16.04.16 

uname -a: Linux digifus 3.13.0-57-generic #95-Ubuntu SMP Fri Jun 19 09:28:15 UTC 2015 x86_64 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/var/www/html/antonellaServer/application/libraries/PHPExcel/Writer/Excel5/   drwxr-xr-x
Free 9.8 GB of 29.4 GB (33.32%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     Worksheet.php (121.12 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/**
 * PHPExcel
 *
 * Copyright (c) 2006 - 2014 PHPExcel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category   PHPExcel
 * @package    PHPExcel_Writer_Excel5
 * @copyright  Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
 * @version    1.8.0, 2014-03-02
 */

// Original file header of PEAR::Spreadsheet_Excel_Writer_Worksheet (used as the base for this class):
// -----------------------------------------------------------------------------------------
// /*
// *  Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
// *
// *  The majority of this is _NOT_ my code.  I simply ported it from the
// *  PERL Spreadsheet::WriteExcel module.
// *
// *  The author of the Spreadsheet::WriteExcel module is John McNamara
// *  <jmcnamara@cpan.org>
// *
// *  I _DO_ maintain this code, and John McNamara has nothing to do with the
// *  porting of this code to PHP.  Any questions directly related to this
// *  class library should be directed to me.
// *
// *  License Information:
// *
// *    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
// *    Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
// *
// *    This library is free software; you can redistribute it and/or
// *    modify it under the terms of the GNU Lesser General Public
// *    License as published by the Free Software Foundation; either
// *    version 2.1 of the License, or (at your option) any later version.
// *
// *    This library is distributed in the hope that it will be useful,
// *    but WITHOUT ANY WARRANTY; without even the implied warranty of
// *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// *    Lesser General Public License for more details.
// *
// *    You should have received a copy of the GNU Lesser General Public
// *    License along with this library; if not, write to the Free Software
// *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// */


/**
 * PHPExcel_Writer_Excel5_Worksheet
 *
 * @category   PHPExcel
 * @package    PHPExcel_Writer_Excel5
 * @copyright  Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
 */
class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
{
    
/**
     * Formula parser
     *
     * @var PHPExcel_Writer_Excel5_Parser
     */
    
private $_parser;

    
/**
     * Maximum number of characters for a string (LABEL record in BIFF5)
     * @var integer
     */
    
public $_xls_strmax;

    
/**
     * Array containing format information for columns
     * @var array
     */
    
public $_colinfo;

    
/**
     * Array containing the selected area for the worksheet
     * @var array
     */
    
public $_selection;

    
/**
     * The active pane for the worksheet
     * @var integer
     */
    
public $_active_pane;

    
/**
     * Whether to use outline.
     * @var integer
     */
    
public $_outline_on;

    
/**
     * Auto outline styles.
     * @var bool
     */
    
public $_outline_style;

    
/**
     * Whether to have outline summary below.
     * @var bool
     */
    
public $_outline_below;

    
/**
     * Whether to have outline summary at the right.
     * @var bool
     */
    
public $_outline_right;

    
/**
     * Reference to the total number of strings in the workbook
     * @var integer
     */
    
public $_str_total;

    
/**
     * Reference to the number of unique strings in the workbook
     * @var integer
     */
    
public $_str_unique;

    
/**
     * Reference to the array containing all the unique strings in the workbook
     * @var array
     */
    
public $_str_table;

    
/**
     * Color cache
     */
    
private $_colors;

    
/**
     * Index of first used row (at least 0)
     * @var int
     */
    
private $_firstRowIndex;

    
/**
     * Index of last used row. (no used rows means -1)
     * @var int
     */
    
private $_lastRowIndex;

    
/**
     * Index of first used column (at least 0)
     * @var int
     */
    
private $_firstColumnIndex;

    
/**
     * Index of last used column (no used columns means -1)
     * @var int
     */
    
private $_lastColumnIndex;

    
/**
     * Sheet object
     * @var PHPExcel_Worksheet
     */
    
public $_phpSheet;

    
/**
     * Count cell style Xfs
     *
     * @var int
     */
    
private $_countCellStyleXfs;

    
/**
     * Escher object corresponding to MSODRAWING
     *
     * @var PHPExcel_Shared_Escher
     */
    
private $_escher;

    
/**
     * Array of font hashes associated to FONT records index
     *
     * @var array
     */
    
public $_fntHashIndex;

    
/**
     * Constructor
     *
     * @param int        &$str_total        Total number of strings
     * @param int        &$str_unique    Total number of unique strings
     * @param array        &$str_table        String Table
     * @param array        &$colors        Colour Table
     * @param mixed        $parser            The formula parser created for the Workbook
     * @param boolean    $preCalculateFormulas    Flag indicating whether formulas should be calculated or just written
     * @param string    $phpSheet        The worksheet to write
     * @param PHPExcel_Worksheet $phpSheet
     */
    
public function __construct(&$str_total, &$str_unique, &$str_table, &$colors,
                                
$parser$preCalculateFormulas$phpSheet)
    {
        
// It needs to call its parent's constructor explicitly
        
parent::__construct();

        
// change BIFFwriter limit for CONTINUE records
//        $this->_limit = 8224;


        
$this->_preCalculateFormulas $preCalculateFormulas;
        
$this->_str_total        = &$str_total;
        
$this->_str_unique        = &$str_unique;
        
$this->_str_table        = &$str_table;
        
$this->_colors            = &$colors;
        
$this->_parser            $parser;

        
$this->_phpSheet $phpSheet;

        
//$this->ext_sheets        = array();
        //$this->offset            = 0;
        
$this->_xls_strmax        255;
        
$this->_colinfo            = array();
        
$this->_selection        = array(0,0,0,0);
        
$this->_active_pane        3;

        
$this->_print_headers        0;

        
$this->_outline_style        0;
        
$this->_outline_below        1;
        
$this->_outline_right        1;
        
$this->_outline_on            1;

        
$this->_fntHashIndex    = array();

        
// calculate values for DIMENSIONS record
        
$minR 1;
        
$minC 'A';

        
$maxR  $this->_phpSheet->getHighestRow();
        
$maxC $this->_phpSheet->getHighestColumn();

        
// Determine lowest and highest column and row
//        $this->_firstRowIndex = ($minR > 65535) ? 65535 : $minR;
        
$this->_lastRowIndex = ($maxR 65535) ? 65535 $maxR ;

        
$this->_firstColumnIndex    PHPExcel_Cell::columnIndexFromString($minC);
        
$this->_lastColumnIndex        PHPExcel_Cell::columnIndexFromString($maxC);

//        if ($this->_firstColumnIndex > 255) $this->_firstColumnIndex = 255;
        
if ($this->_lastColumnIndex 255$this->_lastColumnIndex 255;

        
$this->_countCellStyleXfs count($phpSheet->getParent()->getCellStyleXfCollection());
    }

    
/**
     * Add data to the beginning of the workbook (note the reverse order)
     * and to the end of the workbook.
     *
     * @access public
     * @see PHPExcel_Writer_Excel5_Workbook::storeWorkbook()
     */
    
function close()
    {
        
$_phpSheet $this->_phpSheet;

        
$num_sheets $_phpSheet->getParent()->getSheetCount();

        
// Write BOF record
        
$this->_storeBof(0x0010);

        
// Write PRINTHEADERS
        
$this->_writePrintHeaders();

        
// Write PRINTGRIDLINES
        
$this->_writePrintGridlines();

        
// Write GRIDSET
        
$this->_writeGridset();

        
// Calculate column widths
        
$_phpSheet->calculateColumnWidths();

        
// Column dimensions
        
if (($defaultWidth $_phpSheet->getDefaultColumnDimension()->getWidth()) < 0) {
            
$defaultWidth PHPExcel_Shared_Font::getDefaultColumnWidthByFont($_phpSheet->getParent()->getDefaultStyle()->getFont());
        }

        
$columnDimensions $_phpSheet->getColumnDimensions();
        
$maxCol $this->_lastColumnIndex -1;
        for (
$i 0$i <= $maxCol; ++$i) {
            
$hidden 0;
            
$level 0;
            
$xfIndex 15// there are 15 cell style Xfs

            
$width $defaultWidth;

            
$columnLetter PHPExcel_Cell::stringFromColumnIndex($i);
            if (isset(
$columnDimensions[$columnLetter])) {
                
$columnDimension $columnDimensions[$columnLetter];
                if (
$columnDimension->getWidth() >= 0) {
                    
$width $columnDimension->getWidth();
                }
                
$hidden $columnDimension->getVisible() ? 1;
                
$level $columnDimension->getOutlineLevel();
                
$xfIndex $columnDimension->getXfIndex() + 15// there are 15 cell style Xfs
            
}

            
// Components of _colinfo:
            // $firstcol first column on the range
            // $lastcol  last column on the range
            // $width    width to set
            // $xfIndex  The optional cell style Xf index to apply to the columns
            // $hidden   The optional hidden atribute
            // $level    The optional outline level
            
$this->_colinfo[] = array($i$i$width$xfIndex$hidden$level);
        }

        
// Write GUTS
        
$this->_writeGuts();

        
// Write DEFAULTROWHEIGHT
        
$this->_writeDefaultRowHeight();

        
// Write WSBOOL
        
$this->_writeWsbool();

        
// Write horizontal and vertical page breaks
        
$this->_writeBreaks();

        
// Write page header
        
$this->_writeHeader();

        
// Write page footer
        
$this->_writeFooter();

        
// Write page horizontal centering
        
$this->_writeHcenter();

        
// Write page vertical centering
        
$this->_writeVcenter();

        
// Write left margin
        
$this->_writeMarginLeft();

        
// Write right margin
        
$this->_writeMarginRight();

        
// Write top margin
        
$this->_writeMarginTop();

        
// Write bottom margin
        
$this->_writeMarginBottom();

        
// Write page setup
        
$this->_writeSetup();

        
// Write sheet protection
        
$this->_writeProtect();

        
// Write SCENPROTECT
        
$this->_writeScenProtect();

        
// Write OBJECTPROTECT
        
$this->_writeObjectProtect();

        
// Write sheet password
        
$this->_writePassword();

        
// Write DEFCOLWIDTH record
        
$this->_writeDefcol();

        
// Write the COLINFO records if they exist
        
if (!empty($this->_colinfo)) {
            
$colcount count($this->_colinfo);
            for (
$i 0$i $colcount; ++$i) {
                
$this->_writeColinfo($this->_colinfo[$i]);
            }
        }
        
$autoFilterRange $_phpSheet->getAutoFilter()->getRange();
        if (!empty(
$autoFilterRange)) {
            
// Write AUTOFILTERINFO
            
$this->_writeAutoFilterInfo();
        }

        
// Write sheet dimensions
        
$this->_writeDimensions();

        
// Row dimensions
        
foreach ($_phpSheet->getRowDimensions() as $rowDimension) {
            
$xfIndex $rowDimension->getXfIndex() + 15// there are 15 cellXfs
            
$this->_writeRow$rowDimension->getRowIndex() - 1$rowDimension->getRowHeight(), $xfIndex, ($rowDimension->getVisible() ? '0' '1'), $rowDimension->getOutlineLevel() );
        }

        
// Write Cells
        
foreach ($_phpSheet->getCellCollection() as $cellID) {
            
$cell $_phpSheet->getCell($cellID);
            
$row $cell->getRow() - 1;
            
$column PHPExcel_Cell::columnIndexFromString($cell->getColumn()) - 1;

            
// Don't break Excel!
//            if ($row + 1 > 65536 or $column + 1 > 256) {
            
if ($row 65535 || $column 255) {
                break;
            }

            
// Write cell value
            
$xfIndex $cell->getXfIndex() + 15// there are 15 cell style Xfs

            
$cVal $cell->getValue();
            if (
$cVal instanceof PHPExcel_RichText) {
                
// $this->_writeString($row, $column, $cVal->getPlainText(), $xfIndex);
                
$arrcRun = array();
                
$str_len PHPExcel_Shared_String::CountCharacters($cVal->getPlainText(), 'UTF-8');
                
$str_pos 0;
                
$elements $cVal->getRichTextElements();
                foreach (
$elements as $element) {
                    
// FONT Index
                    
if ($element instanceof PHPExcel_RichText_Run) {
                        
$str_fontidx $this->_fntHashIndex[$element->getFont()->getHashCode()];
                    }
                    else {
                        
$str_fontidx 0;
                    }
                    
$arrcRun[] = array('strlen' => $str_pos'fontidx' => $str_fontidx);
                    
// Position FROM
                    
$str_pos += PHPExcel_Shared_String::CountCharacters($element->getText(), 'UTF-8');
                }
                
$this->_writeRichTextString($row$column$cVal->getPlainText(), $xfIndex$arrcRun);
            } else {
                switch (
$cell->getDatatype()) {
                    case 
PHPExcel_Cell_DataType::TYPE_STRING:
                    case 
PHPExcel_Cell_DataType::TYPE_NULL:
                        if (
$cVal === '' || $cVal === null) {
                            
$this->_writeBlank($row$column$xfIndex);
                        } else {
                            
$this->_writeString($row$column$cVal$xfIndex);
                        }
                        break;

                    case 
PHPExcel_Cell_DataType::TYPE_NUMERIC:
                        
$this->_writeNumber($row$column$cVal$xfIndex);
                        break;

                    case 
PHPExcel_Cell_DataType::TYPE_FORMULA:
                        
$calculatedValue $this->_preCalculateFormulas ?
                            
$cell->getCalculatedValue() : null;
                        
$this->_writeFormula($row$column$cVal$xfIndex$calculatedValue);
                        break;

                    case 
PHPExcel_Cell_DataType::TYPE_BOOL:
                        
$this->_writeBoolErr($row$column$cVal0$xfIndex);
                        break;

                    case 
PHPExcel_Cell_DataType::TYPE_ERROR:
                        
$this->_writeBoolErr($row$columnself::_mapErrorCode($cVal), 1$xfIndex);
                        break;

                }
            }
        }

        
// Append
        
$this->_writeMsoDrawing();

        
// Write WINDOW2 record
        
$this->_writeWindow2();

        
// Write PLV record
        
$this->_writePageLayoutView();

        
// Write ZOOM record
        
$this->_writeZoom();
        if (
$_phpSheet->getFreezePane()) {
            
$this->_writePanes();
        }

        
// Write SELECTION record
        
$this->_writeSelection();

        
// Write MergedCellsTable Record
        
$this->_writeMergedCells();

        
// Hyperlinks
        
foreach ($_phpSheet->getHyperLinkCollection() as $coordinate => $hyperlink) {
            list(
$column$row) = PHPExcel_Cell::coordinateFromString($coordinate);

            
$url $hyperlink->getUrl();

            if ( 
strpos($url'sheet://') !== false ) {
                
// internal to current workbook
                
$url str_replace('sheet://''internal:'$url);

            } else if ( 
preg_match('/^(http:|https:|ftp:|mailto:)/'$url) ) {
                
// URL
                // $url = $url;

            
} else {
                
// external (local file)
                
$url 'external:' $url;
            }

            
$this->_writeUrl($row 1PHPExcel_Cell::columnIndexFromString($column) - 1$url);
        }

        
$this->_writeDataValidity();
        
$this->_writeSheetLayout();

        
// Write SHEETPROTECTION record
        
$this->_writeSheetProtection();
        
$this->_writeRangeProtection();

        
$arrConditionalStyles $_phpSheet->getConditionalStylesCollection();
        if(!empty(
$arrConditionalStyles)){
            
$arrConditional = array();
            
// @todo CFRule & CFHeader
            // Write CFHEADER record
            
$this->_writeCFHeader();
            
// Write ConditionalFormattingTable records
            
foreach ($arrConditionalStyles as $cellCoordinate => $conditionalStyles) {
                foreach (
$conditionalStyles as $conditional) {
                    if(
$conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION
                        
|| $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){
                        if(!
in_array($conditional->getHashCode(), $arrConditional)){
                            
$arrConditional[] = $conditional->getHashCode();
                            
// Write CFRULE record
                            
$this->_writeCFRule($conditional);
                        }
                    }
                }
            }
        }

        
$this->_storeEof();
    }

    
/**
     * Write a cell range address in BIFF8
     * always fixed range
     * See section 2.5.14 in OpenOffice.org's Documentation of the Microsoft Excel File Format
     *
     * @param string $range E.g. 'A1' or 'A1:B6'
     * @return string Binary data
     */
    
private function _writeBIFF8CellRangeAddressFixed($range 'A1')
    {
        
$explodes explode(':'$range);

        
// extract first cell, e.g. 'A1'
        
$firstCell $explodes[0];

        
// extract last cell, e.g. 'B6'
        
if (count($explodes) == 1) {
            
$lastCell $firstCell;
        } else {
            
$lastCell $explodes[1];
        }

        
$firstCellCoordinates PHPExcel_Cell::coordinateFromString($firstCell); // e.g. array(0, 1)
        
$lastCellCoordinates  PHPExcel_Cell::coordinateFromString($lastCell);  // e.g. array(1, 6)

        
return(pack('vvvv',
            
$firstCellCoordinates[1] - 1,
            
$lastCellCoordinates[1] - 1,
            
PHPExcel_Cell::columnIndexFromString($firstCellCoordinates[0]) - 1,
            
PHPExcel_Cell::columnIndexFromString($lastCellCoordinates[0]) - 1
        
));
    }

    
/**
     * Retrieves data from memory in one chunk, or from disk in $buffer
     * sized chunks.
     *
     * @return string The data
     */
    
function getData()
    {
        
$buffer 4096;

        
// Return data stored in memory
        
if (isset($this->_data)) {
            
$tmp   $this->_data;
            unset(
$this->_data);
            return 
$tmp;
        }
        
// No data to return
        
return false;
    }

    
/**
     * Set the option to print the row and column headers on the printed page.
     *
     * @access public
     * @param integer $print Whether to print the headers or not. Defaults to 1 (print).
     */
    
function printRowColHeaders($print 1)
    {
        
$this->_print_headers $print;
    }

    
/**
     * This method sets the properties for outlining and grouping. The defaults
     * correspond to Excel's defaults.
     *
     * @param bool $visible
     * @param bool $symbols_below
     * @param bool $symbols_right
     * @param bool $auto_style
     */
    
function setOutline($visible true$symbols_below true$symbols_right true$auto_style false)
    {
        
$this->_outline_on    $visible;
        
$this->_outline_below $symbols_below;
        
$this->_outline_right $symbols_right;
        
$this->_outline_style $auto_style;

        
// Ensure this is a boolean vale for Window2
        
if ($this->_outline_on) {
            
$this->_outline_on 1;
        }
     }

    
/**
     * Write a double to the specified row and column (zero indexed).
     * An integer can be written as a double. Excel will display an
     * integer. $format is optional.
     *
     * Returns  0 : normal termination
     *         -2 : row or column out of range
     *
     * @param integer $row    Zero indexed row
     * @param integer $col    Zero indexed column
     * @param float   $num    The number to write
     * @param mixed   $xfIndex The optional XF format
     * @return integer
     */
    
private function _writeNumber($row$col$num$xfIndex)
    {
        
$record    0x0203;                 // Record identifier
        
$length    0x000E;                 // Number of bytes to follow

        
$header        pack("vv",  $record$length);
        
$data        pack("vvv"$row$col$xfIndex);
        
$xl_double    pack("d",   $num);
        if (
self::getByteOrder()) { // if it's Big Endian
            
$xl_double strrev($xl_double);
        }

        
$this->_append($header.$data.$xl_double);
        return(
0);
    }

    
/**
     * Write a LABELSST record or a LABEL record. Which one depends on BIFF version
     *
     * @param int $row Row index (0-based)
     * @param int $col Column index (0-based)
     * @param string $str The string
     * @param int $xfIndex Index to XF record
     */
    
private function _writeString($row$col$str$xfIndex)
    {
        
$this->_writeLabelSst($row$col$str$xfIndex);
    }

    
/**
     * Write a LABELSST record or a LABEL record. Which one depends on BIFF version
     * It differs from _writeString by the writing of rich text strings.
     * @param int $row Row index (0-based)
     * @param int $col Column index (0-based)
     * @param string $str The string
     * @param mixed   $xfIndex The XF format index for the cell
     * @param array $arrcRun Index to Font record and characters beginning
     */
    
private function _writeRichTextString($row$col$str$xfIndex$arrcRun){
        
$record    0x00FD;                   // Record identifier
        
$length    0x000A;                   // Bytes to follow
        
$str PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($str$arrcRun);

        
/* check if string is already present */
        
if (!isset($this->_str_table[$str])) {
            
$this->_str_table[$str] = $this->_str_unique++;
        }
        
$this->_str_total++;

        
$header    pack('vv',   $record$length);
        
$data    pack('vvvV'$row$col$xfIndex$this->_str_table[$str]);
        
$this->_append($header.$data);
    }

    
/**
     * Write a string to the specified row and column (zero indexed).
     * NOTE: there is an Excel 5 defined limit of 255 characters.
     * $format is optional.
     * Returns  0 : normal termination
     *         -2 : row or column out of range
     *         -3 : long string truncated to 255 chars
     *
     * @access public
     * @param integer $row    Zero indexed row
     * @param integer $col    Zero indexed column
     * @param string  $str    The string to write
     * @param mixed   $xfIndex The XF format index for the cell
     * @return integer
     */
    
private function _writeLabel($row$col$str$xfIndex)
    {
        
$strlen    strlen($str);
        
$record    0x0204;                   // Record identifier
        
$length    0x0008 $strlen;         // Bytes to follow

        
$str_error 0;

        if (
$strlen $this->_xls_strmax) { // LABEL must be < 255 chars
            
$str    substr($str0$this->_xls_strmax);
            
$length    0x0008 $this->_xls_strmax;
            
$strlen    $this->_xls_strmax;
            
$str_error = -3;
        }

        
$header    pack("vv",   $record$length);
        
$data    pack("vvvv"$row$col$xfIndex$strlen);
        
$this->_append($header $data $str);
        return(
$str_error);
    }

    
/**
     * Write a string to the specified row and column (zero indexed).
     * This is the BIFF8 version (no 255 chars limit).
     * $format is optional.
     * Returns  0 : normal termination
     *         -2 : row or column out of range
     *         -3 : long string truncated to 255 chars
     *
     * @access public
     * @param integer $row    Zero indexed row
     * @param integer $col    Zero indexed column
     * @param string  $str    The string to write
     * @param mixed   $xfIndex The XF format index for the cell
     * @return integer
     */
    
private function _writeLabelSst($row$col$str$xfIndex)
    {
        
$record    0x00FD;                   // Record identifier
        
$length    0x000A;                   // Bytes to follow

        
$str PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($str);

        
/* check if string is already present */
        
if (!isset($this->_str_table[$str])) {
            
$this->_str_table[$str] = $this->_str_unique++;
        }
        
$this->_str_total++;

        
$header    pack('vv',   $record$length);
        
$data    pack('vvvV'$row$col$xfIndex$this->_str_table[$str]);
        
$this->_append($header.$data);
    }

    
/**
     * Writes a note associated with the cell given by the row and column.
     * NOTE records don't have a length limit.
     *
     * @param integer $row    Zero indexed row
     * @param integer $col    Zero indexed column
     * @param string  $note   The note to write
     */
    
private function _writeNote($row$col$note)
    {
        
$note_length    strlen($note);
        
$record            0x001C;            // Record identifier
        
$max_length        2048;                // Maximun length for a NOTE record

        // Length for this record is no more than 2048 + 6
        
$length    0x0006 min($note_length2048);
        
$header    pack("vv",   $record$length);
        
$data    pack("vvv"$row$col$note_length);
        
$this->_append($header $data substr($note02048));

        for (
$i $max_length$i $note_length$i += $max_length) {
            
$chunk  substr($note$i$max_length);
            
$length 0x0006 strlen($chunk);
            
$header pack("vv",   $record$length);
            
$data   pack("vvv", -10strlen($chunk));
            
$this->_append($header.$data.$chunk);
        }
        return(
0);
    }

    
/**
     * Write a blank cell to the specified row and column (zero indexed).
     * A blank cell is used to specify formatting without adding a string
     * or a number.
     *
     * A blank cell without a format serves no purpose. Therefore, we don't write
     * a BLANK record unless a format is specified.
     *
     * Returns  0 : normal termination (including no format)
     *         -1 : insufficient number of arguments
     *         -2 : row or column out of range
     *
     * @param integer $row    Zero indexed row
     * @param integer $col    Zero indexed column
     * @param mixed   $xfIndex The XF format index
     */
    
function _writeBlank($row$col$xfIndex)
    {
        
$record    0x0201;                 // Record identifier
        
$length    0x0006;                 // Number of bytes to follow

        
$header    pack("vv",  $record$length);
        
$data      pack("vvv"$row$col$xfIndex);
        
$this->_append($header $data);
        return 
0;
    }

    
/**
     * Write a boolean or an error type to the specified row and column (zero indexed)
     *
     * @param int $row Row index (0-based)
     * @param int $col Column index (0-based)
     * @param int $value
     * @param boolean $isError Error or Boolean?
     * @param int $xfIndex
     */
    
private function _writeBoolErr($row$col$value$isError$xfIndex)
    {
        
$record 0x0205;
        
$length 8;

        
$header    pack("vv",  $record$length);
        
$data      pack("vvvCC"$row$col$xfIndex$value$isError);
        
$this->_append($header $data);
        return 
0;
    }

    
/**
     * Write a formula to the specified row and column (zero indexed).
     * The textual representation of the formula is passed to the parser in
     * Parser.php which returns a packed binary string.
     *
     * Returns  0 : normal termination
     *         -1 : formula errors (bad formula)
     *         -2 : row or column out of range
     *
     * @param integer $row     Zero indexed row
     * @param integer $col     Zero indexed column
     * @param string  $formula The formula text string
     * @param mixed   $xfIndex  The XF format index
     * @param mixed   $calculatedValue  Calculated value
     * @return integer
     */
    
private function _writeFormula($row$col$formula$xfIndex$calculatedValue)
    {
        
$record    0x0006;     // Record identifier

        // Initialize possible additional value for STRING record that should be written after the FORMULA record?
        
$stringValue null;

        
// calculated value
        
if (isset($calculatedValue)) {
            
// Since we can't yet get the data type of the calculated value,
            // we use best effort to determine data type
            
if (is_bool($calculatedValue)) {
                
// Boolean value
                
$num pack('CCCvCv'0x010x00, (int)$calculatedValue0x000x000xFFFF);
            } elseif (
is_int($calculatedValue) || is_float($calculatedValue)) {
                
// Numeric value
                
$num pack('d'$calculatedValue);
            } elseif (
is_string($calculatedValue)) {
                if (
array_key_exists($calculatedValuePHPExcel_Cell_DataType::getErrorCodes())) {
                    
// Error value
                    
$num pack('CCCvCv'0x020x00self::_mapErrorCode($calculatedValue), 0x000x000xFFFF);
                } elseif (
$calculatedValue === '') {
                    
// Empty string (and BIFF8)
                    
$num pack('CCCvCv'0x030x000x000x000x000xFFFF);
                } else {
                    
// Non-empty string value (or empty string BIFF5)
                    
$stringValue $calculatedValue;
                    
$num pack('CCCvCv'0x000x000x000x000x000xFFFF);
                }
            } else {
                
// We are really not supposed to reach here
                
$num pack('d'0x00);
            }
        } else {
            
$num pack('d'0x00);
        }

        
$grbit        0x03;                // Option flags
        
$unknown    0x0000;            // Must be zero

        // Strip the '=' or '@' sign at the beginning of the formula string
        
if ($formula{0} == '=') {
            
$formula substr($formula,1);
        } else {
            
// Error handling
            
$this->_writeString($row$col'Unrecognised character for formula');
            return -
1;
        }

        
// Parse the formula using the parser in Parser.php
        
try {
            
$error $this->_parser->parse($formula);
            
$formula $this->_parser->toReversePolish();

            
$formlen    strlen($formula);    // Length of the binary string
            
$length     0x16 $formlen;     // Length of the record data

            
$header    pack("vv",      $record$length);

            
$data      pack("vvv"$row$col$xfIndex)
                        . 
$num
                        
pack("vVv"$grbit$unknown$formlen);
            
$this->_append($header $data $formula);

            
// Append also a STRING record if necessary
            
if ($stringValue !== null) {
                
$this->_writeStringRecord($stringValue);
            }

            return 
0;

        } catch (
PHPExcel_Exception $e) {
            
// do nothing
        
}

    }

    
/**
     * Write a STRING record. This
     *
     * @param string $stringValue
     */
    
private function _writeStringRecord($stringValue)
    {
        
$record 0x0207;     // Record identifier
        
$data PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($stringValue);

        
$length strlen($data);
        
$header pack('vv'$record$length);

        
$this->_append($header $data);
    }

    
/**
     * Write a hyperlink.
     * This is comprised of two elements: the visible label and
     * the invisible link. The visible label is the same as the link unless an
     * alternative string is specified. The label is written using the
     * _writeString() method. Therefore the 255 characters string limit applies.
     * $string and $format are optional.
     *
     * The hyperlink can be to a http, ftp, mail, internal sheet (not yet), or external
     * directory url.
     *
     * Returns  0 : normal termination
     *         -2 : row or column out of range
     *         -3 : long string truncated to 255 chars
     *
     * @param integer $row    Row
     * @param integer $col    Column
     * @param string  $url    URL string
     * @return integer
     */
    
private function _writeUrl($row$col$url)
    {
        
// Add start row and col to arg list
        
return($this->_writeUrlRange($row$col$row$col$url));
    }

    
/**
     * This is the more general form of _writeUrl(). It allows a hyperlink to be
     * written to a range of cells. This function also decides the type of hyperlink
     * to be written. These are either, Web (http, ftp, mailto), Internal
     * (Sheet1!A1) or external ('c:\temp\foo.xls#Sheet1!A1').
     *
     * @access private
     * @see _writeUrl()
     * @param integer $row1   Start row
     * @param integer $col1   Start column
     * @param integer $row2   End row
     * @param integer $col2   End column
     * @param string  $url    URL string
     * @return integer
     */
    
function _writeUrlRange($row1$col1$row2$col2$url)
    {
        
// Check for internal/external sheet links or default to web link
        
if (preg_match('[^internal:]'$url)) {
            return(
$this->_writeUrlInternal($row1$col1$row2$col2$url));
        }
        if (
preg_match('[^external:]'$url)) {
            return(
$this->_writeUrlExternal($row1$col1$row2$col2$url));
        }
        return(
$this->_writeUrlWeb($row1$col1$row2$col2$url));
    }

    
/**
     * Used to write http, ftp and mailto hyperlinks.
     * The link type ($options) is 0x03 is the same as absolute dir ref without
     * sheet. However it is differentiated by the $unknown2 data stream.
     *
     * @access private
     * @see _writeUrl()
     * @param integer $row1   Start row
     * @param integer $col1   Start column
     * @param integer $row2   End row
     * @param integer $col2   End column
     * @param string  $url    URL string
     * @return integer
     */
    
function _writeUrlWeb($row1$col1$row2$col2$url)
    {
        
$record      0x01B8;                       // Record identifier
        
$length      0x00000;                      // Bytes to follow

        // Pack the undocumented parts of the hyperlink stream
        
$unknown1    pack("H*""D0C9EA79F9BACE118C8200AA004BA90B02000000");
        
$unknown2    pack("H*""E0C9EA79F9BACE118C8200AA004BA90B");

        
// Pack the option flags
        
$options     pack("V"0x03);

        
// Convert URL to a null terminated wchar string
        
$url         join("\0"preg_split("''"$url, -1PREG_SPLIT_NO_EMPTY));
        
$url         $url "\0\0\0";

        
// Pack the length of the URL
        
$url_len     pack("V"strlen($url));

        
// Calculate the data length
        
$length      0x34 strlen($url);

        
// Pack the header data
        
$header      pack("vv",   $record$length);
        
$data        pack("vvvv"$row1$row2$col1$col2);

        
// Write the packed data
        
$this->_append($header $data .
                       
$unknown1 $options .
                       
$unknown2 $url_len $url);
        return 
0;
    }

    
/**
     * Used to write internal reference hyperlinks such as "Sheet1!A1".
     *
     * @access private
     * @see _writeUrl()
     * @param integer $row1   Start row
     * @param integer $col1   Start column
     * @param integer $row2   End row
     * @param integer $col2   End column
     * @param string  $url    URL string
     * @return integer
     */
    
function _writeUrlInternal($row1$col1$row2$col2$url)
    {
        
$record      0x01B8;                       // Record identifier
        
$length      0x00000;                      // Bytes to follow

        // Strip URL type
        
$url preg_replace('/^internal:/'''$url);

        
// Pack the undocumented parts of the hyperlink stream
        
$unknown1    pack("H*""D0C9EA79F9BACE118C8200AA004BA90B02000000");

        
// Pack the option flags
        
$options     pack("V"0x08);

        
// Convert the URL type and to a null terminated wchar string
        
$url .= "\0";

        
// character count
        
$url_len PHPExcel_Shared_String::CountCharacters($url);
        
$url_len pack('V'$url_len);

        
$url PHPExcel_Shared_String::ConvertEncoding($url'UTF-16LE''UTF-8');

        
// Calculate the data length
        
$length      0x24 strlen($url);

        
// Pack the header data
        
$header      pack("vv",   $record$length);
        
$data        pack("vvvv"$row1$row2$col1$col2);

        
// Write the packed data
        
$this->_append($header $data .
                       
$unknown1 $options .
                       
$url_len $url);
        return 
0;
    }

    
/**
     * Write links to external directory names such as 'c:\foo.xls',
     * c:\foo.xls#Sheet1!A1', '../../foo.xls'. and '../../foo.xls#Sheet1!A1'.
     *
     * Note: Excel writes some relative links with the $dir_long string. We ignore
     * these cases for the sake of simpler code.
     *
     * @access private
     * @see _writeUrl()
     * @param integer $row1   Start row
     * @param integer $col1   Start column
     * @param integer $row2   End row
     * @param integer $col2   End column
     * @param string  $url    URL string
     * @return integer
     */
    
function _writeUrlExternal($row1$col1$row2$col2$url)
    {
        
// Network drives are different. We will handle them separately
        // MS/Novell network drives and shares start with \\
        
if (preg_match('[^external:\\\\]'$url)) {
            return; 
//($this->_writeUrlExternal_net($row1, $col1, $row2, $col2, $url, $str, $format));
        
}

        
$record      0x01B8;                       // Record identifier
        
$length      0x00000;                      // Bytes to follow

        // Strip URL type and change Unix dir separator to Dos style (if needed)
        //
        
$url preg_replace('/^external:/'''$url);
        
$url preg_replace('/\//'"\\"$url);

        
// Determine if the link is relative or absolute:
        //   relative if link contains no dir separator, "somefile.xls"
        //   relative if link starts with up-dir, "..\..\somefile.xls"
        //   otherwise, absolute

        
$absolute 0x00// relative path
        
if ( preg_match('/^[A-Z]:/'$url) ) {
            
$absolute 0x02// absolute path on Windows, e.g. C:\...
        
}
        
$link_type               0x01 $absolute;

        
// Determine if the link contains a sheet reference and change some of the
        // parameters accordingly.
        // Split the dir name and sheet name (if it exists)
        
$dir_long $url;
        if (
preg_match("/\#/"$url)) {
            
$link_type |= 0x08;
        }


        
// Pack the link type
        
$link_type   pack("V"$link_type);

        
// Calculate the up-level dir count e.g.. (..\..\..\ == 3)
        
$up_count    preg_match_all("/\.\.\\\/"$dir_long$useless);
        
$up_count    pack("v"$up_count);

        
// Store the short dos dir name (null terminated)
        
$dir_short   preg_replace("/\.\.\\\/"''$dir_long) . "\0";

        
// Store the long dir name as a wchar string (non-null terminated)
        
$dir_long       $dir_long "\0";

        
// Pack the lengths of the dir strings
        
$dir_short_len pack("V"strlen($dir_short)      );
        
$dir_long_len  pack("V"strlen($dir_long)       );
        
$stream_len    pack("V"0);//strlen($dir_long) + 0x06);

        // Pack the undocumented parts of the hyperlink stream
        
$unknown1 pack("H*",'D0C9EA79F9BACE118C8200AA004BA90B02000000'       );
        
$unknown2 pack("H*",'0303000000000000C000000000000046'               );
        
$unknown3 pack("H*",'FFFFADDE000000000000000000000000000000000000000');
        
$unknown4 pack("v",  0x03                                            );

        
// Pack the main data stream
        
$data        pack("vvvv"$row1$row2$col1$col2) .
                          
$unknown1     .
                          
$link_type    .
                          
$unknown2     .
                          
$up_count     .
                          
$dir_short_len.
                          
$dir_short    .
                          
$unknown3     .
                          
$stream_len   ;/*.
                          $dir_long_len .
                          $unknown4     .
                          $dir_long     .
                          $sheet_len    .
                          $sheet        ;*/

        // Pack the header data
        
$length   strlen($data);
        
$header   pack("vv"$record$length);

        
// Write the packed data
        
$this->_append($header$data);
        return 
0;
    }

    
/**
     * This method is used to set the height and format for a row.
     *
     * @param integer $row    The row to set
     * @param integer $height Height we are giving to the row.
     *                        Use null to set XF without setting height
     * @param integer $xfIndex  The optional cell style Xf index to apply to the columns
     * @param bool    $hidden The optional hidden attribute
     * @param integer $level  The optional outline level for row, in range [0,7]
     */
    
private function _writeRow($row$height$xfIndex$hidden false$level 0)
    {
        
$record      0x0208;               // Record identifier
        
$length      0x0010;               // Number of bytes to follow

        
$colMic      0x0000;               // First defined column
        
$colMac      0x0000;               // Last defined column
        
$irwMac      0x0000;               // Used by Excel to optimise loading
        
$reserved    0x0000;               // Reserved
        
$grbit       0x0000;               // Option flags
        
$ixfe        $xfIndex;

        if ( 
$height ){
            
$height null;
        }

        
// Use _writeRow($row, null, $XF) to set XF format without setting height
        
if ($height != null) {
            
$miyRw $height 20;  // row height
        
} else {
            
$miyRw 0xff;          // default row height is 256
        
}

        
// Set the options flags. fUnsynced is used to show that the font and row
        // heights are not compatible. This is usually the case for WriteExcel.
        // The collapsed flag 0x10 doesn't seem to be used to indicate that a row
        // is collapsed. Instead it is used to indicate that the previous row is
        // collapsed. The zero height flag, 0x20, is used to collapse a row.

        
$grbit |= $level;
        if (
$hidden) {
            
$grbit |= 0x0020;
        }
        if (
$height !== null) {
            
$grbit |= 0x0040// fUnsynced
        
}
        if (
$xfIndex !== 0xF) {
            
$grbit |= 0x0080;
        }
        
$grbit |= 0x0100;

        
$header   pack("vv",       $record$length);
        
$data     pack("vvvvvvvv"$row$colMic$colMac$miyRw,
                                     
$irwMac,$reserved$grbit$ixfe);
        
$this->_append($header.$data);
    }

    
/**
     * Writes Excel DIMENSIONS to define the area in which there is data.
     */
    
private function _writeDimensions()
    {
        
$record 0x0200// Record identifier

        
$length 0x000E;
        
$data pack('VVvvv'
                
$this->_firstRowIndex
                
$this->_lastRowIndex 1
                
$this->_firstColumnIndex
                
$this->_lastColumnIndex 1
                
0x0000 // reserved
            
);

        
$header pack("vv"$record$length);
        
$this->_append($header.$data);
    }

    
/**
     * Write BIFF record Window2.
     */
    
private function _writeWindow2()
    {
        
$record         0x023E;     // Record identifier
        
$length         0x0012;

        
$grbit          0x00B6;     // Option flags
        
$rwTop          0x0000;     // Top row visible in window
        
$colLeft        0x0000;     // Leftmost column visible in window


        // The options flags that comprise $grbit
        
$fDspFmla       0;                     // 0 - bit
        
$fDspGrid       $this->_phpSheet->getShowGridlines() ? 0// 1
        
$fDspRwCol      $this->_phpSheet->getShowRowColHeaders() ? 0// 2
        
$fFrozen        $this->_phpSheet->getFreezePane() ? 0;        // 3
        
$fDspZeros      1;                     // 4
        
$fDefaultHdr    1;                     // 5
        
$fArabic        $this->_phpSheet->getRightToLeft() ? 0// 6
        
$fDspGuts       $this->_outline_on;    // 7
        
$fFrozenNoSplit 0;                     // 0 - bit
        // no support in PHPExcel for selected sheet, therefore sheet is only selected if it is the active sheet
        
$fSelected      = ($this->_phpSheet === $this->_phpSheet->getParent()->getActiveSheet()) ? 0;
        
$fPaged         1;                     // 2
        
$fPageBreakPreview $this->_phpSheet->getSheetView()->getView() === PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW;

        
$grbit             $fDspFmla;
        
$grbit            |= $fDspGrid       << 1;
        
$grbit            |= $fDspRwCol       << 2;
        
$grbit            |= $fFrozen           << 3;
        
$grbit            |= $fDspZeros       << 4;
        
$grbit            |= $fDefaultHdr       << 5;
        
$grbit            |= $fArabic           << 6;
        
$grbit            |= $fDspGuts       << 7;
        
$grbit            |= $fFrozenNoSplit << 8;
        
$grbit            |= $fSelected       << 9;
        
$grbit            |= $fPaged           << 10;
        
$grbit            |= $fPageBreakPreview << 11;

        
$header  pack("vv",   $record$length);
        
$data    pack("vvv"$grbit$rwTop$colLeft);

        
// FIXME !!!
        
$rgbHdr       0x0040// Row/column heading and gridline color index
        
$zoom_factor_page_break = ($fPageBreakPreview$this->_phpSheet->getSheetView()->getZoomScale() : 0x0000);
        
$zoom_factor_normal =  $this->_phpSheet->getSheetView()->getZoomScaleNormal();

        
$data .= pack("vvvvV"$rgbHdr0x0000$zoom_factor_page_break$zoom_factor_normal0x00000000);

        
$this->_append($header.$data);
    }

    
/**
     * Write BIFF record DEFAULTROWHEIGHT.
     */
    
private function _writeDefaultRowHeight()
    {
        
$defaultRowHeight $this->_phpSheet->getDefaultRowDimension()->getRowHeight();

        if (
$defaultRowHeight 0) {
            return;
        }

        
// convert to twips
        
$defaultRowHeight = (int) 20 $defaultRowHeight;

        
$record   0x0225;      // Record identifier
        
$length   0x0004;      // Number of bytes to follow

        
$header   pack("vv"$record$length);
        
$data     pack("vv",  1$defaultRowHeight);
        
$this->_append($header $data);
    }

    
/**
     * Write BIFF record DEFCOLWIDTH if COLINFO records are in use.
     */
    
private function _writeDefcol()
    {
        
$defaultColWidth 8;

        
$record   0x0055;      // Record identifier
        
$length   0x0002;      // Number of bytes to follow

        
$header pack("vv"$record$length);
        
$data pack("v"$defaultColWidth);
        
$this->_append($header $data);
    }

    
/**
     * Write BIFF record COLINFO to define column widths
     *
     * Note: The SDK says the record length is 0x0B but Excel writes a 0x0C
     * length record.
     *
     * @param array $col_array This is the only parameter received and is composed of the following:
     *                0 => First formatted column,
     *                1 => Last formatted column,
     *                2 => Col width (8.43 is Excel default),
     *                3 => The optional XF format of the column,
     *                4 => Option flags.
     *                5 => Optional outline level
     */
    
private function _writeColinfo($col_array)
    {
        if (isset(
$col_array[0])) {
            
$colFirst $col_array[0];
        }
        if (isset(
$col_array[1])) {
            
$colLast $col_array[1];
        }
        if (isset(
$col_array[2])) {
            
$coldx $col_array[2];
        } else {
            
$coldx 8.43;
        }
        if (isset(
$col_array[3])) {
            
$xfIndex $col_array[3];
        } else {
            
$xfIndex 15;
        }
        if (isset(
$col_array[4])) {
            
$grbit $col_array[4];
        } else {
            
$grbit 0;
        }
        if (isset(
$col_array[5])) {
            
$level $col_array[5];
        } else {
            
$level 0;
        }
        
$record   0x007D;          // Record identifier
        
$length   0x000C;          // Number of bytes to follow

        
$coldx   *= 256;             // Convert to units of 1/256 of a char

        
$ixfe     $xfIndex;
        
$reserved 0x0000;            // Reserved

        
$level max(0min($level7));
        
$grbit |= $level << 8;

        
$header   pack("vv",     $record$length);
        
$data     pack("vvvvvv"$colFirst$colLast$coldx,
                                   
$ixfe$grbit$reserved);
        
$this->_append($header.$data);
    }

    
/**
     * Write BIFF record SELECTION.
     */
    
private function _writeSelection()
    {
        
// look up the selected cell range
        
$selectedCells $this->_phpSheet->getSelectedCells();
        
$selectedCells PHPExcel_Cell::splitRange($this->_phpSheet->getSelectedCells());
        
$selectedCells $selectedCells[0];
        if (
count($selectedCells) == 2) {
            list(
$first$last) = $selectedCells;
        } else {
            
$first $selectedCells[0];
            
$last  $selectedCells[0];
        }

        list(
$colFirst$rwFirst) = PHPExcel_Cell::coordinateFromString($first);
        
$colFirst PHPExcel_Cell::columnIndexFromString($colFirst) - 1// base 0 column index
        
--$rwFirst// base 0 row index

        
list($colLast$rwLast) = PHPExcel_Cell::coordinateFromString($last);
        
$colLast PHPExcel_Cell::columnIndexFromString($colLast) - 1// base 0 column index
        
--$rwLast// base 0 row index

        // make sure we are not out of bounds
        
$colFirst min($colFirst255);
        
$colLast  min($colLast,  255);

        
$rwFirst min($rwFirst65535);
        
$rwLast  min($rwLast,  65535);

        
$record   0x001D;                  // Record identifier
        
$length   0x000F;                  // Number of bytes to follow

        
$pnn      $this->_active_pane;     // Pane position
        
$rwAct    $rwFirst;                // Active row
        
$colAct   $colFirst;               // Active column
        
$irefAct  0;                       // Active cell ref
        
$cref     1;                       // Number of refs

        
if (!isset($rwLast)) {
            
$rwLast   $rwFirst;       // Last  row in reference
        
}
        if (!isset(
$colLast)) {
            
$colLast  $colFirst;      // Last  col in reference
        
}

        
// Swap last row/col for first row/col as necessary
        
if ($rwFirst $rwLast) {
            list(
$rwFirst$rwLast) = array($rwLast$rwFirst);
        }

        if (
$colFirst $colLast) {
            list(
$colFirst$colLast) = array($colLast$colFirst);
        }

        
$header   pack("vv",         $record$length);
        
$data     pack("CvvvvvvCC",  $pnn$rwAct$colAct,
                                       
$irefAct$cref,
                                       
$rwFirst$rwLast,
                                       
$colFirst$colLast);
        
$this->_append($header $data);
    }

    
/**
     * Store the MERGEDCELLS records for all ranges of merged cells
     */
    
private function _writeMergedCells()
    {
        
$mergeCells $this->_phpSheet->getMergeCells();
        
$countMergeCells count($mergeCells);

        if (
$countMergeCells == 0) {
            return;
        }

        
// maximum allowed number of merged cells per record
        
$maxCountMergeCellsPerRecord 1027;

        
// record identifier
        
$record 0x00E5;

        
// counter for total number of merged cells treated so far by the writer
        
$i 0;

        
// counter for number of merged cells written in record currently being written
        
$j 0;

        
// initialize record data
        
$recordData '';

        
// loop through the merged cells
        
foreach ($mergeCells as $mergeCell) {
            ++
$i;
            ++
$j;

            
// extract the row and column indexes
            
$range PHPExcel_Cell::splitRange($mergeCell);
            list(
$first$last) = $range[0];
            list(
$firstColumn$firstRow) = PHPExcel_Cell::coordinateFromString($first);
            list(
$lastColumn$lastRow) = PHPExcel_Cell::coordinateFromString($last);

            
$recordData .= pack('vvvv'$firstRow 1$lastRow 1PHPExcel_Cell::columnIndexFromString($firstColumn) - 1PHPExcel_Cell::columnIndexFromString($lastColumn) - 1);

            
// flush record if we have reached limit for number of merged cells, or reached final merged cell
            
if ($j == $maxCountMergeCellsPerRecord or $i == $countMergeCells) {
                
$recordData pack('v'$j) . $recordData;
                
$length strlen($recordData);
                
$header pack('vv'$record$length);
                
$this->_append($header $recordData);

                
// initialize for next record, if any
                
$recordData '';
                
$j 0;
            }
        }
    }

    
/**
     * Write SHEETLAYOUT record
     */
    
private function _writeSheetLayout()
    {
        if (!
$this->_phpSheet->isTabColorSet()) {
            return;
        }

        
$recordData pack(
            
'vvVVVvv'
            
0x0862
            
0x0000        // unused
            
0x00000000    // unused
            
0x00000000    // unused
            
0x00000014    // size of record data
            
$this->_colors[$this->_phpSheet->getTabColor()->getRGB()]    // color index
            
0x0000        // unused
        
);

        
$length strlen($recordData);

        
$record 0x0862// Record identifier
        
$header pack('vv'$record$length);
        
$this->_append($header $recordData);
    }

    
/**
     * Write SHEETPROTECTION
     */
    
private function _writeSheetProtection()
    {
        
// record identifier
        
$record 0x0867;

        
// prepare options
        
$options  =   (int) !$this->_phpSheet->getProtection()->getObjects()
                    | (int) !
$this->_phpSheet->getProtection()->getScenarios()           << 1
                    
| (int) !$this->_phpSheet->getProtection()->getFormatCells()         << 2
                    
| (int) !$this->_phpSheet->getProtection()->getFormatColumns()       << 3
                    
| (int) !$this->_phpSheet->getProtection()->getFormatRows()          << 4
                    
| (int) !$this->_phpSheet->getProtection()->getInsertColumns()       << 5
                    
| (int) !$this->_phpSheet->getProtection()->getInsertRows()          << 6
                    
| (int) !$this->_phpSheet->getProtection()->getInsertHyperlinks()    << 7
                    
| (int) !$this->_phpSheet->getProtection()->getDeleteColumns()       << 8
                    
| (int) !$this->_phpSheet->getProtection()->getDeleteRows()          << 9
                    
| (int) !$this->_phpSheet->getProtection()->getSelectLockedCells()   << 10
                    
| (int) !$this->_phpSheet->getProtection()->getSort()                << 11
                    
| (int) !$this->_phpSheet->getProtection()->getAutoFilter()          << 12
                    
| (int) !$this->_phpSheet->getProtection()->getPivotTables()         << 13
                    
| (int) !$this->_phpSheet->getProtection()->getSelectUnlockedCells() << 14 ;

        
// record data
        
$recordData pack(
            
'vVVCVVvv'
            
0x0867        // repeated record identifier
            
0x0000        // not used
            
0x0000        // not used
            
0x00            // not used
            
0x01000200    // unknown data
            
0xFFFFFFFF    // unknown data
            
$options        // options
            
0x0000        // not used
        
);

        
$length strlen($recordData);
        
$header pack('vv'$record$length);

        
$this->_append($header $recordData);
    }

    
/**
     * Write BIFF record RANGEPROTECTION
     *
     * Openoffice.org's Documentaion of the Microsoft Excel File Format uses term RANGEPROTECTION for these records
     * Microsoft Office Excel 97-2007 Binary File Format Specification uses term FEAT for these records
     */
    
private function _writeRangeProtection()
    {
        foreach (
$this->_phpSheet->getProtectedCells() as $range => $password) {
            
// number of ranges, e.g. 'A1:B3 C20:D25'
            
$cellRanges explode(' '$range);
            
$cref count($cellRanges);

            
$recordData pack(
                
'vvVVvCVvVv',
                
0x0868,
                
0x00,
                
0x0000,
                
0x0000,
                
0x02,
                
0x0,
                
0x0000,
                
$cref,
                
0x0000,
                
0x00
            
);

            foreach (
$cellRanges as $cellRange) {
                
$recordData .= $this->_writeBIFF8CellRangeAddressFixed($cellRange);
            }

            
// the rgbFeat structure
            
$recordData .= pack(
                
'VV',
                
0x0000,
                
hexdec($password)
            );

            
$recordData .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong('p' md5($recordData));

            
$length strlen($recordData);

            
$record 0x0868;        // Record identifier
            
$header pack("vv"$record$length);
            
$this->_append($header $recordData);
        }
    }

    
/**
     * Write BIFF record EXTERNCOUNT to indicate the number of external sheet
     * references in a worksheet.
     *
     * Excel only stores references to external sheets that are used in formulas.
     * For simplicity we store references to all the sheets in the workbook
     * regardless of whether they are used or not. This reduces the overall
     * complexity and eliminates the need for a two way dialogue between the formula
     * parser the worksheet objects.
     *
     * @param integer $count The number of external sheet references in this worksheet
     */
    
private function _writeExterncount($count)
    {
        
$record 0x0016;          // Record identifier
        
$length 0x0002;          // Number of bytes to follow

        
$header pack("vv"$record$length);
        
$data   pack("v",  $count);
        
$this->_append($header $data);
    }

    
/**
     * Writes the Excel BIFF EXTERNSHEET record. These references are used by
     * formulas. A formula references a sheet name via an index. Since we store a
     * reference to all of the external worksheets the EXTERNSHEET index is the same
     * as the worksheet index.
     *
     * @param string $sheetname The name of a external worksheet
     */
    
private function _writeExternsheet($sheetname)
    {
        
$record    0x0017;         // Record identifier

        // References to the current sheet are encoded differently to references to
        // external sheets.
        //
        
if ($this->_phpSheet->getTitle() == $sheetname) {
            
$sheetname '';
            
$length    0x02;  // The following 2 bytes
            
$cch       1;     // The following byte
            
$rgch      0x02;  // Self reference
        
} else {
            
$length    0x02 strlen($sheetname);
            
$cch       strlen($sheetname);
            
$rgch      0x03;  // Reference to a sheet in the current workbook
        
}

        
$header pack("vv",  $record$length);
        
$data   pack("CC"$cch$rgch);
        
$this->_append($header $data $sheetname);
    }

    
/**
     * Writes the Excel BIFF PANE record.
     * The panes can either be frozen or thawed (unfrozen).
     * Frozen panes are specified in terms of an integer number of rows and columns.
     * Thawed panes are specified in terms of Excel's units for rows and columns.
     */
    
private function _writePanes()
    {
        
$panes = array();
        if (
$freezePane $this->_phpSheet->getFreezePane()) {
            list(
$column$row) = PHPExcel_Cell::coordinateFromString($freezePane);
            
$panes[0] = $row 1;
            
$panes[1] = PHPExcel_Cell::columnIndexFromString($column) - 1;
        } else {
            
// thaw panes
            
return;
        }

        
$y       = isset($panes[0]) ? $panes[0] : null;
        
$x       = isset($panes[1]) ? $panes[1] : null;
        
$rwTop   = isset($panes[2]) ? $panes[2] : null;
        
$colLeft = isset($panes[3]) ? $panes[3] : null;
        if (
count($panes) > 4) { // if Active pane was received
            
$pnnAct $panes[4];
        } else {
            
$pnnAct null;
        }
        
$record  0x0041;       // Record identifier
        
$length  0x000A;       // Number of bytes to follow

        // Code specific to frozen or thawed panes.
        
if ($this->_phpSheet->getFreezePane()) {
            
// Set default values for $rwTop and $colLeft
            
if (!isset($rwTop)) {
                
$rwTop   $y;
            }
            if (!isset(
$colLeft)) {
                
$colLeft $x;
            }
        } else {
            
// Set default values for $rwTop and $colLeft
            
if (!isset($rwTop)) {
                
$rwTop   0;
            }
            if (!isset(
$colLeft)) {
                
$colLeft 0;
            }

            
// Convert Excel's row and column units to the internal units.
            // The default row height is 12.75
            // The default column width is 8.43
            // The following slope and intersection values were interpolated.
            //
            
$y 20*$y 255;
            
$x 113.879*$x 390;
        }


        
// Determine which pane should be active. There is also the undocumented
        // option to override this should it be necessary: may be removed later.
        //
        
if (!isset($pnnAct)) {
            if (
$x != && $y != 0) {
                
$pnnAct 0// Bottom right
            
}
            if (
$x != && $y == 0) {
                
$pnnAct 1// Top right
            
}
            if (
$x == && $y != 0) {
                
$pnnAct 2// Bottom left
            
}
            if (
$x == && $y == 0) {
                
$pnnAct 3// Top left
            
}
        }

        
$this->_active_pane $pnnAct// Used in _writeSelection

        
$header     pack("vv",    $record$length);
        
$data       pack("vvvvv"$x$y$rwTop$colLeft$pnnAct);
        
$this->_append($header $data);
    }

    
/**
     * Store the page setup SETUP BIFF record.
     */
    
private function _writeSetup()
    {
        
$record       0x00A1;                  // Record identifier
        
$length       0x0022;                  // Number of bytes to follow

        
$iPaperSize   $this->_phpSheet->getPageSetup()->getPaperSize();    // Paper size

        
$iScale $this->_phpSheet->getPageSetup()->getScale() ?
            
$this->_phpSheet->getPageSetup()->getScale() : 100;   // Print scaling factor

        
$iPageStart   0x01;                 // Starting page number
        
$iFitWidth    = (int) $this->_phpSheet->getPageSetup()->getFitToWidth();    // Fit to number of pages wide
        
$iFitHeight    = (int) $this->_phpSheet->getPageSetup()->getFitToHeight();    // Fit to number of pages high
        
$grbit        0x00;                 // Option flags
        
$iRes         0x0258;               // Print resolution
        
$iVRes        0x0258;               // Vertical print resolution

        
$numHdr       $this->_phpSheet->getPageMargins()->getHeader();  // Header Margin

        
$numFtr       $this->_phpSheet->getPageMargins()->getFooter();   // Footer Margin
        
$iCopies      0x01;                 // Number of copies

        
$fLeftToRight 0x0;                     // Print over then down

        // Page orientation
        
$fLandscape = ($this->_phpSheet->getPageSetup()->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) ?
            
0x0 0x1;

        
$fNoPls       0x0;                     // Setup not read from printer
        
$fNoColor     0x0;                     // Print black and white
        
$fDraft       0x0;                     // Print draft quality
        
$fNotes       0x0;                     // Print notes
        
$fNoOrient    0x0;                     // Orientation not set
        
$fUsePage     0x0;                     // Use custom starting page

        
$grbit           $fLeftToRight;
        
$grbit          |= $fLandscape    << 1;
        
$grbit          |= $fNoPls        << 2;
        
$grbit          |= $fNoColor      << 3;
        
$grbit          |= $fDraft        << 4;
        
$grbit          |= $fNotes        << 5;
        
$grbit          |= $fNoOrient     << 6;
        
$grbit          |= $fUsePage      << 7;

        
$numHdr pack("d"$numHdr);
        
$numFtr pack("d"$numFtr);
        if (
self::getByteOrder()) { // if it's Big Endian
            
$numHdr strrev($numHdr);
            
$numFtr strrev($numFtr);
        }

        
$header pack("vv"$record$length);
        
$data1  pack("vvvvvvvv"$iPaperSize,
                                   
$iScale,
                                   
$iPageStart,
                                   
$iFitWidth,
                                   
$iFitHeight,
                                   
$grbit,
                                   
$iRes,
                                   
$iVRes);
        
$data2  $numHdr.$numFtr;
        
$data3  pack("v"$iCopies);
        
$this->_append($header $data1 $data2 $data3);
    }

    
/**
     * Store the header caption BIFF record.
     */
    
private function _writeHeader()
    {
        
$record  0x0014;               // Record identifier

        /* removing for now
        // need to fix character count (multibyte!)
        if (strlen($this->_phpSheet->getHeaderFooter()->getOddHeader()) <= 255) {
            $str      = $this->_phpSheet->getHeaderFooter()->getOddHeader();       // header string
        } else {
            $str = '';
        }
        */

        
$recordData PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddHeader());
        
$length strlen($recordData);

        
$header   pack("vv"$record$length);

        
$this->_append($header $recordData);
    }

    
/**
     * Store the footer caption BIFF record.
     */
    
private function _writeFooter()
    {
        
$record  0x0015;               // Record identifier

        /* removing for now
        // need to fix character count (multibyte!)
        if (strlen($this->_phpSheet->getHeaderFooter()->getOddFooter()) <= 255) {
            $str = $this->_phpSheet->getHeaderFooter()->getOddFooter();
        } else {
            $str = '';
        }
        */

        
$recordData PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddFooter());
        
$length strlen($recordData);

        
$header    pack("vv"$record$length);

        
$this->_append($header $recordData);
    }

    
/**
     * Store the horizontal centering HCENTER BIFF record.
     *
     * @access private
     */
    
private function _writeHcenter()
    {
        
$record   0x0083;              // Record identifier
        
$length   0x0002;              // Bytes to follow

        
$fHCenter $this->_phpSheet->getPageSetup()->getHorizontalCentered() ? 0;     // Horizontal centering

        
$header    pack("vv"$record$length);
        
$data      pack("v",  $fHCenter);

        
$this->_append($header.$data);
    }

    
/**
     * Store the vertical centering VCENTER BIFF record.
     */
    
private function _writeVcenter()
    {
        
$record   0x0084;              // Record identifier
        
$length   0x0002;              // Bytes to follow

        
$fVCenter $this->_phpSheet->getPageSetup()->getVerticalCentered() ? 0;     // Horizontal centering

        
$header    pack("vv"$record$length);
        
$data      pack("v",  $fVCenter);
        
$this->_append($header $data);
    }

    
/**
     * Store the LEFTMARGIN BIFF record.
     */
    
private function _writeMarginLeft()
    {
        
$record  0x0026;                   // Record identifier
        
$length  0x0008;                   // Bytes to follow

        
$margin  $this->_phpSheet->getPageMargins()->getLeft();     // Margin in inches

        
$header    pack("vv",  $record$length);
        
$data      pack("d",   $margin);
        if (
self::getByteOrder()) { // if it's Big Endian
            
$data strrev($data);
        }

        
$this->_append($header $data);
    }

    
/**
     * Store the RIGHTMARGIN BIFF record.
     */
    
private function _writeMarginRight()
    {
        
$record  0x0027;                   // Record identifier
        
$length  0x0008;                   // Bytes to follow

        
$margin  $this->_phpSheet->getPageMargins()->getRight();     // Margin in inches

        
$header    pack("vv",  $record$length);
        
$data      pack("d",   $margin);
        if (
self::getByteOrder()) { // if it's Big Endian
            
$data strrev($data);
        }

        
$this->_append($header $data);
    }

    
/**
     * Store the TOPMARGIN BIFF record.
     */
    
private function _writeMarginTop()
    {
        
$record  0x0028;                   // Record identifier
        
$length  0x0008;                   // Bytes to follow

        
$margin  $this->_phpSheet->getPageMargins()->getTop();     // Margin in inches

        
$header    pack("vv",  $record$length);
        
$data      pack("d",   $margin);
        if (
self::getByteOrder()) { // if it's Big Endian
            
$data strrev($data);
        }

        
$this->_append($header $data);
    }

    
/**
     * Store the BOTTOMMARGIN BIFF record.
     */
    
private function _writeMarginBottom()
    {
        
$record  0x0029;                   // Record identifier
        
$length  0x0008;                   // Bytes to follow

        
$margin  $this->_phpSheet->getPageMargins()->getBottom();     // Margin in inches

        
$header    pack("vv",  $record$length);
        
$data      pack("d",   $margin);
        if (
self::getByteOrder()) { // if it's Big Endian
            
$data strrev($data);
        }

        
$this->_append($header $data);
    }

    
/**
     * Write the PRINTHEADERS BIFF record.
     */
    
private function _writePrintHeaders()
    {
        
$record      0x002a;                   // Record identifier
        
$length      0x0002;                   // Bytes to follow

        
$fPrintRwCol $this->_print_headers;     // Boolean flag

        
$header      pack("vv"$record$length);
        
$data        pack("v"$fPrintRwCol);
        
$this->_append($header $data);
    }

    
/**
     * Write the PRINTGRIDLINES BIFF record. Must be used in conjunction with the
     * GRIDSET record.
     */
    
private function _writePrintGridlines()
    {
        
$record      0x002b;                    // Record identifier
        
$length      0x0002;                    // Bytes to follow

        
$fPrintGrid  $this->_phpSheet->getPrintGridlines() ? 0;    // Boolean flag

        
$header      pack("vv"$record$length);
        
$data      pack("v"$fPrintGrid);
        
$this->_append($header $data);
    }

    
/**
     * Write the GRIDSET BIFF record. Must be used in conjunction with the
     * PRINTGRIDLINES record.
     */
    
private function _writeGridset()
    {
        
$record      0x0082;                        // Record identifier
        
$length      0x0002;                        // Bytes to follow

        
$fGridSet    = !$this->_phpSheet->getPrintGridlines();     // Boolean flag

        
$header      pack("vv",  $record$length);
        
$data        pack("v",   $fGridSet);
        
$this->_append($header $data);
    }

    
/**
     * Write the AUTOFILTERINFO BIFF record. This is used to configure the number of autofilter select used in the sheet.
     */
    
private function _writeAutoFilterInfo(){
        
$record      0x009D;                        // Record identifier
        
$length      0x0002;                        // Bytes to follow

        
$rangeBounds PHPExcel_Cell::rangeBoundaries($this->_phpSheet->getAutoFilter()->getRange());
        
$iNumFilters $rangeBounds[1][0] - $rangeBounds[0][0];

        
$header   pack("vv"$record$length);
        
$data     pack("v",  $iNumFilters);
        
$this->_append($header $data);
    }

    
/**
     * Write the GUTS BIFF record. This is used to configure the gutter margins
     * where Excel outline symbols are displayed. The visibility of the gutters is
     * controlled by a flag in WSBOOL.
     *
     * @see _writeWsbool()
     */
    
private  function _writeGuts()
    {
        
$record      0x0080;   // Record identifier
        
$length      0x0008;   // Bytes to follow

        
$dxRwGut     0x0000;   // Size of row gutter
        
$dxColGut    0x0000;   // Size of col gutter

        // determine maximum row outline level
        
$maxRowOutlineLevel 0;
        foreach (
$this->_phpSheet->getRowDimensions() as $rowDimension) {
            
$maxRowOutlineLevel max($maxRowOutlineLevel$rowDimension->getOutlineLevel());
        }

        
$col_level   0;

        
// Calculate the maximum column outline level. The equivalent calculation
        // for the row outline level is carried out in _writeRow().
        
$colcount count($this->_colinfo);
        for (
$i 0$i $colcount; ++$i) {
            
$col_level max($this->_colinfo[$i][5], $col_level);
        }

        
// Set the limits for the outline levels (0 <= x <= 7).
        
$col_level max(0min($col_level7));

        
// The displayed level is one greater than the max outline levels
        
if ($maxRowOutlineLevel) {
            ++
$maxRowOutlineLevel;
        }
        if (
$col_level) {
            ++
$col_level;
        }

        
$header      pack("vv",   $record$length);
        
$data        pack("vvvv"$dxRwGut$dxColGut$maxRowOutlineLevel$col_level);

        
$this->_append($header.$data);
    }

    
/**
     * Write the WSBOOL BIFF record, mainly for fit-to-page. Used in conjunction
     * with the SETUP record.
     */
    
private function _writeWsbool()
    {
        
$record      0x0081;   // Record identifier
        
$length      0x0002;   // Bytes to follow
        
$grbit       0x0000;

        
// The only option that is of interest is the flag for fit to page. So we
        // set all the options in one go.
        //
        // Set the option flags
        
$grbit |= 0x0001;                           // Auto page breaks visible
        
if ($this->_outline_style) {
            
$grbit |= 0x0020// Auto outline styles
        
}
        if (
$this->_phpSheet->getShowSummaryBelow()) {
            
$grbit |= 0x0040// Outline summary below
        
}
        if (
$this->_phpSheet->getShowSummaryRight()) {
            
$grbit |= 0x0080// Outline summary right
        
}
        if (
$this->_phpSheet->getPageSetup()->getFitToPage()) {
            
$grbit |= 0x0100// Page setup fit to page
        
}
        if (
$this->_outline_on) {
            
$grbit |= 0x0400// Outline symbols displayed
        
}

        
$header      pack("vv"$record$length);
        
$data        pack("v",  $grbit);
        
$this->_append($header $data);
    }

    
/**
     * Write the HORIZONTALPAGEBREAKS and VERTICALPAGEBREAKS BIFF records.
     */
    
private function _writeBreaks()
    {
        
// initialize
        
$vbreaks = array();
        
$hbreaks = array();

        foreach (
$this->_phpSheet->getBreaks() as $cell => $breakType) {
            
// Fetch coordinates
            
$coordinates PHPExcel_Cell::coordinateFromString($cell);

            
// Decide what to do by the type of break
            
switch ($breakType) {
                case 
PHPExcel_Worksheet::BREAK_COLUMN:
                    
// Add to list of vertical breaks
                    
$vbreaks[] = PHPExcel_Cell::columnIndexFromString($coordinates[0]) - 1;
                    break;

                case 
PHPExcel_Worksheet::BREAK_ROW:
                    
// Add to list of horizontal breaks
                    
$hbreaks[] = $coordinates[1];
                    break;

                case 
PHPExcel_Worksheet::BREAK_NONE:
                default:
                    
// Nothing to do
                    
break;
            }
        }

        
//horizontal page breaks
        
if (!empty($hbreaks)) {

            
// Sort and filter array of page breaks
            
sort($hbreaksSORT_NUMERIC);
            if (
$hbreaks[0] == 0) { // don't use first break if it's 0
                
array_shift($hbreaks);
            }

            
$record  0x001b;               // Record identifier
            
$cbrk    count($hbreaks);       // Number of page breaks
            
$length  $cbrk;      // Bytes to follow

            
$header  pack("vv"$record$length);
            
$data    pack("v",  $cbrk);

            
// Append each page break
            
foreach ($hbreaks as $hbreak) {
                
$data .= pack("vvv"$hbreak0x00000x00ff);
            }

            
$this->_append($header $data);
        }

        
// vertical page breaks
        
if (!empty($vbreaks)) {

            
// 1000 vertical pagebreaks appears to be an internal Excel 5 limit.
            // It is slightly higher in Excel 97/200, approx. 1026
            
$vbreaks array_slice($vbreaks01000);

            
// Sort and filter array of page breaks
            
sort($vbreaksSORT_NUMERIC);
            if (
$vbreaks[0] == 0) { // don't use first break if it's 0
                
array_shift($vbreaks);
            }

            
$record  0x001a;               // Record identifier
            
$cbrk    count($vbreaks);       // Number of page breaks
            
$length  $cbrk;      // Bytes to follow

            
$header  pack("vv",  $record$length);
            
$data    pack("v",   $cbrk);

            
// Append each page break
            
foreach ($vbreaks as $vbreak) {
                
$data .= pack("vvv"$vbreak0x00000xffff);
            }

            
$this->_append($header $data);
        }
    }

    
/**
     * Set the Biff PROTECT record to indicate that the worksheet is protected.
     */
    
private function _writeProtect()
    {
        
// Exit unless sheet protection has been specified
        
if (!$this->_phpSheet->getProtection()->getSheet()) {
            return;
        }

        
$record      0x0012;             // Record identifier
        
$length      0x0002;             // Bytes to follow

        
$fLock      1;    // Worksheet is protected

        
$header      pack("vv"$record$length);
        
$data      pack("v",  $fLock);

        
$this->_append($header.$data);
    }

    
/**
     * Write SCENPROTECT
     */
    
private function _writeScenProtect()
    {
        
// Exit if sheet protection is not active
        
if (!$this->_phpSheet->getProtection()->getSheet()) {
            return;
        }

        
// Exit if scenarios are not protected
        
if (!$this->_phpSheet->getProtection()->getScenarios()) {
            return;
        }

        
$record 0x00DD// Record identifier
        
$length 0x0002// Bytes to follow

        
$header pack('vv'$record$length);
        
$data pack('v'1);

        
$this->_append($header $data);
    }

    
/**
     * Write OBJECTPROTECT
     */
    
private function _writeObjectProtect()
    {
        
// Exit if sheet protection is not active
        
if (!$this->_phpSheet->getProtection()->getSheet()) {
            return;
        }

        
// Exit if objects are not protected
        
if (!$this->_phpSheet->getProtection()->getObjects()) {
            return;
        }

        
$record 0x0063// Record identifier
        
$length 0x0002// Bytes to follow

        
$header pack('vv'$record$length);
        
$data pack('v'1);

        
$this->_append($header $data);
    }

    
/**
     * Write the worksheet PASSWORD record.
     */
    
private function _writePassword()
    {
        
// Exit unless sheet protection and password have been specified
        
if (!$this->_phpSheet->getProtection()->getSheet() || !$this->_phpSheet->getProtection()->getPassword()) {
            return;
        }

        
$record      0x0013;               // Record identifier
        
$length      0x0002;               // Bytes to follow

        
$wPassword   hexdec($this->_phpSheet->getProtection()->getPassword());     // Encoded password

        
$header      pack("vv"$record$length);
        
$data        pack("v",  $wPassword);

        
$this->_append($header $data);
    }

    
/**
     * Insert a 24bit bitmap image in a worksheet.
     *
     * @access public
     * @param integer $row     The row we are going to insert the bitmap into
     * @param integer $col     The column we are going to insert the bitmap into
     * @param mixed   $bitmap  The bitmap filename or GD-image resource
     * @param integer $x       The horizontal position (offset) of the image inside the cell.
     * @param integer $y       The vertical position (offset) of the image inside the cell.
     * @param float   $scale_x The horizontal scale
     * @param float   $scale_y The vertical scale
     */
    
function insertBitmap($row$col$bitmap$x 0$y 0$scale_x 1$scale_y 1)
    {
        
$bitmap_array = (is_resource($bitmap) ? $this->_processBitmapGd($bitmap) : $this->_processBitmap($bitmap));
        list(
$width$height$size$data) = $bitmap_array//$this->_processBitmap($bitmap);

        // Scale the frame of the image.
        
$width  *= $scale_x;
        
$height *= $scale_y;

        
// Calculate the vertices of the image and write the OBJ record
        
$this->_positionImage($col$row$x$y$width$height);

        
// Write the IMDATA record to store the bitmap data
        
$record      0x007f;
        
$length      $size;
        
$cf          0x09;
        
$env         0x01;
        
$lcb         $size;

        
$header      pack("vvvvV"$record$length$cf$env$lcb);
        
$this->_append($header.$data);
    }

    
/**
     * Calculate the vertices that define the position of the image as required by
     * the OBJ record.
     *
     *         +------------+------------+
     *         |     A      |      B     |
     *   +-----+------------+------------+
     *   |     |(x1,y1)     |            |
     *   |  1  |(A1)._______|______      |
     *   |     |    |              |     |
     *   |     |    |              |     |
     *   +-----+----|    BITMAP    |-----+
     *   |     |    |              |     |
     *   |  2  |    |______________.     |
     *   |     |            |        (B2)|
     *   |     |            |     (x2,y2)|
     *   +---- +------------+------------+
     *
     * Example of a bitmap that covers some of the area from cell A1 to cell B2.
     *
     * Based on the width and height of the bitmap we need to calculate 8 vars:
     *     $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2.
     * The width and height of the cells are also variable and have to be taken into
     * account.
     * The values of $col_start and $row_start are passed in from the calling
     * function. The values of $col_end and $row_end are calculated by subtracting
     * the width and height of the bitmap from the width and height of the
     * underlying cells.
     * The vertices are expressed as a percentage of the underlying cell width as
     * follows (rhs values are in pixels):
     *
     *       x1 = X / W *1024
     *       y1 = Y / H *256
     *       x2 = (X-1) / W *1024
     *       y2 = (Y-1) / H *256
     *
     *       Where:  X is distance from the left side of the underlying cell
     *               Y is distance from the top of the underlying cell
     *               W is the width of the cell
     *               H is the height of the cell
     * The SDK incorrectly states that the height should be expressed as a
     *        percentage of 1024.
     *
     * @access private
     * @param integer $col_start Col containing upper left corner of object
     * @param integer $row_start Row containing top left corner of object
     * @param integer $x1        Distance to left side of object
     * @param integer $y1        Distance to top of object
     * @param integer $width     Width of image frame
     * @param integer $height    Height of image frame
     */
    
function _positionImage($col_start$row_start$x1$y1$width$height)
    {
        
// Initialise end cell to the same as the start cell
        
$col_end    $col_start;  // Col containing lower right corner of object
        
$row_end    $row_start;  // Row containing bottom right corner of object

        // Zero the specified offset if greater than the cell dimensions
        
if ($x1 >= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_start))) {
            
$x1 0;
        }
        if (
$y1 >= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_start 1)) {
            
$y1 0;
        }

        
$width      $width  $x1 -1;
        
$height     $height $y1 -1;

        
// Subtract the underlying cell widths to find the end cell of the image
        
while ($width >= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_end))) {
            
$width -= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_end));
            ++
$col_end;
        }

        
// Subtract the underlying cell heights to find the end cell of the image
        
while ($height >= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_end 1)) {
            
$height -= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_end 1);
            ++
$row_end;
        }

        
// Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell
        // with zero eight or width.
        //
        
if (PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_start)) == 0) {
            return;
        }
        if (
PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_end))   == 0) {
            return;
        }
        if (
PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_start 1) == 0) {
            return;
        }
        if (
PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_end 1)   == 0) {
            return;
        }

        
// Convert the pixel values to the percentage value expected by Excel
        
$x1 $x1     PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_start))   * 1024;
        
$y1 $y1     PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_start 1)   *  256;
        
$x2 $width  PHPExcel_Shared_Excel5::sizeCol($this->_phpSheetPHPExcel_Cell::stringFromColumnIndex($col_end))     * 1024// Distance to right side of object
        
$y2 $height PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet$row_end 1)     *  256// Distance to bottom of object

        
$this->_writeObjPicture($col_start$x1,
                                 
$row_start$y1,
                                 
$col_end$x2,
                                 
$row_end$y2);
    }

    
/**
     * Store the OBJ record that precedes an IMDATA record. This could be generalise
     * to support other Excel objects.
     *
     * @param integer $colL Column containing upper left corner of object
     * @param integer $dxL  Distance from left side of cell
     * @param integer $rwT  Row containing top left corner of object
     * @param integer $dyT  Distance from top of cell
     * @param integer $colR Column containing lower right corner of object
     * @param integer $dxR  Distance from right of cell
     * @param integer $rwB  Row containing bottom right corner of object
     * @param integer $dyB  Distance from bottom of cell
     */
    
private function _writeObjPicture($colL,$dxL,$rwT,$dyT,$colR,$dxR,$rwB,$dyB)
    {
        
$record      0x005d;   // Record identifier
        
$length      0x003c;   // Bytes to follow

        
$cObj        0x0001;   // Count of objects in file (set to 1)
        
$OT          0x0008;   // Object type. 8 = Picture
        
$id          0x0001;   // Object ID
        
$grbit       0x0614;   // Option flags

        
$cbMacro     0x0000;   // Length of FMLA structure
        
$Reserved1   0x0000;   // Reserved
        
$Reserved2   0x0000;   // Reserved

        
$icvBack     0x09;     // Background colour
        
$icvFore     0x09;     // Foreground colour
        
$fls         0x00;     // Fill pattern
        
$fAuto       0x00;     // Automatic fill
        
$icv         0x08;     // Line colour
        
$lns         0xff;     // Line style
        
$lnw         0x01;     // Line weight
        
$fAutoB      0x00;     // Automatic border
        
$frs         0x0000;   // Frame style
        
$cf          0x0009;   // Image format, 9 = bitmap
        
$Reserved3   0x0000;   // Reserved
        
$cbPictFmla  0x0000;   // Length of FMLA structure
        
$Reserved4   0x0000;   // Reserved
        
$grbit2      0x0001;   // Option flags
        
$Reserved5   0x0000;   // Reserved


        
$header      pack("vv"$record$length);
        
$data        pack("V"$cObj);
        
$data       .= pack("v"$OT);
        
$data       .= pack("v"$id);
        
$data       .= pack("v"$grbit);
        
$data       .= pack("v"$colL);
        
$data       .= pack("v"$dxL);
        
$data       .= pack("v"$rwT);
        
$data       .= pack("v"$dyT);
        
$data       .= pack("v"$colR);
        
$data       .= pack("v"$dxR);
        
$data       .= pack("v"$rwB);
        
$data       .= pack("v"$dyB);
        
$data       .= pack("v"$cbMacro);
        
$data       .= pack("V"$Reserved1);
        
$data       .= pack("v"$Reserved2);
        
$data       .= pack("C"$icvBack);
        
$data       .= pack("C"$icvFore);
        
$data       .= pack("C"$fls);
        
$data       .= pack("C"$fAuto);
        
$data       .= pack("C"$icv);
        
$data       .= pack("C"$lns);
        
$data       .= pack("C"$lnw);
        
$data       .= pack("C"$fAutoB);
        
$data       .= pack("v"$frs);
        
$data       .= pack("V"$cf);
        
$data       .= pack("v"$Reserved3);
        
$data       .= pack("v"$cbPictFmla);
        
$data       .= pack("v"$Reserved4);
        
$data       .= pack("v"$grbit2);
        
$data       .= pack("V"$Reserved5);

        
$this->_append($header $data);
    }

    
/**
     * Convert a GD-image into the internal format.
     *
     * @access private
     * @param resource $image The image to process
     * @return array Array with data and properties of the bitmap
     */
    
function _processBitmapGd($image) {
        
$width imagesx($image);
        
$height imagesy($image);

        
$data pack("Vvvvv"0x000c$width$height0x010x18);
        for (
$j=$height$j--; ) {
            for (
$i=0$i $width; ++$i) {
                
$color imagecolorsforindex($imageimagecolorat($image$i$j));
                foreach (array(
"red""green""blue") as $key) {
                    
$color[$key] = $color[$key] + round((255 $color[$key]) * $color["alpha"] / 127);
                }
                
$data .= chr($color["blue"]) . chr($color["green"]) . chr($color["red"]);
            }
            if (
3*$width 4) {
                
$data .= str_repeat("\x00"3*$width 4);
            }
        }

        return array(
$width$heightstrlen($data), $data);
    }

    
/**
     * Convert a 24 bit bitmap into the modified internal format used by Windows.
     * This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the
     * MSDN library.
     *
     * @access private
     * @param string $bitmap The bitmap to process
     * @return array Array with data and properties of the bitmap
     */
    
function _processBitmap($bitmap)
    {
        
// Open file.
        
$bmp_fd = @fopen($bitmap,"rb");
        if (!
$bmp_fd) {
            throw new 
PHPExcel_Writer_Exception("Couldn't import $bitmap");
        }

        
// Slurp the file into a string.
        
$data fread($bmp_fdfilesize($bitmap));

        
// Check that the file is big enough to be a bitmap.
        
if (strlen($data) <= 0x36) {
            throw new 
PHPExcel_Writer_Exception("$bitmap doesn't contain enough data.\n");
        }

        
// The first 2 bytes are used to identify the bitmap.
        
$identity unpack("A2ident"$data);
        if (
$identity['ident'] != "BM") {
            throw new 
PHPExcel_Writer_Exception("$bitmap doesn't appear to be a valid bitmap image.\n");
        }

        
// Remove bitmap data: ID.
        
$data substr($data2);

        
// Read and remove the bitmap size. This is more reliable than reading
        // the data size at offset 0x22.
        //
        
$size_array   unpack("Vsa"substr($data04));
        
$size   $size_array['sa'];
        
$data   substr($data4);
        
$size  -= 0x36// Subtract size of bitmap header.
        
$size  += 0x0C// Add size of BIFF header.

        // Remove bitmap data: reserved, offset, header length.
        
$data substr($data12);

        
// Read and remove the bitmap width and height. Verify the sizes.
        
$width_and_height unpack("V2"substr($data08));
        
$width  $width_and_height[1];
        
$height $width_and_height[2];
        
$data   substr($data8);
        if (
$width 0xFFFF) {
            throw new 
PHPExcel_Writer_Exception("$bitmap: largest image width supported is 65k.\n");
        }
        if (
$height 0xFFFF) {
            throw new 
PHPExcel_Writer_Exception("$bitmap: largest image height supported is 65k.\n");
        }

        
// Read and remove the bitmap planes and bpp data. Verify them.
        
$planes_and_bitcount unpack("v2"substr($data04));
        
$data substr($data4);
        if (
$planes_and_bitcount[2] != 24) { // Bitcount
            
throw new PHPExcel_Writer_Exception("$bitmap isn't a 24bit true color bitmap.\n");
        }
        if (
$planes_and_bitcount[1] != 1) {
            throw new 
PHPExcel_Writer_Exception("$bitmap: only 1 plane supported in bitmap image.\n");
        }

        
// Read and remove the bitmap compression. Verify compression.
        
$compression unpack("Vcomp"substr($data04));
        
$data substr($data4);

        
//$compression = 0;
        
if ($compression['comp'] != 0) {
            throw new 
PHPExcel_Writer_Exception("$bitmap: compression not supported in bitmap image.\n");
        }

        
// Remove bitmap data: data size, hres, vres, colours, imp. colours.
        
$data substr($data20);

        
// Add the BITMAPCOREHEADER data
        
$header  pack("Vvvvv"0x000c$width$height0x010x18);
        
$data    $header $data;

        return (array(
$width$height$size$data));
    }

    
/**
     * Store the window zoom factor. This should be a reduced fraction but for
     * simplicity we will store all fractions with a numerator of 100.
     */
    
private function _writeZoom()
    {
        
// If scale is 100 we don't need to write a record
        
if ($this->_phpSheet->getSheetView()->getZoomScale() == 100) {
            return;
        }

        
$record      0x00A0;               // Record identifier
        
$length      0x0004;               // Bytes to follow

        
$header      pack("vv"$record$length);
        
$data        pack("vv"$this->_phpSheet->getSheetView()->getZoomScale(), 100);
        
$this->_append($header $data);
    }

    
/**
     * Get Escher object
     *
     * @return PHPExcel_Shared_Escher
     */
    
public function getEscher()
    {
        return 
$this->_escher;
    }

    
/**
     * Set Escher object
     *
     * @param PHPExcel_Shared_Escher $pValue
     */
    
public function setEscher(PHPExcel_Shared_Escher $pValue null)
    {
        
$this->_escher $pValue;
    }

    
/**
     * Write MSODRAWING record
     */
    
private function _writeMsoDrawing()
    {
        
// write the Escher stream if necessary
        
if (isset($this->_escher)) {
            
$writer = new PHPExcel_Writer_Excel5_Escher($this->_escher);
            
$data $writer->close();
            
$spOffsets $writer->getSpOffsets();
            
$spTypes $writer->getSpTypes();
            
// write the neccesary MSODRAWING, OBJ records

            // split the Escher stream
            
$spOffsets[0] = 0;
            
$nm count($spOffsets) - 1// number of shapes excluding first shape
            
for ($i 1$i <= $nm; ++$i) {
                
// MSODRAWING record
                
$record 0x00EC;            // Record identifier

                // chunk of Escher stream for one shape
                
$dataChunk substr($data$spOffsets[$i -1], $spOffsets[$i] - $spOffsets[$i 1]);

                
$length strlen($dataChunk);
                
$header pack("vv"$record$length);

                
$this->_append($header $dataChunk);

                
// OBJ record
                
$record 0x005D// record identifier
                
$objData '';

                
// ftCmo
                
if($spTypes[$i] == 0x00C9){
                    
// Add ftCmo (common object data) subobject
                    
$objData .=
                        
pack('vvvvvVVV'
                                
0x0015    // 0x0015 = ftCmo
                                
0x0012    // length of ftCmo data
                                
0x0014    // object type, 0x0014 = filter
                                
$i        // object id number, Excel seems to use 1-based index, local for the sheet
                                
0x2101    // option flags, 0x2001 is what OpenOffice.org uses
                                
0            // reserved
                                
0            // reserved
                                
0            // reserved
                        
);

                    
// Add ftSbs Scroll bar subobject
                    
$objData .= pack('vv'0x00C0x0014);
                    
$objData .= pack('H*''0000000000000000640001000A00000010000100');
                    
// Add ftLbsData (List box data) subobject
                    
$objData .= pack('vv'0x00130x1FEE);
                    
$objData .= pack('H*''00000000010001030000020008005700');
                }
                else {
                    
// Add ftCmo (common object data) subobject
                    
$objData .=
                        
pack('vvvvvVVV'
                            
0x0015    // 0x0015 = ftCmo
                            
0x0012    // length of ftCmo data
                            
0x0008    // object type, 0x0008 = picture
                            
$i        // object id number, Excel seems to use 1-based index, local for the sheet
                            
0x6011    // option flags, 0x6011 is what OpenOffice.org uses
                            
0            // reserved
                            
0            // reserved
                            
0            // reserved
                        
);
                }

                
// ftEnd
                
$objData .=
                    
pack('vv'
                        
0x0000    // 0x0000 = ftEnd
                        
0x0000    // length of ftEnd data
                    
);

                
$length strlen($objData);
                
$header pack('vv'$record$length);
                
$this->_append($header $objData);
            }
        }
    }

    
/**
     * Store the DATAVALIDATIONS and DATAVALIDATION records.
     */
    
private function _writeDataValidity()
    {
        
// Datavalidation collection
        
$dataValidationCollection $this->_phpSheet->getDataValidationCollection();

        
// Write data validations?
        
if (!empty($dataValidationCollection)) {

            
// DATAVALIDATIONS record
            
$record 0x01B2;      // Record identifier
            
$length      0x0012;      // Bytes to follow

            
$grbit  0x0000;       // Prompt box at cell, no cached validity data at DV records
            
$horPos      0x00000000;  // Horizontal position of prompt box, if fixed position
            
$verPos      0x00000000;  // Vertical position of prompt box, if fixed position
            
$objId  0xFFFFFFFF;  // Object identifier of drop down arrow object, or -1 if not visible

            
$header      pack('vv'$record$length);
            
$data        pack('vVVVV'$grbit$horPos$verPos$objId,
                                         
count($dataValidationCollection));
            
$this->_append($header.$data);

            
// DATAVALIDATION records
            
$record 0x01BE;              // Record identifier

            
foreach ($dataValidationCollection as $cellCoordinate => $dataValidation) {
                
// initialize record data
                
$data '';

                
// options
                
$options 0x00000000;

                
// data type
                
$type $dataValidation->getType();
                switch (
$type) {
                    case 
PHPExcel_Cell_DataValidation::TYPE_NONE:        $type 0x00;    break;
                    case 
PHPExcel_Cell_DataValidation::TYPE_WHOLE:        $type 0x01;    break;
                    case 
PHPExcel_Cell_DataValidation::TYPE_DECIMAL:    $type 0x02;    break;
                    case 
PHPExcel_Cell_DataValidation::TYPE_LIST:        $type 0x03;    break;
                    case 
PHPExcel_Cell_DataValidation::TYPE_DATE:        $type 0x04;    break;
                    case 
PHPExcel_Cell_DataValidation::TYPE_TIME:        $type 0x05;    break;
                    case 
PHPExcel_Cell_DataValidation::TYPE_TEXTLENGTH:    $type 0x06;    break;
                    case 
PHPExcel_Cell_DataValidation::TYPE_CUSTOM:        $type 0x07;    break;
                }
                
$options |= $type << 0;

                
// error style
                
$errorStyle $dataValidation->getType();
                switch (
$errorStyle) {
                    case 
PHPExcel_Cell_DataValidation::STYLE_STOP:            $errorStyle 0x00;        break;
                    case 
PHPExcel_Cell_DataValidation::STYLE_WARNING:        $errorStyle 0x01;        break;
                    case 
PHPExcel_Cell_DataValidation::STYLE_INFORMATION:    $errorStyle 0x02;        break;
                }
                
$options |= $errorStyle << 4;

                
// explicit formula?
                
if ($type == 0x03 && preg_match('/^\".*\"$/'$dataValidation->getFormula1())) {
                    
$options |= 0x01                << 7;
                }

                
// empty cells allowed
                
$options |= $dataValidation->getAllowBlank() << 8;

                
// show drop down
                
$options |= (!$dataValidation->getShowDropDown()) << 9;

                
// show input message
                
$options |= $dataValidation->getShowInputMessage() << 18;

                
// show error message
                
$options |= $dataValidation->getShowErrorMessage() << 19;

                
// condition operator
                
$operator $dataValidation->getOperator();
                switch (
$operator) {
                    case 
PHPExcel_Cell_DataValidation::OPERATOR_BETWEEN$operator 0x00            ;    break;
                    case 
PHPExcel_Cell_DataValidation::OPERATOR_NOTBETWEEN$operator 0x01        ;    break;
                    case 
PHPExcel_Cell_DataValidation::OPERATOR_EQUAL$operator 0x02                ;    break;
                    case 
PHPExcel_Cell_DataValidation::OPERATOR_NOTEQUAL$operator 0x03            ;    break;
                    case 
PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHAN$operator 0x04        ;    break;
                    case 
PHPExcel_Cell_DataValidation::OPERATOR_LESSTHAN$operator 0x05            ;    break;
                    case 
PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHANOREQUAL$operator 0x06;    break;
                    case 
PHPExcel_Cell_DataValidation::OPERATOR_LESSTHANOREQUAL$operator 0x07    ;    break;
                }
                
$options |= $operator << 20;

                
$data        pack('V'$options);

                
// prompt title
                
$promptTitle $dataValidation->getPromptTitle() !== '' ?
                    
$dataValidation->getPromptTitle() : chr(0);
                
$data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($promptTitle);

                
// error title
                
$errorTitle $dataValidation->getErrorTitle() !== '' ?
                    
$dataValidation->getErrorTitle() : chr(0);
                
$data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($errorTitle);

                
// prompt text
                
$prompt $dataValidation->getPrompt() !== '' ?
                    
$dataValidation->getPrompt() : chr(0);
                
$data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($prompt);

                
// error text
                
$error $dataValidation->getError() !== '' ?
                    
$dataValidation->getError() : chr(0);
                
$data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($error);

                
// formula 1
                
try {
                    
$formula1 $dataValidation->getFormula1();
                    if (
$type == 0x03) { // list type
                        
$formula1 str_replace(','chr(0), $formula1);
                    }
                    
$this->_parser->parse($formula1);
                    
$formula1 $this->_parser->toReversePolish();
                    
$sz1 strlen($formula1);

                } catch(
PHPExcel_Exception $e) {
                    
$sz1 0;
                    
$formula1 '';
                }
                
$data .= pack('vv'$sz10x0000);
                
$data .= $formula1;

                
// formula 2
                
try {
                    
$formula2 $dataValidation->getFormula2();
                    if (
$formula2 === '') {
                        throw new 
PHPExcel_Writer_Exception('No formula2');
                    }
                    
$this->_parser->parse($formula2);
                    
$formula2 $this->_parser->toReversePolish();
                    
$sz2 strlen($formula2);

                } catch(
PHPExcel_Exception $e) {
                    
$sz2 0;
                    
$formula2 '';
                }
                
$data .= pack('vv'$sz20x0000);
                
$data .= $formula2;

                
// cell range address list
                
$data .= pack('v'0x0001);
                
$data .= $this->_writeBIFF8CellRangeAddressFixed($cellCoordinate);

                
$length strlen($data);
            
$header pack("vv"$record$length);

                
$this->_append($header $data);
            }
        }
    }

    
/**
     * Map Error code
     *
     * @param string $errorCode
     * @return int
     */
    
private static function _mapErrorCode($errorCode) {
        switch (
$errorCode) {
            case 
'#NULL!':    return 0x00;
            case 
'#DIV/0!':    return 0x07;
            case 
'#VALUE!':    return 0x0F;
            case 
'#REF!':    return 0x17;
            case 
'#NAME?':    return 0x1D;
            case 
'#NUM!':    return 0x24;
            case 
'#N/A':    return 0x2A;
        }

        return 
0;
    }

    
/**
     * Write PLV Record
     */
    
private function _writePageLayoutView(){
        
$record      0x088B;               // Record identifier
        
$length      0x0010;               // Bytes to follow

        
$rt         0x088B// 2
        
$grbitFrt   0x0000// 2
        
$reserved   0x0000000000000000// 8
        
$wScalvePLV $this->_phpSheet->getSheetView()->getZoomScale(); // 2

        // The options flags that comprise $grbit
        
if($this->_phpSheet->getSheetView()->getView() == PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT){
            
$fPageLayoutView   1;
        } else {
            
$fPageLayoutView   0;
        }
        
$fRulerVisible     0;
        
$fWhitespaceHidden 0;

        
$grbit      $fPageLayoutView// 2
        
$grbit        |= $fRulerVisible       << 1;
        
$grbit        |= $fWhitespaceHidden  << 3;

        
$header      pack("vv"$record$length);
        
$data      pack("vvVVvv"$rt$grbitFrt0x000000000x00000000$wScalvePLV$grbit);
        
$this->_append($header $data);
    }

    
/**
     * Write CFRule Record
     * @param PHPExcel_Style_Conditional $conditional
     */
    
private function _writeCFRule(PHPExcel_Style_Conditional $conditional){
        
$record      0x01B1;               // Record identifier

        // $type : Type of the CF
        // $operatorType : Comparison operator
        
if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION){
            
$type 0x02;
            
$operatorType 0x00;
        } else if(
$conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){
            
$type 0x01;

            switch (
$conditional->getOperatorType()){
                case 
PHPExcel_Style_Conditional::OPERATOR_NONE:
                    
$operatorType 0x00;
                    break;
                case 
PHPExcel_Style_Conditional::OPERATOR_EQUAL:
                    
$operatorType 0x03;
                    break;
                case 
PHPExcel_Style_Conditional::OPERATOR_GREATERTHAN:
                    
$operatorType 0x05;
                    break;
                case 
PHPExcel_Style_Conditional::OPERATOR_GREATERTHANOREQUAL:
                    
$operatorType 0x07;
                    break;
                case 
PHPExcel_Style_Conditional::OPERATOR_LESSTHAN:
                    
$operatorType 0x06;
                    break;
                case 
PHPExcel_Style_Conditional::OPERATOR_LESSTHANOREQUAL:
                    
$operatorType 0x08;
                    break;
                case 
PHPExcel_Style_Conditional::OPERATOR_NOTEQUAL:
                    
$operatorType 0x04;
                    break;
                case 
PHPExcel_Style_Conditional::OPERATOR_BETWEEN:
                    
$operatorType 0x01;
                    break;
                    
// not OPERATOR_NOTBETWEEN 0x02
            
}
        }

        
// $szValue1 : size of the formula data for first value or formula
        // $szValue2 : size of the formula data for second value or formula
        
$arrConditions $conditional->getConditions();
        
$numConditions sizeof($arrConditions);
        if(
$numConditions == 1){
            
$szValue1 = ($arrConditions[0] <= 65535 0x0000);
            
$szValue2 0x0000;
            
$operand1 pack('Cv'0x1E$arrConditions[0]);
            
$operand2 null;
        } else if(
$numConditions == && ($conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_BETWEEN)){
            
$szValue1 = ($arrConditions[0] <= 65535 0x0000);
            
$szValue2 = ($arrConditions[1] <= 65535 0x0000);
            
$operand1 pack('Cv'0x1E$arrConditions[0]);
            
$operand2 pack('Cv'0x1E$arrConditions[1]);
        } else {
            
$szValue1 0x0000;
            
$szValue2 0x0000;
            
$operand1 null;
            
$operand2 null;
        }

        
// $flags : Option flags
        // Alignment
        
$bAlignHz = ($conditional->getStyle()->getAlignment()->getHorizontal() == null 0);
        
$bAlignVt = ($conditional->getStyle()->getAlignment()->getVertical() == null 0);
        
$bAlignWrapTx = ($conditional->getStyle()->getAlignment()->getWrapText() == false 0);
        
$bTxRotation = ($conditional->getStyle()->getAlignment()->getTextRotation() == null 0);
        
$bIndent = ($conditional->getStyle()->getAlignment()->getIndent() == 0);
        
$bShrinkToFit = ($conditional->getStyle()->getAlignment()->getShrinkToFit() == false 0);
        if(
$bAlignHz == || $bAlignVt == || $bAlignWrapTx == || $bTxRotation == || $bIndent == || $bShrinkToFit == 0){
            
$bFormatAlign 1;
        } else {
            
$bFormatAlign 0;
        }
        
// Protection
        
$bProtLocked = ($conditional->getStyle()->getProtection()->getLocked() == null 0);
        
$bProtHidden = ($conditional->getStyle()->getProtection()->getHidden() == null 0);
        if(
$bProtLocked == || $bProtHidden == 0){
            
$bFormatProt 1;
        } else {
            
$bFormatProt 0;
        }
        
// Border
        
$bBorderLeft = ($conditional->getStyle()->getBorders()->getLeft()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK
                        
&& $conditional->getStyle()->getBorders()->getLeft()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE 0);
        
$bBorderRight = ($conditional->getStyle()->getBorders()->getRight()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK
                        
&& $conditional->getStyle()->getBorders()->getRight()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE 0);
        
$bBorderTop = ($conditional->getStyle()->getBorders()->getTop()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK
                        
&& $conditional->getStyle()->getBorders()->getTop()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE 0);
        
$bBorderBottom = ($conditional->getStyle()->getBorders()->getBottom()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK
                        
&& $conditional->getStyle()->getBorders()->getBottom()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE 0);
        if(
$bBorderLeft == || $bBorderRight == || $bBorderTop == || $bBorderBottom == 0){
            
$bFormatBorder 1;
        } else {
            
$bFormatBorder 0;
        }
        
// Pattern
        
$bFillStyle = ($conditional->getStyle()->getFill()->getFillType() == null 1);
        
$bFillColor = ($conditional->getStyle()->getFill()->getStartColor()->getARGB() == null 1);
        
$bFillColorBg = ($conditional->getStyle()->getFill()->getEndColor()->getARGB() == null 1);
        if(
$bFillStyle == || $bFillColor == || $bFillColorBg == 0){
            
$bFormatFill 1;
        } else {
            
$bFormatFill 0;
        }
        
// Font
        
if($conditional->getStyle()->getFont()->getName() != null
            
|| $conditional->getStyle()->getFont()->getSize() != null
            
|| $conditional->getStyle()->getFont()->getBold() != null
            
|| $conditional->getStyle()->getFont()->getItalic() != null
            
|| $conditional->getStyle()->getFont()->getSuperScript() != null
            
|| $conditional->getStyle()->getFont()->getSubScript() != null
            
|| $conditional->getStyle()->getFont()->getUnderline() != null
            
|| $conditional->getStyle()->getFont()->getStrikethrough() != null
            
|| $conditional->getStyle()->getFont()->getColor()->getARGB() != null){
            
$bFormatFont 1;
        } else {
            
$bFormatFont 0;
        }
        
// Alignment
        
$flags 0;
        
$flags |= (== $bAlignHz      0x00000001 0);
        
$flags |= (== $bAlignVt      0x00000002 0);
        
$flags |= (== $bAlignWrapTx  0x00000004 0);
        
$flags |= (== $bTxRotation   0x00000008 0);
        
// Justify last line flag
        
$flags |= (== 1              0x00000010 0);
        
$flags |= (== $bIndent       0x00000020 0);
        
$flags |= (== $bShrinkToFit  0x00000040 0);
        
// Default
        
$flags |= (== 1              0x00000080 0);
        
// Protection
        
$flags |= (== $bProtLocked   0x00000100 0);
        
$flags |= (== $bProtHidden   0x00000200 0);
        
// Border
        
$flags |= (== $bBorderLeft   0x00000400 0);
        
$flags |= (== $bBorderRight  0x00000800 0);
        
$flags |= (== $bBorderTop    0x00001000 0);
        
$flags |= (== $bBorderBottom 0x00002000 0);
        
$flags |= (== 1              0x00004000 0); // Top left to Bottom right border
        
$flags |= (== 1              0x00008000 0); // Bottom left to Top right border
        // Pattern
        
$flags |= (== $bFillStyle    0x00010000 0);
        
$flags |= (== $bFillColor    0x00020000 0);
        
$flags |= (== $bFillColorBg  0x00040000 0);
        
$flags |= (== 1              0x00380000 0);
        
// Font
        
$flags |= (== $bFormatFont   0x04000000 0);
        
// Alignment :
        
$flags |= (== $bFormatAlign  0x08000000 0);
        
// Border
        
$flags |= (== $bFormatBorder 0x10000000 0);
        
// Pattern
        
$flags |= (== $bFormatFill   0x20000000 0);
        
// Protection
        
$flags |= (== $bFormatProt   0x40000000 0);
        
// Text direction
        
$flags |= (== 0              0x80000000 0);

        
// Data Blocks
        
if($bFormatFont == 1){
            
// Font Name
            
if($conditional->getStyle()->getFont()->getName() == null){
                
$dataBlockFont =  pack('VVVVVVVV'0x000000000x000000000x000000000x000000000x000000000x000000000x000000000x00000000);
                
$dataBlockFont .= pack('VVVVVVVV'0x000000000x000000000x000000000x000000000x000000000x000000000x000000000x00000000);
            } else {
                
$dataBlockFont PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($conditional->getStyle()->getFont()->getName());
            }
            
// Font Size
            
if($conditional->getStyle()->getFont()->getSize() == null){
                
$dataBlockFont .= pack('V'20 11);
            } else {
                
$dataBlockFont .= pack('V'20 $conditional->getStyle()->getFont()->getSize());
            }
            
// Font Options
            
$dataBlockFont .= pack('V'0);
            
// Font weight
            
if($conditional->getStyle()->getFont()->getBold() == true){
                
$dataBlockFont .= pack('v'0x02BC);
            } else {
                
$dataBlockFont .= pack('v'0x0190);
            }
            
// Escapement type
            
if($conditional->getStyle()->getFont()->getSubScript() == true){
                
$dataBlockFont .= pack('v'0x02);
                
$fontEscapement 0;
            } else if(
$conditional->getStyle()->getFont()->getSuperScript() == true){
                
$dataBlockFont .= pack('v'0x01);
                
$fontEscapement 0;
            } else {
                
$dataBlockFont .= pack('v'0x00);
                
$fontEscapement 1;
            }
            
// Underline type
            
switch ($conditional->getStyle()->getFont()->getUnderline()){
                case 
PHPExcel_Style_Font::UNDERLINE_NONE             $dataBlockFont .= pack('C'0x00); $fontUnderline 0; break;
                case 
PHPExcel_Style_Font::UNDERLINE_DOUBLE           $dataBlockFont .= pack('C'0x02); $fontUnderline 0; break;
                case 
PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING $dataBlockFont .= pack('C'0x22); $fontUnderline 0; break;
                case 
PHPExcel_Style_Font::UNDERLINE_SINGLE           $dataBlockFont .= pack('C'0x01); $fontUnderline 0; break;
                case 
PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING $dataBlockFont .= pack('C'0x21); $fontUnderline 0; break;
                default                                              : 
$dataBlockFont .= pack('C'0x00); $fontUnderline 1; break;
            }
            
// Not used (3)
            
$dataBlockFont .= pack('vC'0x00000x00);
            
// Font color index
            
switch ($conditional->getStyle()->getFont()->getColor()->getRGB()) {
                case 
'000000'$colorIdx 0x08; break;
                case 
'FFFFFF'$colorIdx 0x09; break;
                case 
'FF0000'$colorIdx 0x0A; break;
                case 
'00FF00'$colorIdx 0x0B; break;
                case 
'0000FF'$colorIdx 0x0C; break;
                case 
'FFFF00'$colorIdx 0x0D; break;
                case 
'FF00FF'$colorIdx 0x0E; break;
                case 
'00FFFF'$colorIdx 0x0F; break;
                case 
'800000'$colorIdx 0x10; break;
                case 
'008000'$colorIdx 0x11; break;
                case 
'000080'$colorIdx 0x12; break;
                case 
'808000'$colorIdx 0x13; break;
                case 
'800080'$colorIdx 0x14; break;
                case 
'008080'$colorIdx 0x15; break;
                case 
'C0C0C0'$colorIdx 0x16; break;
                case 
'808080'$colorIdx 0x17; break;
                case 
'9999FF'$colorIdx 0x18; break;
                case 
'993366'$colorIdx 0x19; break;
                case 
'FFFFCC'$colorIdx 0x1A; break;
                case 
'CCFFFF'$colorIdx 0x1B; break;
                case 
'660066'$colorIdx 0x1C; break;
                case 
'FF8080'$colorIdx 0x1D; break;
                case 
'0066CC'$colorIdx 0x1E; break;
                case 
'CCCCFF'$colorIdx 0x1F; break;
                case 
'000080'$colorIdx 0x20; break;
                case 
'FF00FF'$colorIdx 0x21; break;
                case 
'FFFF00'$colorIdx 0x22; break;
                case 
'00FFFF'$colorIdx 0x23; break;
                case 
'800080'$colorIdx 0x24; break;
                case 
'800000'$colorIdx 0x25; break;
                case 
'008080'$colorIdx 0x26; break;
                case 
'0000FF'$colorIdx 0x27; break;
                case 
'00CCFF'$colorIdx 0x28; break;
                case 
'CCFFFF'$colorIdx 0x29; break;
                case 
'CCFFCC'$colorIdx 0x2A; break;
                case 
'FFFF99'$colorIdx 0x2B; break;
                case 
'99CCFF'$colorIdx 0x2C; break;
                case 
'FF99CC'$colorIdx 0x2D; break;
                case 
'CC99FF'$colorIdx 0x2E; break;
                case 
'FFCC99'$colorIdx 0x2F; break;
                case 
'3366FF'$colorIdx 0x30; break;
                case 
'33CCCC'$colorIdx 0x31; break;
                case 
'99CC00'$colorIdx 0x32; break;
                case 
'FFCC00'$colorIdx 0x33; break;
                case 
'FF9900'$colorIdx 0x34; break;
                case 
'FF6600'$colorIdx 0x35; break;
                case 
'666699'$colorIdx 0x36; break;
                case 
'969696'$colorIdx 0x37; break;
                case 
'003366'$colorIdx 0x38; break;
                case 
'339966'$colorIdx 0x39; break;
                case 
'003300'$colorIdx 0x3A; break;
                case 
'333300'$colorIdx 0x3B; break;
                case 
'993300'$colorIdx 0x3C; break;
                case 
'993366'$colorIdx 0x3D; break;
                case 
'333399'$colorIdx 0x3E; break;
                case 
'333333'$colorIdx 0x3F; break;
                default: 
$colorIdx 0x00; break;
            }
            
$dataBlockFont .= pack('V'$colorIdx);
            
// Not used (4)
            
$dataBlockFont .= pack('V'0x00000000);
            
// Options flags for modified font attributes
            
$optionsFlags 0;
            
$optionsFlagsBold = ($conditional->getStyle()->getFont()->getBold() == null 0);
            
$optionsFlags |= (== $optionsFlagsBold  0x00000002 0);
            
$optionsFlags |= (== 1                  0x00000008 0);
            
$optionsFlags |= (== 1                  0x00000010 0);
            
$optionsFlags |= (== 0                  0x00000020 0);
            
$optionsFlags |= (== 1                  0x00000080 0);
            
$dataBlockFont .= pack('V'$optionsFlags);
            
// Escapement type
            
$dataBlockFont .= pack('V'$fontEscapement);
            
// Underline type
            
$dataBlockFont .= pack('V'$fontUnderline);
            
// Always
            
$dataBlockFont .= pack('V'0x00000000);
            
// Always
            
$dataBlockFont .= pack('V'0x00000000);
            
// Not used (8)
            
$dataBlockFont .= pack('VV'0x000000000x00000000);
            
// Always
            
$dataBlockFont .= pack('v'0x0001);
        }
        if(
$bFormatAlign == 1){
            
$blockAlign 0;
            
// Alignment and text break
            
switch ($conditional->getStyle()->getAlignment()->getHorizontal()){
                case 
PHPExcel_Style_Alignment::HORIZONTAL_GENERAL             $blockAlign 0; break;
                case 
PHPExcel_Style_Alignment::HORIZONTAL_LEFT                $blockAlign 1; break;
                case 
PHPExcel_Style_Alignment::HORIZONTAL_RIGHT                $blockAlign 3; break;
                case 
PHPExcel_Style_Alignment::HORIZONTAL_CENTER            $blockAlign 2; break;
                case 
PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS    $blockAlign 6; break;
                case 
PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY            $blockAlign 5; break;
            }
            if(
$conditional->getStyle()->getAlignment()->getWrapText() == true){
                
$blockAlign |= << 3;
            } else {
                
$blockAlign |= << 3;
            }
            switch (
$conditional->getStyle()->getAlignment()->getVertical()){
                case 
PHPExcel_Style_Alignment::VERTICAL_BOTTOM                 $blockAlign << 4; break;
                case 
PHPExcel_Style_Alignment::VERTICAL_TOP                    $blockAlign << 4; break;
                case 
PHPExcel_Style_Alignment::VERTICAL_CENTER                $blockAlign << 4; break;
                case 
PHPExcel_Style_Alignment::VERTICAL_JUSTIFY                $blockAlign << 4; break;
            }
            
$blockAlign |= << 7;

            
// Text rotation angle
            
$blockRotation $conditional->getStyle()->getAlignment()->getTextRotation();

            
// Indentation
            
$blockIndent $conditional->getStyle()->getAlignment()->getIndent();
            if(
$conditional->getStyle()->getAlignment()->getShrinkToFit() == true){
                
$blockIndent |= << 4;
            } else {
                
$blockIndent |= << 4;
            }
            
$blockIndent |= << 6;

            
// Relative indentation
            
$blockIndentRelative 255;

            
$dataBlockAlign pack('CCvvv'$blockAlign$blockRotation$blockIndent$blockIndentRelative0x0000);
        }
        if(
$bFormatBorder == 1){
            
$blockLineStyle 0;
            switch (
$conditional->getStyle()->getBorders()->getLeft()->getBorderStyle()){
                case 
PHPExcel_Style_Border::BORDER_NONE              $blockLineStyle |= 0x00; break;
                case 
PHPExcel_Style_Border::BORDER_THIN              $blockLineStyle |= 0x01; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUM            $blockLineStyle |= 0x02; break;
                case 
PHPExcel_Style_Border::BORDER_DASHED            $blockLineStyle |= 0x03; break;
                case 
PHPExcel_Style_Border::BORDER_DOTTED            $blockLineStyle |= 0x04; break;
                case 
PHPExcel_Style_Border::BORDER_THICK             $blockLineStyle |= 0x05; break;
                case 
PHPExcel_Style_Border::BORDER_DOUBLE            $blockLineStyle |= 0x06; break;
                case 
PHPExcel_Style_Border::BORDER_HAIR              $blockLineStyle |= 0x07; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHED      $blockLineStyle |= 0x08; break;
                case 
PHPExcel_Style_Border::BORDER_DASHDOT           $blockLineStyle |= 0x09; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT     $blockLineStyle |= 0x0A; break;
                case 
PHPExcel_Style_Border::BORDER_DASHDOTDOT        $blockLineStyle |= 0x0B; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT  $blockLineStyle |= 0x0C; break;
                case 
PHPExcel_Style_Border::BORDER_SLANTDASHDOT      $blockLineStyle |= 0x0D; break;
            }
            switch (
$conditional->getStyle()->getBorders()->getRight()->getBorderStyle()){
                case 
PHPExcel_Style_Border::BORDER_NONE              $blockLineStyle |= 0x00 << 4; break;
                case 
PHPExcel_Style_Border::BORDER_THIN              $blockLineStyle |= 0x01 << 4; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUM            $blockLineStyle |= 0x02 << 4; break;
                case 
PHPExcel_Style_Border::BORDER_DASHED            $blockLineStyle |= 0x03 << 4; break;
                case 
PHPExcel_Style_Border::BORDER_DOTTED            $blockLineStyle |= 0x04 << 4; break;
                case 
PHPExcel_Style_Border::BORDER_THICK             $blockLineStyle |= 0x05 << 4; break;
                case 
PHPExcel_Style_Border::BORDER_DOUBLE            $blockLineStyle |= 0x06 << 4; break;
                case 
PHPExcel_Style_Border::BORDER_HAIR              $blockLineStyle |= 0x07 << 4; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHED      $blockLineStyle |= 0x08 << 4; break;
                case 
PHPExcel_Style_Border::BORDER_DASHDOT           $blockLineStyle |= 0x09 << 4; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT     $blockLineStyle |= 0x0A << 4; break;
                case 
PHPExcel_Style_Border::BORDER_DASHDOTDOT        $blockLineStyle |= 0x0B << 4; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT  $blockLineStyle |= 0x0C << 4; break;
                case 
PHPExcel_Style_Border::BORDER_SLANTDASHDOT      $blockLineStyle |= 0x0D << 4; break;
            }
            switch (
$conditional->getStyle()->getBorders()->getTop()->getBorderStyle()){
                case 
PHPExcel_Style_Border::BORDER_NONE              $blockLineStyle |= 0x00 << 8; break;
                case 
PHPExcel_Style_Border::BORDER_THIN              $blockLineStyle |= 0x01 << 8; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUM            $blockLineStyle |= 0x02 << 8; break;
                case 
PHPExcel_Style_Border::BORDER_DASHED            $blockLineStyle |= 0x03 << 8; break;
                case 
PHPExcel_Style_Border::BORDER_DOTTED            $blockLineStyle |= 0x04 << 8; break;
                case 
PHPExcel_Style_Border::BORDER_THICK             $blockLineStyle |= 0x05 << 8; break;
                case 
PHPExcel_Style_Border::BORDER_DOUBLE            $blockLineStyle |= 0x06 << 8; break;
                case 
PHPExcel_Style_Border::BORDER_HAIR              $blockLineStyle |= 0x07 << 8; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHED      $blockLineStyle |= 0x08 << 8; break;
                case 
PHPExcel_Style_Border::BORDER_DASHDOT           $blockLineStyle |= 0x09 << 8; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT     $blockLineStyle |= 0x0A << 8; break;
                case 
PHPExcel_Style_Border::BORDER_DASHDOTDOT        $blockLineStyle |= 0x0B << 8; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT  $blockLineStyle |= 0x0C << 8; break;
                case 
PHPExcel_Style_Border::BORDER_SLANTDASHDOT      $blockLineStyle |= 0x0D << 8; break;
            }
            switch (
$conditional->getStyle()->getBorders()->getBottom()->getBorderStyle()){
                case 
PHPExcel_Style_Border::BORDER_NONE              $blockLineStyle |= 0x00 << 12; break;
                case 
PHPExcel_Style_Border::BORDER_THIN              $blockLineStyle |= 0x01 << 12; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUM            $blockLineStyle |= 0x02 << 12; break;
                case 
PHPExcel_Style_Border::BORDER_DASHED            $blockLineStyle |= 0x03 << 12; break;
                case 
PHPExcel_Style_Border::BORDER_DOTTED            $blockLineStyle |= 0x04 << 12; break;
                case 
PHPExcel_Style_Border::BORDER_THICK             $blockLineStyle |= 0x05 << 12; break;
                case 
PHPExcel_Style_Border::BORDER_DOUBLE            $blockLineStyle |= 0x06 << 12; break;
                case 
PHPExcel_Style_Border::BORDER_HAIR              $blockLineStyle |= 0x07 << 12; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHED      $blockLineStyle |= 0x08 << 12; break;
                case 
PHPExcel_Style_Border::BORDER_DASHDOT           $blockLineStyle |= 0x09 << 12; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT     $blockLineStyle |= 0x0A << 12; break;
                case 
PHPExcel_Style_Border::BORDER_DASHDOTDOT        $blockLineStyle |= 0x0B << 12; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT  $blockLineStyle |= 0x0C << 12; break;
                case 
PHPExcel_Style_Border::BORDER_SLANTDASHDOT      $blockLineStyle |= 0x0D << 12; break;
            }
            
//@todo _writeCFRule() => $blockLineStyle => Index Color for left line
            //@todo _writeCFRule() => $blockLineStyle => Index Color for right line
            //@todo _writeCFRule() => $blockLineStyle => Top-left to bottom-right on/off
            //@todo _writeCFRule() => $blockLineStyle => Bottom-left to top-right on/off
            
$blockColor 0;
            
//@todo _writeCFRule() => $blockColor => Index Color for top line
            //@todo _writeCFRule() => $blockColor => Index Color for bottom line
            //@todo _writeCFRule() => $blockColor => Index Color for diagonal line
            
switch ($conditional->getStyle()->getBorders()->getDiagonal()->getBorderStyle()){
                case 
PHPExcel_Style_Border::BORDER_NONE              $blockColor |= 0x00 << 21; break;
                case 
PHPExcel_Style_Border::BORDER_THIN              $blockColor |= 0x01 << 21; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUM            $blockColor |= 0x02 << 21; break;
                case 
PHPExcel_Style_Border::BORDER_DASHED            $blockColor |= 0x03 << 21; break;
                case 
PHPExcel_Style_Border::BORDER_DOTTED            $blockColor |= 0x04 << 21; break;
                case 
PHPExcel_Style_Border::BORDER_THICK             $blockColor |= 0x05 << 21; break;
                case 
PHPExcel_Style_Border::BORDER_DOUBLE            $blockColor |= 0x06 << 21; break;
                case 
PHPExcel_Style_Border::BORDER_HAIR              $blockColor |= 0x07 << 21; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHED      $blockColor |= 0x08 << 21; break;
                case 
PHPExcel_Style_Border::BORDER_DASHDOT           $blockColor |= 0x09 << 21; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT     $blockColor |= 0x0A << 21; break;
                case 
PHPExcel_Style_Border::BORDER_DASHDOTDOT        $blockColor |= 0x0B << 21; break;
                case 
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT  $blockColor |= 0x0C << 21; break;
                case 
PHPExcel_Style_Border::BORDER_SLANTDASHDOT      $blockColor |= 0x0D << 21; break;
            }
            
$dataBlockBorder pack('vv'$blockLineStyle$blockColor);
        }
        if(
$bFormatFill == 1){
            
// Fill Patern Style
            
$blockFillPatternStyle 0;
            switch (
$conditional->getStyle()->getFill()->getFillType()){
                case 
PHPExcel_Style_Fill::FILL_NONE                        $blockFillPatternStyle 0x00; break;
                case 
PHPExcel_Style_Fill::FILL_SOLID                    $blockFillPatternStyle 0x01; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY        $blockFillPatternStyle 0x02; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY            $blockFillPatternStyle 0x03; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY        $blockFillPatternStyle 0x04; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL    $blockFillPatternStyle 0x05; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL        $blockFillPatternStyle 0x06; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN            $blockFillPatternStyle 0x07; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_DARKUP            $blockFillPatternStyle 0x08; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID            $blockFillPatternStyle 0x09; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS        $blockFillPatternStyle 0x0A; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL    $blockFillPatternStyle 0x0B; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL    $blockFillPatternStyle 0x0C; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN        $blockFillPatternStyle 0x0D; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP            $blockFillPatternStyle 0x0E; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID        $blockFillPatternStyle 0x0F; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS        $blockFillPatternStyle 0x10; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_GRAY125            $blockFillPatternStyle 0x11; break;
                case 
PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625            $blockFillPatternStyle 0x12; break;
                case 
PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR            $blockFillPatternStyle 0x00; break;    // does not exist in BIFF8
                
case PHPExcel_Style_Fill::FILL_GRADIENT_PATH            $blockFillPatternStyle 0x00; break;    // does not exist in BIFF8
                
default                                                 : $blockFillPatternStyle 0x00; break;
            }
            
// Color
            
switch ($conditional->getStyle()->getFill()->getStartColor()->getRGB()) {
                case 
'000000'$colorIdxBg 0x08; break;
                case 
'FFFFFF'$colorIdxBg 0x09; break;
                case 
'FF0000'$colorIdxBg 0x0A; break;
                case 
'00FF00'$colorIdxBg 0x0B; break;
                case 
'0000FF'$colorIdxBg 0x0C; break;
                case 
'FFFF00'$colorIdxBg 0x0D; break;
                case 
'FF00FF'$colorIdxBg 0x0E; break;
                case 
'00FFFF'$colorIdxBg 0x0F; break;
                case 
'800000'$colorIdxBg 0x10; break;
                case 
'008000'$colorIdxBg 0x11; break;
                case 
'000080'$colorIdxBg 0x12; break;
                case 
'808000'$colorIdxBg 0x13; break;
                case 
'800080'$colorIdxBg 0x14; break;
                case 
'008080'$colorIdxBg 0x15; break;
                case 
'C0C0C0'$colorIdxBg 0x16; break;
                case 
'808080'$colorIdxBg 0x17; break;
                case 
'9999FF'$colorIdxBg 0x18; break;
                case 
'993366'$colorIdxBg 0x19; break;
                case 
'FFFFCC'$colorIdxBg 0x1A; break;
                case 
'CCFFFF'$colorIdxBg 0x1B; break;
                case 
'660066'$colorIdxBg 0x1C; break;
                case 
'FF8080'$colorIdxBg 0x1D; break;
                case 
'0066CC'$colorIdxBg 0x1E; break;
                case 
'CCCCFF'$colorIdxBg 0x1F; break;
                case 
'000080'$colorIdxBg 0x20; break;
                case 
'FF00FF'$colorIdxBg 0x21; break;
                case 
'FFFF00'$colorIdxBg 0x22; break;
                case 
'00FFFF'$colorIdxBg 0x23; break;
                case 
'800080'$colorIdxBg 0x24; break;
                case 
'800000'$colorIdxBg 0x25; break;
                case 
'008080'$colorIdxBg 0x26; break;
                case 
'0000FF'$colorIdxBg 0x27; break;
                case 
'00CCFF'$colorIdxBg 0x28; break;
                case 
'CCFFFF'$colorIdxBg 0x29; break;
                case 
'CCFFCC'$colorIdxBg 0x2A; break;
                case 
'FFFF99'$colorIdxBg 0x2B; break;
                case 
'99CCFF'$colorIdxBg 0x2C; break;
                case 
'FF99CC'$colorIdxBg 0x2D; break;
                case 
'CC99FF'$colorIdxBg 0x2E; break;
                case 
'FFCC99'$colorIdxBg 0x2F; break;
                case 
'3366FF'$colorIdxBg 0x30; break;
                case 
'33CCCC'$colorIdxBg 0x31; break;
                case 
'99CC00'$colorIdxBg 0x32; break;
                case 
'FFCC00'$colorIdxBg 0x33; break;
                case 
'FF9900'$colorIdxBg 0x34; break;
                case 
'FF6600'$colorIdxBg 0x35; break;
                case 
'666699'$colorIdxBg 0x36; break;
                case 
'969696'$colorIdxBg 0x37; break;
                case 
'003366'$colorIdxBg 0x38; break;
                case 
'339966'$colorIdxBg 0x39; break;
                case 
'003300'$colorIdxBg 0x3A; break;
                case 
'333300'$colorIdxBg 0x3B; break;
                case 
'993300'$colorIdxBg 0x3C; break;
                case 
'993366'$colorIdxBg 0x3D; break;
                case 
'333399'$colorIdxBg 0x3E; break;
                case 
'333333'$colorIdxBg 0x3F; break;
                default:       
$colorIdxBg 0x41; break;
            }
            
// Fg Color
            
switch ($conditional->getStyle()->getFill()->getEndColor()->getRGB()) {
                case 
'000000'$colorIdxFg 0x08; break;
                case 
'FFFFFF'$colorIdxFg 0x09; break;
                case 
'FF0000'$colorIdxFg 0x0A; break;
                case 
'00FF00'$colorIdxFg 0x0B; break;
                case 
'0000FF'$colorIdxFg 0x0C; break;
                case 
'FFFF00'$colorIdxFg 0x0D; break;
                case 
'FF00FF'$colorIdxFg 0x0E; break;
                case 
'00FFFF'$colorIdxFg 0x0F; break;
                case 
'800000'$colorIdxFg 0x10; break;
                case 
'008000'$colorIdxFg 0x11; break;
                case 
'000080'$colorIdxFg 0x12; break;
                case 
'808000'$colorIdxFg 0x13; break;
                case 
'800080'$colorIdxFg 0x14; break;
                case 
'008080'$colorIdxFg 0x15; break;
                case 
'C0C0C0'$colorIdxFg 0x16; break;
                case 
'808080'$colorIdxFg 0x17; break;
                case 
'9999FF'$colorIdxFg 0x18; break;
                case 
'993366'$colorIdxFg 0x19; break;
                case 
'FFFFCC'$colorIdxFg 0x1A; break;
                case 
'CCFFFF'$colorIdxFg 0x1B; break;
                case 
'660066'$colorIdxFg 0x1C; break;
                case 
'FF8080'$colorIdxFg 0x1D; break;
                case 
'0066CC'$colorIdxFg 0x1E; break;
                case 
'CCCCFF'$colorIdxFg 0x1F; break;
                case 
'000080'$colorIdxFg 0x20; break;
                case 
'FF00FF'$colorIdxFg 0x21; break;
                case 
'FFFF00'$colorIdxFg 0x22; break;
                case 
'00FFFF'$colorIdxFg 0x23; break;
                case 
'800080'$colorIdxFg 0x24; break;
                case 
'800000'$colorIdxFg 0x25; break;
                case 
'008080'$colorIdxFg 0x26; break;
                case 
'0000FF'$colorIdxFg 0x27; break;
                case 
'00CCFF'$colorIdxFg 0x28; break;
                case 
'CCFFFF'$colorIdxFg 0x29; break;
                case 
'CCFFCC'$colorIdxFg 0x2A; break;
                case 
'FFFF99'$colorIdxFg 0x2B; break;
                case 
'99CCFF'$colorIdxFg 0x2C; break;
                case 
'FF99CC'$colorIdxFg 0x2D; break;
                case 
'CC99FF'$colorIdxFg 0x2E; break;
                case 
'FFCC99'$colorIdxFg 0x2F; break;
                case 
'3366FF'$colorIdxFg 0x30; break;
                case 
'33CCCC'$colorIdxFg 0x31; break;
                case 
'99CC00'$colorIdxFg 0x32; break;
                case 
'FFCC00'$colorIdxFg 0x33; break;
                case 
'FF9900'$colorIdxFg 0x34; break;
                case 
'FF6600'$colorIdxFg 0x35; break;
                case 
'666699'$colorIdxFg 0x36; break;
                case 
'969696'$colorIdxFg 0x37; break;
                case 
'003366'$colorIdxFg 0x38; break;
                case 
'339966'$colorIdxFg 0x39; break;
                case 
'003300'$colorIdxFg 0x3A; break;
                case 
'333300'$colorIdxFg 0x3B; break;
                case 
'993300'$colorIdxFg 0x3C; break;
                case 
'993366'$colorIdxFg 0x3D; break;
                case 
'333399'$colorIdxFg 0x3E; break;
                case 
'333333'$colorIdxFg 0x3F; break;
                default:       
$colorIdxFg 0x40; break;
            }
            
$dataBlockFill pack('v'$blockFillPatternStyle);
            
$dataBlockFill .= pack('v'$colorIdxFg | ($colorIdxBg << 7));
        }
        if(
$bFormatProt == 1){
            
$dataBlockProtection 0;
            if(
$conditional->getStyle()->getProtection()->getLocked() == PHPExcel_Style_Protection::PROTECTION_PROTECTED){
                
$dataBlockProtection 1;
            }
            if(
$conditional->getStyle()->getProtection()->getHidden() == PHPExcel_Style_Protection::PROTECTION_PROTECTED){
                
$dataBlockProtection << 1;
            }
        }

        
$data      pack('CCvvVv'$type$operatorType$szValue1$szValue2$flags0x0000);
        if(
$bFormatFont == 1){ // Block Formatting : OK
            
$data .= $dataBlockFont;
        }
        if(
$bFormatAlign == 1){
            
$data .= $dataBlockAlign;
        }
        if(
$bFormatBorder == 1){
            
$data .= $dataBlockBorder;
        }
        if(
$bFormatFill == 1){ // Block Formatting : OK
            
$data .= $dataBlockFill;
        }
        if(
$bFormatProt == 1){
            
$data .= $dataBlockProtection;
        }
        if(!
is_null($operand1)){
            
$data .= $operand1;
        }
        if(!
is_null($operand2)){
            
$data .= $operand2;
        }
        
$header      pack('vv'$recordstrlen($data));
        
$this->_append($header $data);
    }

    
/**
     * Write CFHeader record
     */
    
private function _writeCFHeader(){
        
$record      0x01B0;               // Record identifier
        
$length      0x0016;               // Bytes to follow

        
$numColumnMin null;
        
$numColumnMax null;
        
$numRowMin null;
        
$numRowMax null;
        
$arrConditional = array();
        foreach (
$this->_phpSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
            foreach (
$conditionalStyles as $conditional) {
                if(
$conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION
                        
|| $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){
                    if(!
in_array($conditional->getHashCode(), $arrConditional)){
                        
$arrConditional[] = $conditional->getHashCode();
                    }
                    
// Cells
                    
$arrCoord PHPExcel_Cell::coordinateFromString($cellCoordinate);
                    if(!
is_numeric($arrCoord[0])){
                        
$arrCoord[0] = PHPExcel_Cell::columnIndexFromString($arrCoord[0]);
                    }
                    if(
is_null($numColumnMin) || ($numColumnMin $arrCoord[0])){
                        
$numColumnMin $arrCoord[0];
                    }
                    if(
is_null($numColumnMax) || ($numColumnMax $arrCoord[0])){
                        
$numColumnMax $arrCoord[0];
                    }
                    if(
is_null($numRowMin) || ($numRowMin $arrCoord[1])){
                        
$numRowMin $arrCoord[1];
                    }
                    if(
is_null($numRowMax) || ($numRowMax $arrCoord[1])){
                        
$numRowMax $arrCoord[1];
                    }
                }
            }
        }
        
$needRedraw 1;
        
$cellRange pack('vvvv'$numRowMin-1$numRowMax-1$numColumnMin-1$numColumnMax-1);

        
$header      pack('vv'$record$length);
        
$data      pack('vv'count($arrConditional), $needRedraw);
        
$data     .= $cellRange;
        
$data     .= pack('v'0x0001);
        
$data     .= $cellRange;
        
$this->_append($header $data);
    }
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by KaizenLouie | C99Shell Github | Generation time: 0.0227 ]--