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

Source for file ReferenceHelper.php

Documentation is available at ReferenceHelper.php

  1. <?php
  2. /**
  3.  * PHPExcel
  4.  *
  5.  * Copyright (c) 2006 - 2011 PHPExcel
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with this library; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  20.  *
  21.  * @category   PHPExcel
  22.  * @package    PHPExcel
  23.  * @copyright  Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
  24.  * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
  25.  * @version    1.7.6, 2011-02-27
  26.  */
  27.  
  28.  
  29. /**
  30.  * PHPExcel_ReferenceHelper (Singleton)
  31.  *
  32.  * @category   PHPExcel
  33.  * @package    PHPExcel
  34.  * @copyright  Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
  35.  */
  36. {
  37.     /**    Constants                */
  38.     /**    Regular Expressions        */
  39.     const REFHELPER_REGEXP_CELLREF        '((\w*|\'[^!]*\')!)?(?<![:a-z\$])(\$?[a-z]{1,3}\$?\d+)(?=[^:!\d\'])';
  40.     const REFHELPER_REGEXP_CELLRANGE    '((\w*|\'[^!]*\')!)?(\$?[a-z]{1,3}\$?\d+):(\$?[a-z]{1,3}\$?\d+)';
  41.     const REFHELPER_REGEXP_ROWRANGE        '((\w*|\'[^!]*\')!)?(\$?\d+):(\$?\d+)';
  42.     const REFHELPER_REGEXP_COLRANGE        '((\w*|\'[^!]*\')!)?(\$?[a-z]{1,3}):(\$?[a-z]{1,3})';
  43.  
  44.     /**
  45.      * Instance of this class
  46.      *
  47.      * @var PHPExcel_ReferenceHelper 
  48.      */
  49.     private static $_instance;
  50.  
  51.     /**
  52.      * Get an instance of this class
  53.      *
  54.      * @return PHPExcel_ReferenceHelper 
  55.      */
  56.     public static function getInstance({
  57.         if (!isset(self::$_instance|| is_null(self::$_instance)) {
  58.             self::$_instance new PHPExcel_ReferenceHelper();
  59.         }
  60.  
  61.         return self::$_instance;
  62.     }
  63.  
  64.     /**
  65.      * Create a new PHPExcel_ReferenceHelper
  66.      */
  67.     protected function __construct({
  68.     }
  69.  
  70.     /**
  71.      * Insert a new column, updating all possible related data
  72.      *
  73.      * @param    int    $pBefore    Insert before this one
  74.      * @param    int    $pNumCols    Number of columns to insert
  75.      * @param    int    $pNumRows    Number of rows to insert
  76.      * @throws    Exception
  77.      */
  78.     public function insertNewBefore($pBefore 'A1'$pNumCols 0$pNumRows 0PHPExcel_Worksheet $pSheet null{
  79.         $aCellCollection $pSheet->getCellCollection();
  80.  
  81.         // Get coordinates of $pBefore
  82.         $beforeColumn    'A';
  83.         $beforeRow        1;
  84.         list($beforeColumn$beforeRowPHPExcel_Cell::coordinateFromString$pBefore );
  85.  
  86.  
  87.         // Clear cells if we are removing columns or rows
  88.         $highestColumn    $pSheet->getHighestColumn();
  89.         $highestRow    $pSheet->getHighestRow();
  90.  
  91.         // 1. Clear column strips if we are removing columns
  92.         if ($pNumCols && PHPExcel_Cell::columnIndexFromString($beforeColumn$pNumCols 0{
  93.             for ($i 1$i <= $highestRow 1++$i{
  94.                 for ($j PHPExcel_Cell::columnIndexFromString($beforeColumn$pNumCols$j <= PHPExcel_Cell::columnIndexFromString($beforeColumn2++$j{
  95.                     $coordinate PHPExcel_Cell::stringFromColumnIndex($j$i;
  96.                     $pSheet->removeConditionalStyles($coordinate);
  97.                     if ($pSheet->cellExists($coordinate)) {
  98.                         $pSheet->getCell($coordinate)->setValueExplicit(''PHPExcel_Cell_DataType::TYPE_NULL);
  99.                         $pSheet->getCell($coordinate)->setXfIndex(0);
  100.                     }
  101.                 }
  102.             }
  103.         }
  104.  
  105.         // 2. Clear row strips if we are removing rows
  106.         if ($pNumRows && $beforeRow $pNumRows 0{
  107.             for ($i PHPExcel_Cell::columnIndexFromString($beforeColumn1$i <= PHPExcel_Cell::columnIndexFromString($highestColumn1++$i{
  108.                 for ($j $beforeRow $pNumRows$j <= $beforeRow 1++$j{
  109.                     $coordinate PHPExcel_Cell::stringFromColumnIndex($i$j;
  110.                     $pSheet->removeConditionalStyles($coordinate);
  111.                     if ($pSheet->cellExists($coordinate)) {
  112.                         $pSheet->getCell($coordinate)->setValueExplicit(''PHPExcel_Cell_DataType::TYPE_NULL);
  113.                         $pSheet->getCell($coordinate)->setXfIndex(0);
  114.                     }
  115.                 }
  116.             }
  117.         }
  118.  
  119.  
  120.         // Loop through cells, bottom-up, and change cell coordinates
  121.         while (($cellID ($pNumCols || $pNumRows 0array_shift($aCellCollectionarray_pop($aCellCollection))) {
  122.             $cell $pSheet->getCell($cellID);
  123.  
  124.             // New coordinates
  125.             $newCoordinates PHPExcel_Cell::stringFromColumnIndexPHPExcel_Cell::columnIndexFromString($cell->getColumn()) $pNumCols ($cell->getRow($pNumRows);
  126.  
  127.             // Should the cell be updated? Move value and cellXf index from one cell to another.
  128.             if ((PHPExcel_Cell::columnIndexFromString$cell->getColumn() ) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)) &&
  129.                 ($cell->getRow(>= $beforeRow)) {
  130.  
  131.                 // Update cell styles
  132.                 $pSheet->getCell($newCoordinates)->setXfIndex($cell->getXfIndex());
  133.                 $cell->setXfIndex(0);
  134.  
  135.                 // Insert this cell at its new location
  136.                 if ($cell->getDataType(== PHPExcel_Cell_DataType::TYPE_FORMULA{
  137.                     // Formula should be adjusted
  138.                     $pSheet->getCell($newCoordinates)
  139.                            ->setValue($this->updateFormulaReferences($cell->getValue(),
  140.                                                $pBefore$pNumCols$pNumRows$pSheet->getTitle()));
  141.                 else {
  142.                     // Formula should not be adjusted
  143.                     $pSheet->getCell($newCoordinates)->setValue($cell->getValue());
  144.                 }
  145.  
  146.                 // Clear the original cell
  147.                 $pSheet->getCell($cell->getCoordinate())->setValue('');
  148.  
  149.             else {
  150.                 /*    We don't need to update styles for rows/columns before our insertion position,
  151.                         but we do still need to adjust any formulae    in those cells                    */
  152.                 if ($cell->getDataType(== PHPExcel_Cell_DataType::TYPE_FORMULA{
  153.                     // Formula should be adjusted
  154.                     $cell->setValue($this->updateFormulaReferences($cell->getValue(),
  155.                                         $pBefore$pNumCols$pNumRows$pSheet->getTitle()));
  156.                 }
  157.  
  158.             }
  159.         }
  160.  
  161.  
  162.         // Duplicate styles for the newly inserted cells
  163.         $highestColumn    $pSheet->getHighestColumn();
  164.         $highestRow    $pSheet->getHighestRow();
  165.  
  166.         if ($pNumCols && PHPExcel_Cell::columnIndexFromString($beforeColumn0{
  167.             for ($i $beforeRow$i <= $highestRow 1++$i{
  168.  
  169.                 // Style
  170.                 $coordinate PHPExcel_Cell::stringFromColumnIndexPHPExcel_Cell::columnIndexFromString($beforeColumn$i;
  171.                 if ($pSheet->cellExists($coordinate)) {
  172.                     $xfIndex $pSheet->getCell($coordinate)->getXfIndex();
  173.                     $conditionalStyles $pSheet->conditionalStylesExists($coordinate?
  174.                         $pSheet->getConditionalStyles($coordinatefalse;
  175.                     for ($j PHPExcel_Cell::columnIndexFromString($beforeColumn1$j <= PHPExcel_Cell::columnIndexFromString($beforeColumn$pNumCols++$j{
  176.                         $pSheet->getCellByColumnAndRow($j$i)->setXfIndex($xfIndex);
  177.                         if ($conditionalStyles{
  178.                             $cloned array();
  179.                             foreach ($conditionalStyles as $conditionalStyle{
  180.                                 $cloned[clone $conditionalStyle;
  181.                             }
  182.                             $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($j$i$cloned);
  183.                         }
  184.                     }
  185.                 }
  186.  
  187.             }
  188.         }
  189.  
  190.         if ($pNumRows && $beforeRow 0{
  191.             for ($i PHPExcel_Cell::columnIndexFromString($beforeColumn1$i <= PHPExcel_Cell::columnIndexFromString($highestColumn1++$i{
  192.  
  193.                 // Style
  194.                 $coordinate PHPExcel_Cell::stringFromColumnIndex($i($beforeRow 1);
  195.                 if ($pSheet->cellExists($coordinate)) {
  196.                     $xfIndex $pSheet->getCell($coordinate)->getXfIndex();
  197.                     $conditionalStyles $pSheet->conditionalStylesExists($coordinate?
  198.                         $pSheet->getConditionalStyles($coordinatefalse;
  199.                     for ($j $beforeRow$j <= $beforeRow $pNumRows++$j{
  200.                         $pSheet->getCell(PHPExcel_Cell::stringFromColumnIndex($i$j)->setXfIndex($xfIndex);
  201.                         if ($conditionalStyles{
  202.                             $cloned array();
  203.                             foreach ($conditionalStyles as $conditionalStyle{
  204.                                 $cloned[clone $conditionalStyle;
  205.                             }
  206.                             $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($i$j$cloned);
  207.                         }
  208.                     }
  209.                 }
  210.             }
  211.         }
  212.  
  213.  
  214.         // Update worksheet: column dimensions
  215.         $aColumnDimensions array_reverse($pSheet->getColumnDimensions()true);
  216.         if (count($aColumnDimensions0{
  217.             foreach ($aColumnDimensions as $objColumnDimension{
  218.                 $newReference $this->updateCellReference($objColumnDimension->getColumnIndex('1'$pBefore$pNumCols$pNumRows);
  219.                 list($newReferencePHPExcel_Cell::coordinateFromString($newReference);
  220.                 if ($objColumnDimension->getColumnIndex(!= $newReference{
  221.                     $objColumnDimension->setColumnIndex($newReference);
  222.                 }
  223.             }
  224.             $pSheet->refreshColumnDimensions();
  225.         }
  226.  
  227.  
  228.         // Update worksheet: row dimensions
  229.         $aRowDimensions array_reverse($pSheet->getRowDimensions()true);
  230.         if (count($aRowDimensions0{
  231.             foreach ($aRowDimensions as $objRowDimension{
  232.                 $newReference $this->updateCellReference('A' $objRowDimension->getRowIndex()$pBefore$pNumCols$pNumRows);
  233.                 list($newReferencePHPExcel_Cell::coordinateFromString($newReference);
  234.                 if ($objRowDimension->getRowIndex(!= $newReference{
  235.                     $objRowDimension->setRowIndex($newReference);
  236.                 }
  237.             }
  238.             $pSheet->refreshRowDimensions();
  239.  
  240.             $copyDimension $pSheet->getRowDimension($beforeRow 1);
  241.             for ($i $beforeRow$i <= $beforeRow $pNumRows++$i{
  242.                 $newDimension $pSheet->getRowDimension($i);
  243.                 $newDimension->setRowHeight($copyDimension->getRowHeight());
  244.                 $newDimension->setVisible($copyDimension->getVisible());
  245.                 $newDimension->setOutlineLevel($copyDimension->getOutlineLevel());
  246.                 $newDimension->setCollapsed($copyDimension->getCollapsed());
  247.             }
  248.         }
  249.  
  250.  
  251.         // Update worksheet: breaks
  252.         $aBreaks array_reverse($pSheet->getBreaks()true);
  253.         foreach ($aBreaks as $key => $value{
  254.             $newReference $this->updateCellReference($key$pBefore$pNumCols$pNumRows);
  255.             if ($key != $newReference{
  256.                 $pSheet->setBreak$newReference$value );
  257.                 $pSheet->setBreak$keyPHPExcel_Worksheet::BREAK_NONE );
  258.             }
  259.         }
  260.  
  261.         // Update worksheet: comments
  262.         $aComments $pSheet->getComments();
  263.         $aNewComments array()// the new array of all comments
  264.         foreach ($aComments as $key => &$value{
  265.             $newReference $this->updateCellReference($key$pBefore$pNumCols$pNumRows);
  266.             $aNewComments[$newReference$value;
  267.         }
  268.         $pSheet->setComments($aNewComments)// replace the comments array
  269.  
  270.         // Update worksheet: hyperlinks
  271.         $aHyperlinkCollection array_reverse($pSheet->getHyperlinkCollection()true);
  272.         foreach ($aHyperlinkCollection as $key => $value{
  273.             $newReference $this->updateCellReference($key$pBefore$pNumCols$pNumRows);
  274.             if ($key != $newReference{
  275.                 $pSheet->setHyperlink$newReference$value );
  276.                 $pSheet->setHyperlink$keynull );
  277.             }
  278.         }
  279.  
  280.  
  281.         // Update worksheet: data validations
  282.         $aDataValidationCollection array_reverse($pSheet->getDataValidationCollection()true);
  283.         foreach ($aDataValidationCollection as $key => $value{
  284.             $newReference $this->updateCellReference($key$pBefore$pNumCols$pNumRows);
  285.             if ($key != $newReference{
  286.                 $pSheet->setDataValidation$newReference$value );
  287.                 $pSheet->setDataValidation$keynull );
  288.             }
  289.         }
  290.  
  291.  
  292.         // Update worksheet: merge cells
  293.         $aMergeCells $pSheet->getMergeCells();
  294.         $aNewMergeCells array()// the new array of all merge cells
  295.         foreach ($aMergeCells as $key => &$value{
  296.             $newReference $this->updateCellReference($key$pBefore$pNumCols$pNumRows);
  297.             $aNewMergeCells[$newReference$newReference;
  298.         }
  299.         $pSheet->setMergeCells($aNewMergeCells)// replace the merge cells array
  300.  
  301.  
  302.         // Update worksheet: protected cells
  303.         $aProtectedCells array_reverse($pSheet->getProtectedCells()true);
  304.         foreach ($aProtectedCells as $key => $value{
  305.             $newReference $this->updateCellReference($key$pBefore$pNumCols$pNumRows);
  306.             if ($key != $newReference{
  307.                 $pSheet->protectCells$newReference$valuetrue );
  308.                 $pSheet->unprotectCells$key );
  309.             }
  310.         }
  311.  
  312.  
  313.         // Update worksheet: autofilter
  314.         if ($pSheet->getAutoFilter(!= ''{
  315.             $pSheet->setAutoFilter$this->updateCellReference($pSheet->getAutoFilter()$pBefore$pNumCols$pNumRows) );
  316.         }
  317.  
  318.  
  319.         // Update worksheet: freeze pane
  320.         if ($pSheet->getFreezePane(!= ''{
  321.             $pSheet->freezePane$this->updateCellReference($pSheet->getFreezePane()$pBefore$pNumCols$pNumRows) );
  322.         }
  323.  
  324.  
  325.         // Page setup
  326.         if ($pSheet->getPageSetup()->isPrintAreaSet()) {
  327.             $pSheet->getPageSetup()->setPrintArea$this->updateCellReference($pSheet->getPageSetup()->getPrintArea()$pBefore$pNumCols$pNumRows) );
  328.         }
  329.  
  330.  
  331.         // Update worksheet: drawings
  332.         $aDrawings $pSheet->getDrawingCollection();
  333.         foreach ($aDrawings as $objDrawing{
  334.             $newReference $this->updateCellReference($objDrawing->getCoordinates()$pBefore$pNumCols$pNumRows);
  335.             if ($objDrawing->getCoordinates(!= $newReference{
  336.                 $objDrawing->setCoordinates($newReference);
  337.             }
  338.         }
  339.  
  340.  
  341.         // Update workbook: named ranges
  342.         if (count($pSheet->getParent()->getNamedRanges()) 0{
  343.             foreach ($pSheet->getParent()->getNamedRanges(as $namedRange{
  344.                 if ($namedRange->getWorksheet()->getHashCode(== $pSheet->getHashCode()) {
  345.                     $namedRange->setRange(
  346.                         $this->updateCellReference($namedRange->getRange()$pBefore$pNumCols$pNumRows)
  347.                     );
  348.                 }
  349.             }
  350.         }
  351.  
  352.         // Garbage collect
  353.         $pSheet->garbageCollect();
  354.     }
  355.  
  356.     /**
  357.      * Update references within formulas
  358.      *
  359.      * @param    string    $pFormula    Formula to update
  360.      * @param    int        $pBefore    Insert before this one
  361.      * @param    int        $pNumCols    Number of columns to insert
  362.      * @param    int        $pNumRows    Number of rows to insert
  363.      * @return    string    Updated formula
  364.      * @throws    Exception
  365.      */
  366.     public function updateFormulaReferences($pFormula ''$pBefore 'A1'$pNumCols 0$pNumRows 0$sheetName ''{
  367.         //    Update cell references in the formula
  368.         $formulaBlocks explode('"',$pFormula);
  369.         $i false;
  370.         foreach($formulaBlocks as &$formulaBlock{
  371.             //    Ignore blocks that were enclosed in quotes (alternating entries in the $formulaBlocks array after the explode)
  372.             if ($i !$i{
  373.                 $adjustCount 0;
  374.                 $newCellTokens $cellTokens array();
  375.                 //    Search for row ranges (e.g. 'Sheet1'!3:5 or 3:5) with or without $ absolutes (e.g. $3:5)
  376.                 $matchCount preg_match_all('/'.self::REFHELPER_REGEXP_ROWRANGE.'/i'' '.$formulaBlock.' '$matchesPREG_SET_ORDER);
  377.                 if ($matchCount 0{
  378.                     foreach($matches as $match{
  379.                         $fromString ($match[2''$match[2].'!' '';
  380.                         $fromString .= $match[3].':'.$match[4];
  381.                         $modified3 substr($this->updateCellReference('$A'.$match[3],$pBefore,$pNumCols,$pNumRows),2);
  382.                         $modified4 substr($this->updateCellReference('$A'.$match[4],$pBefore,$pNumCols,$pNumRows),2);
  383.  
  384.                         if ($match[3].':'.$match[4!== $modified3.':'.$modified4{
  385.                             if (($match[2== ''|| (trim($match[2],"'"== $sheetName)) {
  386.                                 $toString ($match[2''$match[2].'!' '';
  387.                                 $toString .= $modified3.':'.$modified4;
  388.                                 //    Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
  389.                                 $column 100000;
  390.                                 $row 10000000+trim($match[3],'$');
  391.                                 $cellIndex $column.$row;
  392.  
  393.                                 $newCellTokens[$cellIndexpreg_quote($toString);
  394.                                 $cellTokens[$cellIndex'/(?<!\d)'.preg_quote($fromString).'(?!\d)/i';
  395.                                 ++$adjustCount;
  396.                             }
  397.                         }
  398.                     }
  399.                 }
  400.                 //    Search for column ranges (e.g. 'Sheet1'!C:E or C:E) with or without $ absolutes (e.g. $C:E)
  401.                 $matchCount preg_match_all('/'.self::REFHELPER_REGEXP_COLRANGE.'/i'' '.$formulaBlock.' '$matchesPREG_SET_ORDER);
  402.                 if ($matchCount 0{
  403.                     foreach($matches as $match{
  404.                         $fromString ($match[2''$match[2].'!' '';
  405.                         $fromString .= $match[3].':'.$match[4];
  406.                         $modified3 substr($this->updateCellReference($match[3].'$1',$pBefore,$pNumCols,$pNumRows),0,-2);
  407.                         $modified4 substr($this->updateCellReference($match[4].'$1',$pBefore,$pNumCols,$pNumRows),0,-2);
  408.  
  409.                         if ($match[3].':'.$match[4!== $modified3.':'.$modified4{
  410.                             if (($match[2== ''|| (trim($match[2],"'"== $sheetName)) {
  411.                                 $toString ($match[2''$match[2].'!' '';
  412.                                 $toString .= $modified3.':'.$modified4;
  413.                                 //    Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
  414.                                 $column PHPExcel_Cell::columnIndexFromString(trim($match[3],'$')) 100000;
  415.                                 $row 10000000;
  416.                                 $cellIndex $column.$row;
  417.  
  418.                                 $newCellTokens[$cellIndexpreg_quote($toString);
  419.                                 $cellTokens[$cellIndex'/(?<![A-Z])'.preg_quote($fromString).'(?![A-Z])/i';
  420.                                 ++$adjustCount;
  421.                             }
  422.                         }
  423.                     }
  424.                 }
  425.                 //    Search for cell ranges (e.g. 'Sheet1'!A3:C5 or A3:C5) with or without $ absolutes (e.g. $A1:C$5)
  426.                 $matchCount preg_match_all('/'.self::REFHELPER_REGEXP_CELLRANGE.'/i'' '.$formulaBlock.' '$matchesPREG_SET_ORDER);
  427.                 if ($matchCount 0{
  428.                     foreach($matches as $match{
  429.                         $fromString ($match[2''$match[2].'!' '';
  430.                         $fromString .= $match[3].':'.$match[4];
  431.                         $modified3 $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows);
  432.                         $modified4 $this->updateCellReference($match[4],$pBefore,$pNumCols,$pNumRows);
  433.  
  434.                         if ($match[3].$match[4!== $modified3.$modified4{
  435.                             if (($match[2== ''|| (trim($match[2],"'"== $sheetName)) {
  436.                                 $toString ($match[2''$match[2].'!' '';
  437.                                 $toString .= $modified3.':'.$modified4;
  438.                                 list($column,$rowPHPExcel_Cell::coordinateFromString($match[3]);
  439.                                 //    Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
  440.                                 $column PHPExcel_Cell::columnIndexFromString(trim($column,'$')) 100000;
  441.                                 $row trim($row,'$'10000000;
  442.                                 $cellIndex $column.$row;
  443.  
  444.                                 $newCellTokens[$cellIndexpreg_quote($toString);
  445.                                 $cellTokens[$cellIndex'/(?<![A-Z])'.preg_quote($fromString).'(?!\d)/i';
  446.                                 ++$adjustCount;
  447.                             }
  448.                         }
  449.                     }
  450.                 }
  451.                 //    Search for cell references (e.g. 'Sheet1'!A3 or C5) with or without $ absolutes (e.g. $A1 or C$5)
  452.                 $matchCount preg_match_all('/'.self::REFHELPER_REGEXP_CELLREF.'/i'' '.$formulaBlock.' '$matchesPREG_SET_ORDER);
  453.                 if ($matchCount 0{
  454.                     foreach($matches as $match{
  455.                         $fromString ($match[2''$match[2].'!' '';
  456.                         $fromString .= $match[3];
  457.                         $modified3 $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows);
  458.  
  459.                         if ($match[3!== $modified3{
  460.                             if (($match[2== ''|| (trim($match[2],"'"== $sheetName)) {
  461.                                 $toString ($match[2''$match[2].'!' '';
  462.                                 $toString .= $modified3;
  463.                                 list($column,$rowPHPExcel_Cell::coordinateFromString($match[3]);
  464.                                 //    Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
  465.                                 $column PHPExcel_Cell::columnIndexFromString(trim($column,'$')) 100000;
  466.                                 $row trim($row,'$'10000000;
  467.                                 $cellIndex $column.$row;
  468.  
  469.                                 $newCellTokens[$cellIndexpreg_quote($toString);
  470.                                 $cellTokens[$cellIndex'/(?<![A-Z])'.preg_quote($fromString).'(?!\d)/i';
  471.                                 ++$adjustCount;
  472.                             }
  473.                         }
  474.                     }
  475.                 }
  476.                 if ($adjustCount 0{
  477.                     krsort($cellTokens);
  478.                     krsort($newCellTokens);
  479.                     //    Update cell references in the formula
  480.                     $formulaBlock str_replace('\\','',preg_replace($cellTokens,$newCellTokens,$formulaBlock));
  481.                 }
  482.             }
  483.         }
  484.         unset($formulaBlock);
  485.  
  486.         //    Then rebuild the formula string
  487.         return implode('"',$formulaBlocks);
  488.     }
  489.  
  490.     /**
  491.      * Update cell reference
  492.      *
  493.      * @param    string    $pCellRange            Cell range
  494.      * @param    int        $pBefore            Insert before this one
  495.      * @param    int        $pNumCols            Number of columns to increment
  496.      * @param    int        $pNumRows            Number of rows to increment
  497.      * @return    string    Updated cell range
  498.      * @throws    Exception
  499.      */
  500.     public function updateCellReference($pCellRange 'A1'$pBefore 'A1'$pNumCols 0$pNumRows 0{
  501.         // Is it in another worksheet? Will not have to update anything.
  502.         if (strpos($pCellRange"!"!== false{
  503.             return $pCellRange;
  504.         // Is it a range or a single cell?
  505.         elseif (strpos($pCellRange':'=== false && strpos($pCellRange','=== false{
  506.             // Single cell
  507.             return $this->_updateSingleCellReference($pCellRange$pBefore$pNumCols$pNumRows);
  508.         elseif (strpos($pCellRange':'!== false || strpos($pCellRange','!== false{
  509.             // Range
  510.             return $this->_updateCellRange($pCellRange$pBefore$pNumCols$pNumRows);
  511.         else {
  512.             // Return original
  513.             return $pCellRange;
  514.         }
  515.     }
  516.  
  517.     /**
  518.      * Update named formulas (i.e. containing worksheet references / named ranges)
  519.      *
  520.      * @param PHPExcel $pPhpExcel    Object to update
  521.      * @param string $oldName        Old name (name to replace)
  522.      * @param string $newName        New name
  523.      */
  524.     public function updateNamedFormulas(PHPExcel $pPhpExcel$oldName ''$newName ''{
  525.         if ($oldName == ''{
  526.             return;
  527.         }
  528.  
  529.         foreach ($pPhpExcel->getWorksheetIterator(as $sheet{
  530.             foreach ($sheet->getCellCollection(falseas $cellID{
  531.                 $cell $sheet->getCell($cellID);
  532.                 if (!is_null($cell&& $cell->getDataType(== PHPExcel_Cell_DataType::TYPE_FORMULA{
  533.                     $formula $cell->getValue();
  534.                     if (strpos($formula$oldName!== false{
  535.                         $formula str_replace("'" $oldName "'!""'" $newName "'!"$formula);
  536.                         $formula str_replace($oldName "!"$newName "!"$formula);
  537.                         $cell->setValueExplicit($formulaPHPExcel_Cell_DataType::TYPE_FORMULA);
  538.                     }
  539.                 }
  540.             }
  541.         }
  542.     }
  543.  
  544.     /**
  545.      * Update cell range
  546.      *
  547.      * @param    string    $pCellRange            Cell range    (e.g. 'B2:D4', 'B:C' or '2:3')
  548.      * @param    int        $pBefore            Insert before this one
  549.      * @param    int        $pNumCols            Number of columns to increment
  550.      * @param    int        $pNumRows            Number of rows to increment
  551.      * @return    string    Updated cell range
  552.      * @throws    Exception
  553.      */
  554.     private function _updateCellRange($pCellRange 'A1:A1'$pBefore 'A1'$pNumCols 0$pNumRows 0{
  555.         if (strpos($pCellRange,':'!== false || strpos($pCellRange','!== false{
  556.             // Update range
  557.             $range PHPExcel_Cell::splitRange($pCellRange);
  558.             $ic count($range);
  559.             for ($i 0$i $ic++$i{
  560.                 $jc count($range[$i]);
  561.                 for ($j 0$j $jc++$j{
  562.                     if (ctype_alpha($range[$i][$j])) {
  563.                         $r PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference($range[$i][$j].'1'$pBefore$pNumCols$pNumRows));
  564.                         $range[$i][$j$r[0];
  565.                     elseif(ctype_digit($range[$i][$j])) {
  566.                         $r PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference('A'.$range[$i][$j]$pBefore$pNumCols$pNumRows));
  567.                         $range[$i][$j$r[1];
  568.                     else {
  569.                         $range[$i][$j$this->_updateSingleCellReference($range[$i][$j]$pBefore$pNumCols$pNumRows);
  570.                     }
  571.                 }
  572.             }
  573.  
  574.             // Recreate range string
  575.             return PHPExcel_Cell::buildRange($range);
  576.         else {
  577.             throw new Exception("Only cell ranges may be passed to this method.");
  578.         }
  579.     }
  580.  
  581.     /**
  582.      * Update single cell reference
  583.      *
  584.      * @param    string    $pCellReference        Single cell reference
  585.      * @param    int        $pBefore            Insert before this one
  586.      * @param    int        $pNumCols            Number of columns to increment
  587.      * @param    int        $pNumRows            Number of rows to increment
  588.      * @return    string    Updated cell reference
  589.      * @throws    Exception
  590.      */
  591.     private function _updateSingleCellReference($pCellReference 'A1'$pBefore 'A1'$pNumCols 0$pNumRows 0{
  592.         if (strpos($pCellReference':'=== false && strpos($pCellReference','=== false{
  593.             // Get coordinates of $pBefore
  594.             list($beforeColumn$beforeRowPHPExcel_Cell::coordinateFromString$pBefore );
  595.  
  596.             // Get coordinates of $pCellReference
  597.             list($newColumn$newRowPHPExcel_Cell::coordinateFromString$pCellReference );
  598.  
  599.             // Verify which parts should be updated
  600.             $updateColumn (($newColumn{0!= '$'&& ($beforeColumn{0!= '$'&&
  601.                              PHPExcel_Cell::columnIndexFromString($newColumn>= PHPExcel_Cell::columnIndexFromString($beforeColumn));
  602.  
  603.             $updateRow (($newRow{0!= '$'&& ($beforeRow{0!= '$'&&
  604.                           $newRow >= $beforeRow);
  605.  
  606.             // Create new column reference
  607.             if ($updateColumn{
  608.                 $newColumn    PHPExcel_Cell::stringFromColumnIndexPHPExcel_Cell::columnIndexFromString($newColumn$pNumCols );
  609.             }
  610.  
  611.             // Create new row reference
  612.             if ($updateRow{
  613.                 $newRow    $newRow $pNumRows;
  614.             }
  615.  
  616.             // Return new reference
  617.             return $newColumn $newRow;
  618.         else {
  619.             throw new Exception("Only single cell references may be passed to this method.");
  620.         }
  621.     }
  622.  
  623.     /**
  624.      * __clone implementation. Cloning should not be allowed in a Singleton!
  625.      *
  626.      * @throws    Exception
  627.      */
  628.     public final function __clone({
  629.         throw new Exception("Cloning a Singleton is not allowed!");
  630.     }
  631. }

Documentation generated on Sun, 27 Feb 2011 16:33:41 -0800 by phpDocumentor 1.4.3