PageRenderTime 122ms CodeModel.GetById 49ms app.highlight 48ms RepoModel.GetById 2ms app.codeStats 1ms

/administrator/components/com_chronocontact/excelwriter/Writer/Worksheet.php

https://bitbucket.org/dgough/annamaria-daneswood-25102012
PHP | 3502 lines | 1738 code | 423 blank | 1341 comment | 272 complexity | aaf9ac7fc0ad85353b2ab7b3cbb3b3c7 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/*
   3*  Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
   4*
   5*  The majority of this is _NOT_ my code.  I simply ported it from the
   6*  PERL Spreadsheet::WriteExcel module.
   7*
   8*  The author of the Spreadsheet::WriteExcel module is John McNamara
   9*  <jmcnamara@cpan.org>
  10*
  11*  I _DO_ maintain this code, and John McNamara has nothing to do with the
  12*  porting of this code to PHP.  Any questions directly related to this
  13*  class library should be directed to me.
  14*
  15*  License Information:
  16*
  17*    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
  18*    Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
  19*
  20*    This library is free software; you can redistribute it and/or
  21*    modify it under the terms of the GNU Lesser General Public
  22*    License as published by the Free Software Foundation; either
  23*    version 2.1 of the License, or (at your option) any later version.
  24*
  25*    This library is distributed in the hope that it will be useful,
  26*    but WITHOUT ANY WARRANTY; without even the implied warranty of
  27*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  28*    Lesser General Public License for more details.
  29*
  30*    You should have received a copy of the GNU Lesser General Public
  31*    License along with this library; if not, write to the Free Software
  32*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  33*/
  34
  35require_once $mosConfig_absolute_path.'/administrator/components/com_chronocontact/excelwriter/'.'Writer/Parser.php';
  36require_once $mosConfig_absolute_path.'/administrator/components/com_chronocontact/excelwriter/'.'Writer/BIFFwriter.php';
  37
  38/**
  39* Class for generating Excel Spreadsheets
  40*
  41* @author   Xavier Noguer <xnoguer@rezebra.com>
  42* @category FileFormats
  43* @package  Spreadsheet_Excel_Writer
  44*/
  45
  46class Spreadsheet_Excel_Writer_Worksheet extends Spreadsheet_Excel_Writer_BIFFwriter
  47{
  48    /**
  49    * Name of the Worksheet
  50    * @var string
  51    */
  52    var $name;
  53
  54    /**
  55    * Index for the Worksheet
  56    * @var integer
  57    */
  58    var $index;
  59
  60    /**
  61    * Reference to the (default) Format object for URLs
  62    * @var object Format
  63    */
  64    var $_url_format;
  65
  66    /**
  67    * Reference to the parser used for parsing formulas
  68    * @var object Format
  69    */
  70    var $_parser;
  71
  72    /**
  73    * Filehandle to the temporary file for storing data
  74    * @var resource
  75    */
  76    var $_filehandle;
  77
  78    /**
  79    * Boolean indicating if we are using a temporary file for storing data
  80    * @var bool
  81    */
  82    var $_using_tmpfile;
  83
  84    /**
  85    * Maximum number of rows for an Excel spreadsheet (BIFF5)
  86    * @var integer
  87    */
  88    var $_xls_rowmax;
  89
  90    /**
  91    * Maximum number of columns for an Excel spreadsheet (BIFF5)
  92    * @var integer
  93    */
  94    var $_xls_colmax;
  95
  96    /**
  97    * Maximum number of characters for a string (LABEL record in BIFF5)
  98    * @var integer
  99    */
 100    var $_xls_strmax;
 101
 102    /**
 103    * First row for the DIMENSIONS record
 104    * @var integer
 105    * @see _storeDimensions()
 106    */
 107    var $_dim_rowmin;
 108
 109    /**
 110    * Last row for the DIMENSIONS record
 111    * @var integer
 112    * @see _storeDimensions()
 113    */
 114    var $_dim_rowmax;
 115
 116    /**
 117    * First column for the DIMENSIONS record
 118    * @var integer
 119    * @see _storeDimensions()
 120    */
 121    var $_dim_colmin;
 122
 123    /**
 124    * Last column for the DIMENSIONS record
 125    * @var integer
 126    * @see _storeDimensions()
 127    */
 128    var $_dim_colmax;
 129
 130    /**
 131    * Array containing format information for columns
 132    * @var array
 133    */
 134    var $_colinfo;
 135
 136    /**
 137    * Array containing the selected area for the worksheet
 138    * @var array
 139    */
 140    var $_selection;
 141
 142    /**
 143    * Array containing the panes for the worksheet
 144    * @var array
 145    */
 146    var $_panes;
 147
 148    /**
 149    * The active pane for the worksheet
 150    * @var integer
 151    */
 152    var $_active_pane;
 153
 154    /**
 155    * Bit specifying if panes are frozen
 156    * @var integer
 157    */
 158    var $_frozen;
 159
 160    /**
 161    * Bit specifying if the worksheet is selected
 162    * @var integer
 163    */
 164    var $selected;
 165
 166    /**
 167    * The paper size (for printing) (DOCUMENT!!!)
 168    * @var integer
 169    */
 170    var $_paper_size;
 171
 172    /**
 173    * Bit specifying paper orientation (for printing). 0 => landscape, 1 => portrait
 174    * @var integer
 175    */
 176    var $_orientation;
 177
 178    /**
 179    * The page header caption
 180    * @var string
 181    */
 182    var $_header;
 183
 184    /**
 185    * The page footer caption
 186    * @var string
 187    */
 188    var $_footer;
 189
 190    /**
 191    * The horizontal centering value for the page
 192    * @var integer
 193    */
 194    var $_hcenter;
 195
 196    /**
 197    * The vertical centering value for the page
 198    * @var integer
 199    */
 200    var $_vcenter;
 201
 202    /**
 203    * The margin for the header
 204    * @var float
 205    */
 206    var $_margin_head;
 207
 208    /**
 209    * The margin for the footer
 210    * @var float
 211    */
 212    var $_margin_foot;
 213
 214    /**
 215    * The left margin for the worksheet in inches
 216    * @var float
 217    */
 218    var $_margin_left;
 219
 220    /**
 221    * The right margin for the worksheet in inches
 222    * @var float
 223    */
 224    var $_margin_right;
 225
 226    /**
 227    * The top margin for the worksheet in inches
 228    * @var float
 229    */
 230    var $_margin_top;
 231
 232    /**
 233    * The bottom margin for the worksheet in inches
 234    * @var float
 235    */
 236    var $_margin_bottom;
 237
 238    /**
 239    * First row to reapeat on each printed page
 240    * @var integer
 241    */
 242    var $title_rowmin;
 243
 244    /**
 245    * Last row to reapeat on each printed page
 246    * @var integer
 247    */
 248    var $title_rowmax;
 249
 250    /**
 251    * First column to reapeat on each printed page
 252    * @var integer
 253    */
 254    var $title_colmin;
 255
 256    /**
 257    * First row of the area to print
 258    * @var integer
 259    */
 260    var $print_rowmin;
 261
 262    /**
 263    * Last row to of the area to print
 264    * @var integer
 265    */
 266    var $print_rowmax;
 267
 268    /**
 269    * First column of the area to print
 270    * @var integer
 271    */
 272    var $print_colmin;
 273
 274    /**
 275    * Last column of the area to print
 276    * @var integer
 277    */
 278    var $print_colmax;
 279
 280    /**
 281    * Whether to use outline.
 282    * @var integer
 283    */
 284    var $_outline_on;
 285
 286    /**
 287    * Auto outline styles.
 288    * @var bool
 289    */
 290    var $_outline_style;
 291
 292    /**
 293    * Whether to have outline summary below.
 294    * @var bool
 295    */
 296    var $_outline_below;
 297
 298    /**
 299    * Whether to have outline summary at the right.
 300    * @var bool
 301    */
 302    var $_outline_right;
 303
 304    /**
 305    * Outline row level.
 306    * @var integer
 307    */
 308    var $_outline_row_level;
 309
 310    /**
 311    * Whether to fit to page when printing or not.
 312    * @var bool
 313    */
 314    var $_fit_page;
 315
 316    /**
 317    * Number of pages to fit wide
 318    * @var integer
 319    */
 320    var $_fit_width;
 321
 322    /**
 323    * Number of pages to fit high
 324    * @var integer
 325    */
 326    var $_fit_height;
 327
 328    /**
 329    * Reference to the total number of strings in the workbook
 330    * @var integer
 331    */
 332    var $_str_total;
 333
 334    /**
 335    * Reference to the number of unique strings in the workbook
 336    * @var integer
 337    */
 338    var $_str_unique;
 339
 340    /**
 341    * Reference to the array containing all the unique strings in the workbook
 342    * @var array
 343    */
 344    var $_str_table;
 345
 346    /**
 347    * Merged cell ranges
 348    * @var array
 349    */
 350    var $_merged_ranges;
 351
 352    /**
 353    * Charset encoding currently used when calling writeString()
 354    * @var string
 355    */
 356    var $_input_encoding;
 357
 358    /**
 359    * Constructor
 360    *
 361    * @param string  $name         The name of the new worksheet
 362    * @param integer $index        The index of the new worksheet
 363    * @param mixed   &$activesheet The current activesheet of the workbook we belong to
 364    * @param mixed   &$firstsheet  The first worksheet in the workbook we belong to
 365    * @param mixed   &$url_format  The default format for hyperlinks
 366    * @param mixed   &$parser      The formula parser created for the Workbook
 367    * @access private
 368    */
 369    function Spreadsheet_Excel_Writer_Worksheet($BIFF_version, $name,
 370                                                $index, &$activesheet,
 371                                                &$firstsheet, &$str_total,
 372                                                &$str_unique, &$str_table,
 373                                                &$url_format, &$parser)
 374    {
 375        // It needs to call its parent's constructor explicitly
 376        $this->Spreadsheet_Excel_Writer_BIFFwriter();
 377        $this->_BIFF_version   = $BIFF_version;
 378        $rowmax                = 65536; // 16384 in Excel 5
 379        $colmax                = 256;
 380
 381        $this->name            = $name;
 382        $this->index           = $index;
 383        $this->activesheet     = &$activesheet;
 384        $this->firstsheet      = &$firstsheet;
 385        $this->_str_total      = &$str_total;
 386        $this->_str_unique     = &$str_unique;
 387        $this->_str_table      = &$str_table;
 388        $this->_url_format     = &$url_format;
 389        $this->_parser         = &$parser;
 390
 391        //$this->ext_sheets      = array();
 392        $this->_filehandle     = '';
 393        $this->_using_tmpfile  = true;
 394        //$this->fileclosed      = 0;
 395        //$this->offset          = 0;
 396        $this->_xls_rowmax     = $rowmax;
 397        $this->_xls_colmax     = $colmax;
 398        $this->_xls_strmax     = 255;
 399        $this->_dim_rowmin     = $rowmax + 1;
 400        $this->_dim_rowmax     = 0;
 401        $this->_dim_colmin     = $colmax + 1;
 402        $this->_dim_colmax     = 0;
 403        $this->_colinfo        = array();
 404        $this->_selection      = array(0,0,0,0);
 405        $this->_panes          = array();
 406        $this->_active_pane    = 3;
 407        $this->_frozen         = 0;
 408        $this->selected        = 0;
 409
 410        $this->_paper_size      = 0x0;
 411        $this->_orientation     = 0x1;
 412        $this->_header          = '';
 413        $this->_footer          = '';
 414        $this->_hcenter         = 0;
 415        $this->_vcenter         = 0;
 416        $this->_margin_head     = 0.50;
 417        $this->_margin_foot     = 0.50;
 418        $this->_margin_left     = 0.75;
 419        $this->_margin_right    = 0.75;
 420        $this->_margin_top      = 1.00;
 421        $this->_margin_bottom   = 1.00;
 422
 423        $this->title_rowmin     = null;
 424        $this->title_rowmax     = null;
 425        $this->title_colmin     = null;
 426        $this->title_colmax     = null;
 427        $this->print_rowmin     = null;
 428        $this->print_rowmax     = null;
 429        $this->print_colmin     = null;
 430        $this->print_colmax     = null;
 431
 432        $this->_print_gridlines  = 1;
 433        $this->_screen_gridlines = 1;
 434        $this->_print_headers    = 0;
 435
 436        $this->_fit_page        = 0;
 437        $this->_fit_width       = 0;
 438        $this->_fit_height      = 0;
 439
 440        $this->_hbreaks         = array();
 441        $this->_vbreaks         = array();
 442
 443        $this->_protect         = 0;
 444        $this->_password        = null;
 445
 446        $this->col_sizes        = array();
 447        $this->_row_sizes        = array();
 448
 449        $this->_zoom            = 100;
 450        $this->_print_scale     = 100;
 451
 452        $this->_outline_row_level = 0;
 453        $this->_outline_style     = 0;
 454        $this->_outline_below     = 1;
 455        $this->_outline_right     = 1;
 456        $this->_outline_on        = 1;
 457
 458        $this->_merged_ranges     = array();
 459
 460        $this->_input_encoding    = '';
 461
 462        $this->_dv                = array();
 463
 464        $this->_initialize();
 465    }
 466
 467    /**
 468    * Open a tmp file to store the majority of the Worksheet data. If this fails,
 469    * for example due to write permissions, store the data in memory. This can be
 470    * slow for large files.
 471    *
 472    * @access private
 473    */
 474    function _initialize()
 475    {
 476        // Open tmp file for storing Worksheet data
 477        $fh = tmpfile();
 478        if ($fh) {
 479            // Store filehandle
 480            $this->_filehandle = $fh;
 481        } else {
 482            // If tmpfile() fails store data in memory
 483            $this->_using_tmpfile = false;
 484        }
 485    }
 486
 487    /**
 488    * Add data to the beginning of the workbook (note the reverse order)
 489    * and to the end of the workbook.
 490    *
 491    * @access public
 492    * @see Spreadsheet_Excel_Writer_Workbook::storeWorkbook()
 493    * @param array $sheetnames The array of sheetnames from the Workbook this
 494    *                          worksheet belongs to
 495    */
 496    function close($sheetnames)
 497    {
 498        $num_sheets = count($sheetnames);
 499
 500        /***********************************************
 501        * Prepend in reverse order!!
 502        */
 503
 504        // Prepend the sheet dimensions
 505        $this->_storeDimensions();
 506
 507        // Prepend the sheet password
 508        $this->_storePassword();
 509
 510        // Prepend the sheet protection
 511        $this->_storeProtect();
 512
 513        // Prepend the page setup
 514        $this->_storeSetup();
 515
 516        /* FIXME: margins are actually appended */
 517        // Prepend the bottom margin
 518        $this->_storeMarginBottom();
 519
 520        // Prepend the top margin
 521        $this->_storeMarginTop();
 522
 523        // Prepend the right margin
 524        $this->_storeMarginRight();
 525
 526        // Prepend the left margin
 527        $this->_storeMarginLeft();
 528
 529        // Prepend the page vertical centering
 530        $this->_storeVcenter();
 531
 532        // Prepend the page horizontal centering
 533        $this->_storeHcenter();
 534
 535        // Prepend the page footer
 536        $this->_storeFooter();
 537
 538        // Prepend the page header
 539        $this->_storeHeader();
 540
 541        // Prepend the vertical page breaks
 542        $this->_storeVbreak();
 543
 544        // Prepend the horizontal page breaks
 545        $this->_storeHbreak();
 546
 547        // Prepend WSBOOL
 548        $this->_storeWsbool();
 549
 550        // Prepend GRIDSET
 551        $this->_storeGridset();
 552
 553         //  Prepend GUTS
 554        if ($this->_BIFF_version == 0x0500) {
 555            $this->_storeGuts();
 556        }
 557
 558        // Prepend PRINTGRIDLINES
 559        $this->_storePrintGridlines();
 560
 561        // Prepend PRINTHEADERS
 562        $this->_storePrintHeaders();
 563
 564        // Prepend EXTERNSHEET references
 565        if ($this->_BIFF_version == 0x0500) {
 566            for ($i = $num_sheets; $i > 0; $i--) {
 567                $sheetname = $sheetnames[$i-1];
 568                $this->_storeExternsheet($sheetname);
 569            }
 570        }
 571
 572        // Prepend the EXTERNCOUNT of external references.
 573        if ($this->_BIFF_version == 0x0500) {
 574            $this->_storeExterncount($num_sheets);
 575        }
 576
 577        // Prepend the COLINFO records if they exist
 578        if (!empty($this->_colinfo)) {
 579            $colcount = count($this->_colinfo);
 580            for ($i = 0; $i < $colcount; $i++) {
 581                $this->_storeColinfo($this->_colinfo[$i]);
 582            }
 583            $this->_storeDefcol();
 584        }
 585
 586        // Prepend the BOF record
 587        $this->_storeBof(0x0010);
 588
 589        /*
 590        * End of prepend. Read upwards from here.
 591        ***********************************************/
 592
 593        // Append
 594        $this->_storeWindow2();
 595        $this->_storeZoom();
 596        if (!empty($this->_panes)) {
 597            $this->_storePanes($this->_panes);
 598        }
 599        $this->_storeSelection($this->_selection);
 600        $this->_storeMergedCells();
 601        /* TODO: add data validity */
 602        /*if ($this->_BIFF_version == 0x0600) {
 603            $this->_storeDataValidity();
 604        }*/
 605        $this->_storeEof();
 606    }
 607
 608    /**
 609    * Retrieve the worksheet name.
 610    * This is usefull when creating worksheets without a name.
 611    *
 612    * @access public
 613    * @return string The worksheet's name
 614    */
 615    function getName()
 616    {
 617        return $this->name;
 618    }
 619
 620    /**
 621    * Retrieves data from memory in one chunk, or from disk in $buffer
 622    * sized chunks.
 623    *
 624    * @return string The data
 625    */
 626    function getData()
 627    {
 628        $buffer = 4096;
 629
 630        // Return data stored in memory
 631        if (isset($this->_data)) {
 632            $tmp   = $this->_data;
 633            unset($this->_data);
 634            $fh    = $this->_filehandle;
 635            if ($this->_using_tmpfile) {
 636                fseek($fh, 0);
 637            }
 638            return $tmp;
 639        }
 640        // Return data stored on disk
 641        if ($this->_using_tmpfile) {
 642            if ($tmp = fread($this->_filehandle, $buffer)) {
 643                return $tmp;
 644            }
 645        }
 646
 647        // No data to return
 648        return '';
 649    }
 650
 651    /**
 652    * Sets a merged cell range
 653    *
 654    * @access public
 655    * @param integer $first_row First row of the area to merge
 656    * @param integer $first_col First column of the area to merge
 657    * @param integer $last_row  Last row of the area to merge
 658    * @param integer $last_col  Last column of the area to merge
 659    */
 660    function setMerge($first_row, $first_col, $last_row, $last_col)
 661    {
 662        if (($last_row < $first_row) || ($last_col < $first_col)) {
 663            return;
 664        }
 665        // don't check rowmin, rowmax, etc... because we don't know when this
 666        // is going to be called
 667        $this->_merged_ranges[] = array($first_row, $first_col, $last_row, $last_col);
 668    }
 669
 670    /**
 671    * Set this worksheet as a selected worksheet,
 672    * i.e. the worksheet has its tab highlighted.
 673    *
 674    * @access public
 675    */
 676    function select()
 677    {
 678        $this->selected = 1;
 679    }
 680
 681    /**
 682    * Set this worksheet as the active worksheet,
 683    * i.e. the worksheet that is displayed when the workbook is opened.
 684    * Also set it as selected.
 685    *
 686    * @access public
 687    */
 688    function activate()
 689    {
 690        $this->selected = 1;
 691        $this->activesheet = $this->index;
 692    }
 693
 694    /**
 695    * Set this worksheet as the first visible sheet.
 696    * This is necessary when there are a large number of worksheets and the
 697    * activated worksheet is not visible on the screen.
 698    *
 699    * @access public
 700    */
 701    function setFirstSheet()
 702    {
 703        $this->firstsheet = $this->index;
 704    }
 705
 706    /**
 707    * Set the worksheet protection flag
 708    * to prevent accidental modification and to
 709    * hide formulas if the locked and hidden format properties have been set.
 710    *
 711    * @access public
 712    * @param string $password The password to use for protecting the sheet.
 713    */
 714    function protect($password)
 715    {
 716        $this->_protect   = 1;
 717        $this->_password  = $this->_encodePassword($password);
 718    }
 719
 720    /**
 721    * Set the width of a single column or a range of columns.
 722    *
 723    * @access public
 724    * @param integer $firstcol first column on the range
 725    * @param integer $lastcol  last column on the range
 726    * @param integer $width    width to set
 727    * @param mixed   $format   The optional XF format to apply to the columns
 728    * @param integer $hidden   The optional hidden atribute
 729    * @param integer $level    The optional outline level
 730    */
 731    function setColumn($firstcol, $lastcol, $width, $format = 0, $hidden = 0, $level = 0)
 732    {
 733        $this->_colinfo[] = array($firstcol, $lastcol, $width, &$format, $hidden, $level);
 734
 735        // Set width to zero if column is hidden
 736        $width = ($hidden) ? 0 : $width;
 737
 738        for ($col = $firstcol; $col <= $lastcol; $col++) {
 739            $this->col_sizes[$col] = $width;
 740        }
 741    }
 742
 743    /**
 744    * Set which cell or cells are selected in a worksheet
 745    *
 746    * @access public
 747    * @param integer $first_row    first row in the selected quadrant
 748    * @param integer $first_column first column in the selected quadrant
 749    * @param integer $last_row     last row in the selected quadrant
 750    * @param integer $last_column  last column in the selected quadrant
 751    */
 752    function setSelection($first_row,$first_column,$last_row,$last_column)
 753    {
 754        $this->_selection = array($first_row,$first_column,$last_row,$last_column);
 755    }
 756
 757    /**
 758    * Set panes and mark them as frozen.
 759    *
 760    * @access public
 761    * @param array $panes This is the only parameter received and is composed of the following:
 762    *                     0 => Vertical split position,
 763    *                     1 => Horizontal split position
 764    *                     2 => Top row visible
 765    *                     3 => Leftmost column visible
 766    *                     4 => Active pane
 767    */
 768    function freezePanes($panes)
 769    {
 770        $this->_frozen = 1;
 771        $this->_panes  = $panes;
 772    }
 773
 774    /**
 775    * Set panes and mark them as unfrozen.
 776    *
 777    * @access public
 778    * @param array $panes This is the only parameter received and is composed of the following:
 779    *                     0 => Vertical split position,
 780    *                     1 => Horizontal split position
 781    *                     2 => Top row visible
 782    *                     3 => Leftmost column visible
 783    *                     4 => Active pane
 784    */
 785    function thawPanes($panes)
 786    {
 787        $this->_frozen = 0;
 788        $this->_panes  = $panes;
 789    }
 790
 791    /**
 792    * Set the page orientation as portrait.
 793    *
 794    * @access public
 795    */
 796    function setPortrait()
 797    {
 798        $this->_orientation = 1;
 799    }
 800
 801    /**
 802    * Set the page orientation as landscape.
 803    *
 804    * @access public
 805    */
 806    function setLandscape()
 807    {
 808        $this->_orientation = 0;
 809    }
 810
 811    /**
 812    * Set the paper type. Ex. 1 = US Letter, 9 = A4
 813    *
 814    * @access public
 815    * @param integer $size The type of paper size to use
 816    */
 817    function setPaper($size = 0)
 818    {
 819        $this->_paper_size = $size;
 820    }
 821
 822
 823    /**
 824    * Set the page header caption and optional margin.
 825    *
 826    * @access public
 827    * @param string $string The header text
 828    * @param float  $margin optional head margin in inches.
 829    */
 830    function setHeader($string,$margin = 0.50)
 831    {
 832        if (strlen($string) >= 255) {
 833            //carp 'Header string must be less than 255 characters';
 834            return;
 835        }
 836        $this->_header      = $string;
 837        $this->_margin_head = $margin;
 838    }
 839
 840    /**
 841    * Set the page footer caption and optional margin.
 842    *
 843    * @access public
 844    * @param string $string The footer text
 845    * @param float  $margin optional foot margin in inches.
 846    */
 847    function setFooter($string,$margin = 0.50)
 848    {
 849        if (strlen($string) >= 255) {
 850            //carp 'Footer string must be less than 255 characters';
 851            return;
 852        }
 853        $this->_footer      = $string;
 854        $this->_margin_foot = $margin;
 855    }
 856
 857    /**
 858    * Center the page horinzontally.
 859    *
 860    * @access public
 861    * @param integer $center the optional value for centering. Defaults to 1 (center).
 862    */
 863    function centerHorizontally($center = 1)
 864    {
 865        $this->_hcenter = $center;
 866    }
 867
 868    /**
 869    * Center the page vertically.
 870    *
 871    * @access public
 872    * @param integer $center the optional value for centering. Defaults to 1 (center).
 873    */
 874    function centerVertically($center = 1)
 875    {
 876        $this->_vcenter = $center;
 877    }
 878
 879    /**
 880    * Set all the page margins to the same value in inches.
 881    *
 882    * @access public
 883    * @param float $margin The margin to set in inches
 884    */
 885    function setMargins($margin)
 886    {
 887        $this->setMarginLeft($margin);
 888        $this->setMarginRight($margin);
 889        $this->setMarginTop($margin);
 890        $this->setMarginBottom($margin);
 891    }
 892
 893    /**
 894    * Set the left and right margins to the same value in inches.
 895    *
 896    * @access public
 897    * @param float $margin The margin to set in inches
 898    */
 899    function setMargins_LR($margin)
 900    {
 901        $this->setMarginLeft($margin);
 902        $this->setMarginRight($margin);
 903    }
 904
 905    /**
 906    * Set the top and bottom margins to the same value in inches.
 907    *
 908    * @access public
 909    * @param float $margin The margin to set in inches
 910    */
 911    function setMargins_TB($margin)
 912    {
 913        $this->setMarginTop($margin);
 914        $this->setMarginBottom($margin);
 915    }
 916
 917    /**
 918    * Set the left margin in inches.
 919    *
 920    * @access public
 921    * @param float $margin The margin to set in inches
 922    */
 923    function setMarginLeft($margin = 0.75)
 924    {
 925        $this->_margin_left = $margin;
 926    }
 927
 928    /**
 929    * Set the right margin in inches.
 930    *
 931    * @access public
 932    * @param float $margin The margin to set in inches
 933    */
 934    function setMarginRight($margin = 0.75)
 935    {
 936        $this->_margin_right = $margin;
 937    }
 938
 939    /**
 940    * Set the top margin in inches.
 941    *
 942    * @access public
 943    * @param float $margin The margin to set in inches
 944    */
 945    function setMarginTop($margin = 1.00)
 946    {
 947        $this->_margin_top = $margin;
 948    }
 949
 950    /**
 951    * Set the bottom margin in inches.
 952    *
 953    * @access public
 954    * @param float $margin The margin to set in inches
 955    */
 956    function setMarginBottom($margin = 1.00)
 957    {
 958        $this->_margin_bottom = $margin;
 959    }
 960
 961    /**
 962    * Set the rows to repeat at the top of each printed page.
 963    *
 964    * @access public
 965    * @param integer $first_row First row to repeat
 966    * @param integer $last_row  Last row to repeat. Optional.
 967    */
 968    function repeatRows($first_row, $last_row = null)
 969    {
 970        $this->title_rowmin  = $first_row;
 971        if (isset($last_row)) { //Second row is optional
 972            $this->title_rowmax  = $last_row;
 973        } else {
 974            $this->title_rowmax  = $first_row;
 975        }
 976    }
 977
 978    /**
 979    * Set the columns to repeat at the left hand side of each printed page.
 980    *
 981    * @access public
 982    * @param integer $first_col First column to repeat
 983    * @param integer $last_col  Last column to repeat. Optional.
 984    */
 985    function repeatColumns($first_col, $last_col = null)
 986    {
 987        $this->title_colmin  = $first_col;
 988        if (isset($last_col)) { // Second col is optional
 989            $this->title_colmax  = $last_col;
 990        } else {
 991            $this->title_colmax  = $first_col;
 992        }
 993    }
 994
 995    /**
 996    * Set the area of each worksheet that will be printed.
 997    *
 998    * @access public
 999    * @param integer $first_row First row of the area to print
1000    * @param integer $first_col First column of the area to print
1001    * @param integer $last_row  Last row of the area to print
1002    * @param integer $last_col  Last column of the area to print
1003    */
1004    function printArea($first_row, $first_col, $last_row, $last_col)
1005    {
1006        $this->print_rowmin  = $first_row;
1007        $this->print_colmin  = $first_col;
1008        $this->print_rowmax  = $last_row;
1009        $this->print_colmax  = $last_col;
1010    }
1011
1012
1013    /**
1014    * Set the option to hide gridlines on the printed page.
1015    *
1016    * @access public
1017    */
1018    function hideGridlines()
1019    {
1020        $this->_print_gridlines = 0;
1021    }
1022
1023    /**
1024    * Set the option to hide gridlines on the worksheet (as seen on the screen).
1025    *
1026    * @access public
1027    */
1028    function hideScreenGridlines()
1029    {
1030        $this->_screen_gridlines = 0;
1031    }
1032
1033    /**
1034    * Set the option to print the row and column headers on the printed page.
1035    *
1036    * @access public
1037    * @param integer $print Whether to print the headers or not. Defaults to 1 (print).
1038    */
1039    function printRowColHeaders($print = 1)
1040    {
1041        $this->_print_headers = $print;
1042    }
1043
1044    /**
1045    * Set the vertical and horizontal number of pages that will define the maximum area printed.
1046    * It doesn't seem to work with OpenOffice.
1047    *
1048    * @access public
1049    * @param  integer $width  Maximun width of printed area in pages
1050    * @param  integer $height Maximun heigth of printed area in pages
1051    * @see setPrintScale()
1052    */
1053    function fitToPages($width, $height)
1054    {
1055        $this->_fit_page      = 1;
1056        $this->_fit_width     = $width;
1057        $this->_fit_height    = $height;
1058    }
1059
1060    /**
1061    * Store the horizontal page breaks on a worksheet (for printing).
1062    * The breaks represent the row after which the break is inserted.
1063    *
1064    * @access public
1065    * @param array $breaks Array containing the horizontal page breaks
1066    */
1067    function setHPagebreaks($breaks)
1068    {
1069        foreach ($breaks as $break) {
1070            array_push($this->_hbreaks, $break);
1071        }
1072    }
1073
1074    /**
1075    * Store the vertical page breaks on a worksheet (for printing).
1076    * The breaks represent the column after which the break is inserted.
1077    *
1078    * @access public
1079    * @param array $breaks Array containing the vertical page breaks
1080    */
1081    function setVPagebreaks($breaks)
1082    {
1083        foreach ($breaks as $break) {
1084            array_push($this->_vbreaks, $break);
1085        }
1086    }
1087
1088
1089    /**
1090    * Set the worksheet zoom factor.
1091    *
1092    * @access public
1093    * @param integer $scale The zoom factor
1094    */
1095    function setZoom($scale = 100)
1096    {
1097        // Confine the scale to Excel's range
1098        if ($scale < 10 || $scale > 400) {
1099            $this->raiseError("Zoom factor $scale outside range: 10 <= zoom <= 400");
1100            $scale = 100;
1101        }
1102
1103        $this->_zoom = floor($scale);
1104    }
1105
1106    /**
1107    * Set the scale factor for the printed page.
1108    * It turns off the "fit to page" option
1109    *
1110    * @access public
1111    * @param integer $scale The optional scale factor. Defaults to 100
1112    */
1113    function setPrintScale($scale = 100)
1114    {
1115        // Confine the scale to Excel's range
1116        if ($scale < 10 || $scale > 400) {
1117            $this->raiseError("Print scale $scale outside range: 10 <= zoom <= 400");
1118            $scale = 100;
1119        }
1120
1121        // Turn off "fit to page" option
1122        $this->_fit_page = 0;
1123
1124        $this->_print_scale = floor($scale);
1125    }
1126
1127    /**
1128    * Map to the appropriate write method acording to the token recieved.
1129    *
1130    * @access public
1131    * @param integer $row    The row of the cell we are writing to
1132    * @param integer $col    The column of the cell we are writing to
1133    * @param mixed   $token  What we are writing
1134    * @param mixed   $format The optional format to apply to the cell
1135    */
1136    function write($row, $col, $token, $format = 0)
1137    {
1138        // Check for a cell reference in A1 notation and substitute row and column
1139        /*if ($_[0] =~ /^\D/) {
1140            @_ = $this->_substituteCellref(@_);
1141    }*/
1142
1143        if (preg_match("/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/", $token)) {
1144            // Match number
1145            return $this->writeNumber($row, $col, $token, $format);
1146        } elseif (preg_match("/^[fh]tt?p:\/\//", $token)) {
1147            // Match http or ftp URL
1148            return $this->writeUrl($row, $col, $token, '', $format);
1149        } elseif (preg_match("/^mailto:/", $token)) {
1150            // Match mailto:
1151            return $this->writeUrl($row, $col, $token, '', $format);
1152        } elseif (preg_match("/^(?:in|ex)ternal:/", $token)) {
1153            // Match internal or external sheet link
1154            return $this->writeUrl($row, $col, $token, '', $format);
1155        } elseif (preg_match("/^=/", $token)) {
1156            // Match formula
1157            return $this->writeFormula($row, $col, $token, $format);
1158        } elseif (preg_match("/^@/", $token)) {
1159            // Match formula
1160            return $this->writeFormula($row, $col, $token, $format);
1161        } elseif ($token == '') {
1162            // Match blank
1163            return $this->writeBlank($row, $col, $format);
1164        } else {
1165            // Default: match string
1166            return $this->writeString($row, $col, $token, $format);
1167        }
1168    }
1169
1170    /**
1171    * Write an array of values as a row
1172    *
1173    * @access public
1174    * @param integer $row    The row we are writing to
1175    * @param integer $col    The first col (leftmost col) we are writing to
1176    * @param array   $val    The array of values to write
1177    * @param mixed   $format The optional format to apply to the cell
1178    * @return mixed PEAR_Error on failure
1179    */
1180
1181    function writeRow($row, $col, $val, $format = 0)
1182    {
1183        $retval = '';
1184        if (is_array($val)) {
1185            foreach ($val as $v) {
1186                if (is_array($v)) {
1187                    $this->writeCol($row, $col, $v, $format);
1188                } else {
1189                    $this->write($row, $col, $v, $format);
1190                }
1191                $col++;
1192            }
1193        } else {
1194            $retval = new PEAR_Error('$val needs to be an array');
1195        }
1196        return($retval);
1197    }
1198
1199    /**
1200    * Write an array of values as a column
1201    *
1202    * @access public
1203    * @param integer $row    The first row (uppermost row) we are writing to
1204    * @param integer $col    The col we are writing to
1205    * @param array   $val    The array of values to write
1206    * @param mixed   $format The optional format to apply to the cell
1207    * @return mixed PEAR_Error on failure
1208    */
1209
1210    function writeCol($row, $col, $val, $format=0)
1211    {
1212        $retval = '';
1213        if (is_array($val)) {
1214            foreach ($val as $v) {
1215                $this->write($row, $col, $v, $format);
1216                $row++;
1217            }
1218        } else {
1219            $retval = new PEAR_Error('$val needs to be an array');
1220        }
1221        return($retval);
1222    }
1223
1224    /**
1225    * Returns an index to the XF record in the workbook
1226    *
1227    * @access private
1228    * @param mixed &$format The optional XF format
1229    * @return integer The XF record index
1230    */
1231    function _XF(&$format)
1232    {
1233        if ($format != 0) {
1234            return($format->getXfIndex());
1235        } else {
1236            return(0x0F);
1237        }
1238    }
1239
1240
1241    /******************************************************************************
1242    *******************************************************************************
1243    *
1244    * Internal methods
1245    */
1246
1247
1248    /**
1249    * Store Worksheet data in memory using the parent's class append() or to a
1250    * temporary file, the default.
1251    *
1252    * @access private
1253    * @param string $data The binary data to append
1254    */
1255    function _append($data)
1256    {
1257        if ($this->_using_tmpfile) {
1258            // Add CONTINUE records if necessary
1259            if (strlen($data) > $this->_limit) {
1260                $data = $this->_addContinue($data);
1261            }
1262            fwrite($this->_filehandle, $data);
1263            $this->_datasize += strlen($data);
1264        } else {
1265            parent::_append($data);
1266        }
1267    }
1268
1269    /**
1270    * Substitute an Excel cell reference in A1 notation for  zero based row and
1271    * column values in an argument list.
1272    *
1273    * Ex: ("A4", "Hello") is converted to (3, 0, "Hello").
1274    *
1275    * @access private
1276    * @param string $cell The cell reference. Or range of cells.
1277    * @return array
1278    */
1279    function _substituteCellref($cell)
1280    {
1281        $cell = strtoupper($cell);
1282
1283        // Convert a column range: 'A:A' or 'B:G'
1284        if (preg_match("/([A-I]?[A-Z]):([A-I]?[A-Z])/", $cell, $match)) {
1285            list($no_use, $col1) =  $this->_cellToRowcol($match[1] .'1'); // Add a dummy row
1286            list($no_use, $col2) =  $this->_cellToRowcol($match[2] .'1'); // Add a dummy row
1287            return(array($col1, $col2));
1288        }
1289
1290        // Convert a cell range: 'A1:B7'
1291        if (preg_match("/\$?([A-I]?[A-Z]\$?\d+):\$?([A-I]?[A-Z]\$?\d+)/", $cell, $match)) {
1292            list($row1, $col1) =  $this->_cellToRowcol($match[1]);
1293            list($row2, $col2) =  $this->_cellToRowcol($match[2]);
1294            return(array($row1, $col1, $row2, $col2));
1295        }
1296
1297        // Convert a cell reference: 'A1' or 'AD2000'
1298        if (preg_match("/\$?([A-I]?[A-Z]\$?\d+)/", $cell)) {
1299            list($row1, $col1) =  $this->_cellToRowcol($match[1]);
1300            return(array($row1, $col1));
1301        }
1302
1303        // TODO use real error codes
1304        $this->raiseError("Unknown cell reference $cell", 0, PEAR_ERROR_DIE);
1305    }
1306
1307    /**
1308    * Convert an Excel cell reference in A1 notation to a zero based row and column
1309    * reference; converts C1 to (0, 2).
1310    *
1311    * @access private
1312    * @param string $cell The cell reference.
1313    * @return array containing (row, column)
1314    */
1315    function _cellToRowcol($cell)
1316    {
1317        preg_match("/\$?([A-I]?[A-Z])\$?(\d+)/",$cell,$match);
1318        $col     = $match[1];
1319        $row     = $match[2];
1320
1321        // Convert base26 column string to number
1322        $chars = split('', $col);
1323        $expn  = 0;
1324        $col   = 0;
1325
1326        while ($chars) {
1327            $char = array_pop($chars);        // LS char first
1328            $col += (ord($char) -ord('A') +1) * pow(26,$expn);
1329            $expn++;
1330        }
1331
1332        // Convert 1-index to zero-index
1333        $row--;
1334        $col--;
1335
1336        return(array($row, $col));
1337    }
1338
1339    /**
1340    * Based on the algorithm provided by Daniel Rentz of OpenOffice.
1341    *
1342    * @access private
1343    * @param string $plaintext The password to be encoded in plaintext.
1344    * @return string The encoded password
1345    */
1346    function _encodePassword($plaintext)
1347    {
1348        $password = 0x0000;
1349        $i        = 1;       // char position
1350
1351        // split the plain text password in its component characters
1352        $chars = preg_split('//', $plaintext, -1, PREG_SPLIT_NO_EMPTY);
1353        foreach ($chars as $char) {
1354            $value        = ord($char) << $i;   // shifted ASCII value
1355            $rotated_bits = $value >> 15;       // rotated bits beyond bit 15
1356            $value       &= 0x7fff;             // first 15 bits
1357            $password    ^= ($value | $rotated_bits);
1358            $i++;
1359        }
1360
1361        $password ^= strlen($plaintext);
1362        $password ^= 0xCE4B;
1363
1364        return($password);
1365    }
1366
1367    /**
1368    * This method sets the properties for outlining and grouping. The defaults
1369    * correspond to Excel's defaults.
1370    *
1371    * @param bool $visible
1372    * @param bool $symbols_below
1373    * @param bool $symbols_right
1374    * @param bool $auto_style
1375    */
1376    function setOutline($visible = true, $symbols_below = true, $symbols_right = true, $auto_style = false)
1377    {
1378        $this->_outline_on    = $visible;
1379        $this->_outline_below = $symbols_below;
1380        $this->_outline_right = $symbols_right;
1381        $this->_outline_style = $auto_style;
1382
1383        // Ensure this is a boolean vale for Window2
1384        if ($this->_outline_on) {
1385            $this->_outline_on = 1;
1386        }
1387     }
1388
1389    /******************************************************************************
1390    *******************************************************************************
1391    *
1392    * BIFF RECORDS
1393    */
1394
1395
1396    /**
1397    * Write a double to the specified row and column (zero indexed).
1398    * An integer can be written as a double. Excel will display an
1399    * integer. $format is optional.
1400    *
1401    * Returns  0 : normal termination
1402    *         -2 : row or column out of range
1403    *
1404    * @access public
1405    * @param integer $row    Zero indexed row
1406    * @param integer $col    Zero indexed column
1407    * @param float   $num    The number to write
1408    * @param mixed   $format The optional XF format
1409    * @return integer
1410    */
1411    function writeNumber($row, $col, $num, $format = 0)
1412    {
1413        $record    = 0x0203;                 // Record identifier
1414        $length    = 0x000E;                 // Number of bytes to follow
1415
1416        $xf        = $this->_XF($format);    // The cell format
1417
1418        // Check that row and col are valid and store max and min values
1419        if ($row >= $this->_xls_rowmax) {
1420            return(-2);
1421        }
1422        if ($col >= $this->_xls_colmax) {
1423            return(-2);
1424        }
1425        if ($row <  $this->_dim_rowmin)  {
1426            $this->_dim_rowmin = $row;
1427        }
1428        if ($row >  $this->_dim_rowmax)  {
1429            $this->_dim_rowmax = $row;
1430        }
1431        if ($col <  $this->_dim_colmin)  {
1432            $this->_dim_colmin = $col;
1433        }
1434        if ($col >  $this->_dim_colmax)  {
1435            $this->_dim_colmax = $col;
1436        }
1437
1438        $header    = pack("vv",  $record, $length);
1439        $data      = pack("vvv", $row, $col, $xf);
1440        $xl_double = pack("d",   $num);
1441        if ($this->_byte_order) { // if it's Big Endian
1442            $xl_double = strrev($xl_double);
1443        }
1444
1445        $this->_append($header.$data.$xl_double);
1446        return(0);
1447    }
1448
1449    /**
1450    * Write a string to the specified row and column (zero indexed).
1451    * NOTE: there is an Excel 5 defined limit of 255 characters.
1452    * $format is optional.
1453    * Returns  0 : normal termination
1454    *         -2 : row or column out of range
1455    *         -3 : long string truncated to 255 chars
1456    *
1457    * @access public
1458    * @param integer $row    Zero indexed row
1459    * @param integer $col    Zero indexed column
1460    * @param string  $str    The string to write
1461    * @param mixed   $format The XF format for the cell
1462    * @return integer
1463    */
1464    function writeString($row, $col, $str, $format = 0)
1465    {
1466        if ($this->_BIFF_version == 0x0600) {
1467            return $this->writeStringBIFF8($row, $col, $str, $format);
1468        }
1469        $strlen    = strlen($str);
1470        $record    = 0x0204;                   // Record identifier
1471        $length    = 0x0008 + $strlen;         // Bytes to follow
1472        $xf        = $this->_XF($format);      // The cell format
1473
1474        $str_error = 0;
1475
1476        // Check that row and col are valid and store max and min values
1477        if ($row >= $this->_xls_rowmax) {
1478            return(-2);
1479        }
1480        if ($col >= $this->_xls_colmax) {
1481            return(-2);
1482        }
1483        if ($row <  $this->_dim_rowmin) {
1484            $this->_dim_rowmin = $row;
1485        }
1486        if ($row >  $this->_dim_rowmax) {
1487            $this->_dim_rowmax = $row;
1488        }
1489        if ($col <  $this->_dim_colmin) {
1490            $this->_dim_colmin = $col;
1491        }
1492        if ($col >  $this->_dim_colmax) {
1493            $this->_dim_colmax = $col;
1494        }
1495
1496        if ($strlen > $this->_xls_strmax) { // LABEL must be < 255 chars
1497            $str       = substr($str, 0, $this->_xls_strmax);
1498            $length    = 0x0008 + $this->_xls_strmax;
1499            $strlen    = $this->_xls_strmax;
1500            $str_error = -3;
1501        }
1502
1503        $header    = pack("vv",   $record, $length);
1504        $data      = pack("vvvv", $row, $col, $xf, $strlen);
1505        $this->_append($header . $data . $str);
1506        return($str_error);
1507    }
1508
1509    /**
1510    * Sets Input Encoding for writing strings
1511    *
1512    * @access public
1513    * @param string $encoding The encoding. Ex: 'UTF-16LE', 'utf-8', 'ISO-859-7'
1514    */
1515    function setInputEncoding($encoding)
1516    {
1517         if ($encoding != 'UTF-16LE' && !function_exists('iconv')) {
1518             $this->raiseError("Using an input encoding other than UTF-16LE requires PHP support for iconv");
1519         }
1520         $this->_input_encoding = $encoding;
1521    }
1522
1523    /**
1524    * Write a string to the specified row and column (zero indexed).
1525    * This is the BIFF8 version (no 255 chars limit).
1526    * $format is optional.
1527    * Returns  0 : normal termination
1528    *         -2 : row or column out of range
1529    *         -3 : long string truncated to 255 chars
1530    *
1531    * @access public
1532    * @param integer $row    Zero indexed row
1533    * @param integer $col    Zero indexed column
1534    * @param string  $str    The string to write
1535    * @param mixed   $format The XF format for the cell
1536    * @return integer
1537    */
1538    function writeStringBIFF8($row, $col, $str, $format = 0)
1539    {
1540        if ($this->_input_encoding == 'UTF-16LE')
1541        {
1542            $strlen = function_exists('mb_strlen') ? mb_strlen($str, 'UTF-16LE') : (strlen($str) / 2);
1543            $encoding  = 0x1;
1544        }
1545        elseif ($this->_input_encoding != '')
1546        {
1547            $str = iconv($this->_input_encoding, 'UTF-16LE', $str);
1548            $strlen = function_exists('mb_strlen') ? mb_strlen($str, 'UTF-16LE') : (strlen($str) / 2);
1549            $encoding  = 0x1;
1550        }
1551        else
1552        {
1553            $strlen    = strlen($str);
1554            $encoding  = 0x0;
1555        }
1556        $record    = 0x00FD;                   // Record identifier
1557        $length    = 0x000A;                   // Bytes to follow
1558        $xf        = $this->_XF($format);      // The cell format
1559
1560        $str_error = 0;
1561
1562        // Check that row and col are valid and store max and min values
1563        if ($this->_checkRowCol($row, $col) == false) {
1564            return -2;
1565        }
1566
1567        $str = pack('vC', $strlen, $encoding).$str;
1568
1569        /* check if string is already present */
1570        if (!isset($this->_str_table[$str])) {
1571            $this->_str_table[$str] = $this->_str_unique++;
1572        }
1573        $this->_str_total++;
1574
1575        $header    = pack('vv',   $record, $length);
1576        $data      = pack('vvvV', $row, $col, $xf, $this->_str_table[$str]);
1577        $this->_append($header.$data);
1578        return $str_error;
1579    }
1580
1581    /**
1582    * Check row and col before writing to a cell, and update the sheet's
1583    * dimensions accordingly
1584    *
1585    * @access private
1586    * @param integer $row    Zero indexed row
1587    * @param integer $col    Zero indexed column
1588    * @return boolean true for success, false if row and/or col are grester
1589    *                 then maximums allowed.
1590    */
1591    function _checkRowCol($row, $col)
1592    {
1593        if ($row >= $this->_xls_rowmax) {
1594            return false;
1595        }
1596        if ($col >= $this->_xls_colmax) {
1597            return false;
1598        }
1599        if ($row <  $this->_dim_rowmin) {
1600            $this->_dim_rowmin = $row;
1601        }
1602        if ($row >  $this->_dim_rowmax) {
1603            $this->_dim_rowmax = $row;
1604        }
1605        if ($col <  $this->_dim_colmin) {
1606            $this->_dim_colmin = $col;
1607        }
1608        if ($col >  $this->_dim_colmax) {
1609            $this->_dim_colmax = $col;
1610        }
1611        return true;
1612    }
1613
1614    /**
1615    * Writes a note associated with the cell given by the row and column.
1616    * NOTE records don't have a length limit.
1617    *
1618    * @access public
1619    * @param integer $row    Zero indexed row
1620    * @param integer $col    Zero indexed column
1621    * @param string  $note   The note to write
1622    */
1623    function writeNote($row, $col, $note)
1624    {
1625        $note_length    = strlen($note);
1626        $record         = 0x001C;                // Record identifier
1627        $max_length     = 2048;                  // Maximun length for a NOTE record
1628        //$length      = 0x0006 + $note_length;    // Bytes to follow
1629
1630        // Check that row and col are valid and store max and min values
1631        if ($row >= $this->_xls_rowmax) {
1632            return(-2);
1633        }
1634        if ($col >= $this->_xls_colmax) {
1635            return(-2);
1636        }
1637        if ($row <  $this->_dim_rowmin) {
1638            $this->_dim_rowmin = $row;
1639        }
1640        if ($row >  $this->_dim_rowmax) {
1641            $this->_dim_rowmax = $row;
1642        }
1643        if ($col <  $this->_dim_colmin) {
1644            $this->_dim_colmin = $col;
1645        }
1646        if ($col >  $this->_dim_colmax) {
1647            $this->_dim_colmax = $col;
1648        }
1649
1650        // Length for this record is no more than 2048 + 6
1651        $length    = 0x0006 + min($note_length, 2048);
1652        $header    = pack("vv",   $record, $length);
1653        $data      = pack("vvv", $row, $col, $note_length);
1654        $this->_append($header . $data . substr($note, 0, 2048));
1655
1656        for ($i = $max_length; $i < $note_length; $i += $max_length) {
1657            $chunk  = substr($note, $i, $max_length);
1658            $length = 0x0006 + strlen($chunk);
1659            $header = pack("vv",   $record, $length);
1660            $data   = pack("vvv", -1, 0, strlen($chunk));
1661            $this->_append($header.$data.$chunk);
1662        }
1663        return(0);
1664    }
1665
1666    /**
1667    * Write a blank cell to the specified row and column (zero indexed).
1668    * A blank cell is used to specify formatting without adding a string
1669    * or a number.
1670    *
1671    * A blank cell without a format serves no purpose. Therefore, we don't write
1672    * a BLANK record unless a format is specified.
1673    *
1674    * Returns  0 : normal termination (including no format)
1675    *         -1 : insufficient number of arguments
1676    *         -2 : row or column out of range
1677    *
1678    * @access public
1679    * @param integer $row    Zero indexed row
1680    * @param integer $col    Zero indexed column
1681    * @param mixed   $format The XF format
1682    */
1683    function writeBlank($row, $col, $format)
1684    {
1685        // Don't write a blank cell unless it has a format
1686        if ($format == 0) {
1687            return(0);
1688        }
1689
1690        $record    = 0x0201;                 // Record identifier
1691        $length    = 0x0006;                 // Number of bytes to follow
1692        $xf        = $this->_XF($format);    // The cell format
1693
1694        // Check that row and col are valid and store max and min values
1695        if ($row >= $this->_xls_rowmax) {
1696            return(-2);
1697        }
1698        if ($col >= $this->_xls_colmax) {
1699            return(-2);
1700        }
1701        if ($row <  $this->_dim_rowmin) {
1702            $this->_dim_rowmin = $row;
1703        }
1704        if ($row >  $this->_dim_rowmax) {
1705            $this->_dim_rowmax = $row;
1706        }
1707        if ($col <  $this->_dim_colmin) {
1708            $this->_dim_colmin = $col;
1709        }
1710        if ($col >  $this->_dim_colmax) {
1711            $this->_dim_colmax = $col;
1712        }
1713
1714        $header    = pack("vv",  $record, $length);
1715        $data      = pack("vvv", $row, $col, $xf);
1716        $this->_append($header . $data);
1717        return 0;
1718    }
1719
1720    /**
1721    * Write a formula to the specified row and column (zero indexed).
1722    * The textual representation of the formula is passed to the parser in
1723    * Parser.php which returns a packed binary string.
1724    *
1725    * Returns  0 : normal termination
1726    *         -1 : formula errors (bad formula)
1727    *         -2 : row or column out of range
1728    *
1729    * @access public
1730    * @param integer $row     Zero indexed row
1731    * @param integer $col     Zero indexed column
1732    * @param string  $formula The formula text string
1733    * @param mixed   $format  The optional XF format
1734    * @return integer
1735    */
1736    function writeFormula($row, $col, $formula, $format = 0)
1737    {
1738        $record    = 0x0006;     // Record identifier
1739
1740        // Excel normally stores the last calculated value of the formula in $num.
1741        // Clearly we are not in a position to calculate this a priori. Instead
1742        // we set $num to zero and set the option flags in $grbit to ensure
1743        // automatic calculation of the formula when the file is opened.
1744        //
1745        $xf        = $this->_XF($format); // The cell format
1746        $num      

Large files files are truncated, but you can click here to view the full file